From 00dd1a5460b07f158d69877886d20d12b4a22662 Mon Sep 17 00:00:00 2001
From: Myriam Gantner <48029745+MGJamJam@users.noreply.github.com>
Date: Wed, 8 May 2024 11:11:49 +0200
Subject: [PATCH] Feat/AN-4112 implement order by selection (#69)
* implements license fetching and interval selection
* add tests for intervalUtils
* fix ceiling of timestamp for DAY interval
* add tests
* fix linting
* delete unnecessary export of enum
* implement metric selection
* implement dimension selection
* fix linting errors
* add metric support
* add metric to query and check for null instead of undefined
* implements groupBy selection
* fix linting
* implements reordering of GroupBys and fixes position of Add Button
* make props readonly
* implements order By selection
* splits orderBy state into two seperate states to fix rendering and renames variables
* lint
---
.../src/components/GroupByRow.tsx | 6 +-
.../src/components/OrderByInput.tsx | 63 +++++++++
.../src/components/OrderByRow.tsx | 121 ++++++++++++++++++
.../src/components/QueryEditor.tsx | 10 ++
.../src/datasource.ts | 13 +-
bitmovin-analytics-datasource/src/types.ts | 2 +
.../src/types/queryOrderBy.ts | 9 ++
7 files changed, 211 insertions(+), 13 deletions(-)
create mode 100644 bitmovin-analytics-datasource/src/components/OrderByInput.tsx
create mode 100644 bitmovin-analytics-datasource/src/components/OrderByRow.tsx
create mode 100644 bitmovin-analytics-datasource/src/types/queryOrderBy.ts
diff --git a/bitmovin-analytics-datasource/src/components/GroupByRow.tsx b/bitmovin-analytics-datasource/src/components/GroupByRow.tsx
index b6e7772..2ff83a8 100644
--- a/bitmovin-analytics-datasource/src/components/GroupByRow.tsx
+++ b/bitmovin-analytics-datasource/src/components/GroupByRow.tsx
@@ -61,12 +61,12 @@ export function GroupByRow(props: Props) {
};
const addGroupByInput = () => {
- setSelectedGroupBys((prevState) => [...prevState, { name: '', label: '' }]);
+ setSelectedGroupBys((prevState) => [...prevState, {}]);
};
return (
- {selectedGroupBys?.map((item, index, groupBys) => (
+ {selectedGroupBys.map((item, index, groupBys) => (
))}
- addGroupByInput()} size="xxl" />
+ addGroupByInput()} size="xl" />
);
diff --git a/bitmovin-analytics-datasource/src/components/OrderByInput.tsx b/bitmovin-analytics-datasource/src/components/OrderByInput.tsx
new file mode 100644
index 0000000..033a3fc
--- /dev/null
+++ b/bitmovin-analytics-datasource/src/components/OrderByInput.tsx
@@ -0,0 +1,63 @@
+import React from 'react';
+import { SelectableValue } from '@grafana/data';
+import { HorizontalGroup, IconButton, RadioButtonGroup, Select } from '@grafana/ui';
+
+import { QueryAttribute } from '../types/queryAttributes';
+import { QueryAdAttribute } from '../types/queryAdAttributes';
+import { QuerySortOrder } from '../types/queryOrderBy';
+import { REORDER_DIRECTION } from './GroupByInput';
+
+type Props = {
+ readonly isAdAnalytics: boolean;
+ readonly attribute: SelectableValue;
+ readonly selectableOrderByAttributes: Array>;
+ readonly onAttributeChange: (newValue: SelectableValue) => void;
+ readonly sortOrder: QuerySortOrder;
+ readonly onSortOrderChange: (newValue: QuerySortOrder) => void;
+ readonly onDelete: () => void;
+ readonly isFirst: boolean;
+ readonly isLast: boolean;
+ readonly onReorderOrderBy: (direction: REORDER_DIRECTION) => void;
+};
+
+const sortOrderOption: Array> = [
+ { value: 'ASC', description: 'Sort by ascending', icon: 'sort-amount-up' },
+ { value: 'DESC', description: 'Sort by descending', icon: 'sort-amount-down' },
+];
+
+export function OrderByInput(props: Props) {
+ return (
+
+
+ );
+}
diff --git a/bitmovin-analytics-datasource/src/components/OrderByRow.tsx b/bitmovin-analytics-datasource/src/components/OrderByRow.tsx
new file mode 100644
index 0000000..9067925
--- /dev/null
+++ b/bitmovin-analytics-datasource/src/components/OrderByRow.tsx
@@ -0,0 +1,121 @@
+import React, { useState } from 'react';
+import { Box, IconButton, VerticalGroup } from '@grafana/ui';
+import { SelectableValue } from '@grafana/data';
+import { difference } from 'lodash';
+
+import { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';
+import { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';
+import { QueryOrderBy, QuerySortOrder } from '../types/queryOrderBy';
+import { OrderByInput } from './OrderByInput';
+import { REORDER_DIRECTION } from './GroupByInput';
+
+type Props = {
+ readonly isAdAnalytics: boolean;
+ readonly onChange: (newOrderBy: QueryOrderBy[]) => void;
+};
+
+export function OrderByRow(props: Props) {
+ const [selectedAttributes, setSelectedAttributes] = useState<
+ Array>
+ >([]);
+ const [selectedSortOrders, setSelectedSortOrders] = useState([]);
+
+ const mapOrderBysToSelectableValue = (): Array> => {
+ if (props.isAdAnalytics) {
+ return difference(SELECTABLE_QUERY_AD_ATTRIBUTES, selectedAttributes);
+ } else {
+ return difference(SELECTABLE_QUERY_ATTRIBUTES, selectedAttributes);
+ }
+ };
+
+ const mapSelectedValuesToQueryOrderBy = (
+ selectedAttributes: Array>,
+ selectedSortOrders: QuerySortOrder[]
+ ): QueryOrderBy[] => {
+ const queryOrderBys: QueryOrderBy[] = [];
+ for (let i = 0; i < selectedAttributes.length; i++) {
+ queryOrderBys.push({
+ name: selectedAttributes[i].value!,
+ order: selectedSortOrders[i],
+ });
+ }
+ return queryOrderBys;
+ };
+
+ const deleteOrderByInput = (index: number) => {
+ const newSelectedAttributes = [...selectedAttributes];
+ newSelectedAttributes.splice(index, 1);
+
+ const newSelectedSortOrders = [...selectedSortOrders];
+ newSelectedSortOrders.splice(index, 1);
+
+ setSelectedAttributes(newSelectedAttributes);
+ setSelectedSortOrders(newSelectedSortOrders);
+ props.onChange(mapSelectedValuesToQueryOrderBy(newSelectedAttributes, newSelectedSortOrders));
+ };
+
+ const onAttributesChange = (index: number, newAttribute: SelectableValue) => {
+ const newSelectedAttributes = [...selectedAttributes];
+ newSelectedAttributes.splice(index, 1, newAttribute);
+ setSelectedAttributes(newSelectedAttributes);
+
+ props.onChange(mapSelectedValuesToQueryOrderBy(newSelectedAttributes, selectedSortOrders));
+ };
+
+ const onSortOrdersChange = (index: number, newSortOrder: QuerySortOrder) => {
+ const newSelectedSortOrders = [...selectedSortOrders];
+ newSelectedSortOrders.splice(index, 1, newSortOrder);
+ setSelectedSortOrders(newSelectedSortOrders);
+
+ props.onChange(mapSelectedValuesToQueryOrderBy(selectedAttributes, newSelectedSortOrders));
+ };
+
+ const reorderOrderBy = (direction: REORDER_DIRECTION, index: number) => {
+ const newIndex = direction === REORDER_DIRECTION.UP ? index - 1 : index + 1;
+
+ const newSelectedAttributes = [...selectedAttributes];
+ const attributeToMove = newSelectedAttributes[index];
+ newSelectedAttributes.splice(index, 1);
+ newSelectedAttributes.splice(newIndex, 0, attributeToMove);
+
+ const newSelectedSortOrders = [...selectedSortOrders];
+ const sortOrderToMove = newSelectedSortOrders[index];
+ newSelectedSortOrders.splice(index, 1);
+ newSelectedSortOrders.splice(newIndex, 0, sortOrderToMove);
+
+ setSelectedAttributes(newSelectedAttributes);
+ setSelectedSortOrders(newSelectedSortOrders);
+
+ props.onChange(mapSelectedValuesToQueryOrderBy(newSelectedAttributes, newSelectedSortOrders));
+ };
+ const addOrderByInput = () => {
+ setSelectedAttributes((prevState) => [...prevState, {}]);
+ setSelectedSortOrders((prevState) => [...prevState, 'ASC']);
+ };
+
+ return (
+
+ {selectedAttributes.map((attribute, index, array) => (
+ ) =>
+ onAttributesChange(index, newValue)
+ }
+ sortOrder={selectedSortOrders[index]}
+ onSortOrderChange={(newValue: QuerySortOrder) => onSortOrdersChange(index, newValue)}
+ onDelete={() => deleteOrderByInput(index)}
+ isFirst={index === 0}
+ isLast={index === array.length - 1}
+ onReorderOrderBy={(direction: REORDER_DIRECTION) => reorderOrderBy(direction, index)}
+ />
+ ))}
+
+
+ addOrderByInput()} size="xl" />
+
+
+ );
+}
diff --git a/bitmovin-analytics-datasource/src/components/QueryEditor.tsx b/bitmovin-analytics-datasource/src/components/QueryEditor.tsx
index c6c0c52..d324b75 100644
--- a/bitmovin-analytics-datasource/src/components/QueryEditor.tsx
+++ b/bitmovin-analytics-datasource/src/components/QueryEditor.tsx
@@ -11,6 +11,8 @@ import { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/query
import { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';
import { isMetric, SELECTABLE_METRICS } from '../types/metric';
import { GroupByRow } from './GroupByRow';
+import { OrderByRow } from './OrderByRow';
+import { QueryOrderBy } from '../types/queryOrderBy';
enum LoadingState {
Default = 'DEFAULT',
@@ -67,6 +69,11 @@ export function QueryEditor({ query, onChange, onRunQuery, datasource }: Props)
onRunQuery();
};
+ const onOrderByChange = (newOrderBys: QueryOrderBy[]) => {
+ onChange({ ...query, orderBy: newOrderBys });
+ onRunQuery();
+ };
+
const onFormatAsTimeSeriesChange = (event: ChangeEvent) => {
setIsTimeSeries(event.currentTarget.checked);
if (event.currentTarget.checked) {
@@ -140,6 +147,9 @@ export function QueryEditor({ query, onChange, onRunQuery, datasource }: Props)
+
+
+
diff --git a/bitmovin-analytics-datasource/src/datasource.ts b/bitmovin-analytics-datasource/src/datasource.ts
index a23f5a4..6211340 100644
--- a/bitmovin-analytics-datasource/src/datasource.ts
+++ b/bitmovin-analytics-datasource/src/datasource.ts
@@ -16,12 +16,12 @@ import { QueryAttribute } from './types/queryAttributes';
import { QueryAdAttribute } from './types/queryAdAttributes';
import { Metric } from './types/metric';
import { Aggregation } from './types/aggregations';
-
+import { QueryOrderBy } from './types/queryOrderBy';
type AnalyticsQuery = {
filters: Array<{ name: string; operator: string; value: number }>;
groupBy: QueryAttribute[] | QueryAdAttribute[];
- orderBy: Array<{ name: string; order: string }>;
+ orderBy: QueryOrderBy[];
dimension?: QueryAttribute | QueryAdAttribute;
metric?: Metric;
start: Date;
@@ -73,14 +73,7 @@ export class DataSource extends DataSourceApi = {};
diff --git a/bitmovin-analytics-datasource/src/types/queryOrderBy.ts b/bitmovin-analytics-datasource/src/types/queryOrderBy.ts
new file mode 100644
index 0000000..2b146c4
--- /dev/null
+++ b/bitmovin-analytics-datasource/src/types/queryOrderBy.ts
@@ -0,0 +1,9 @@
+import { QueryAttribute } from './queryAttributes';
+import { QueryAdAttribute } from './queryAdAttributes';
+
+export type QuerySortOrder = 'ASC' | 'DESC';
+
+export type QueryOrderBy = {
+ name: QueryAttribute | QueryAdAttribute;
+ order: QuerySortOrder;
+};