Skip to content

Commit

Permalink
Add Drag Across Axis Functionality to Vis Builder
Browse files Browse the repository at this point in the history
Signed-off-by: Suchit Sahoo <suchsah@amazon.com>
  • Loading branch information
LDrago27 committed Jul 9, 2024
1 parent e74ed2c commit 5b7a9e3
Show file tree
Hide file tree
Showing 19 changed files with 851 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,49 @@

import { EuiForm } from '@elastic/eui';
import React from 'react';
import { useVisualizationType } from '../../utils/use';
import { useTypedSelector } from '../../utils/state_management';

import './config_panel.scss';
import { mapSchemaToAggPanel } from './schema_to_dropbox';
import { SecondaryPanel } from './secondary_panel';
import { Schemas } from '../../../../../vis_default_editor/public';
import {
AggConfig,
AggConfigs,
CreateAggConfigParams,
} from '../../../../../data/common/search/aggs';
import { IndexPattern, TimeRange } from '../../../../../data/public';
import { SchemaDisplayStates } from '.';

export function ConfigPanel() {
const vizType = useVisualizationType();
const editingState = useTypedSelector(
(state) => state.visualization.activeVisualization?.draftAgg
);
const schemas = vizType.ui.containerConfig.data.schemas;
export interface AggProps {
indexPattern: IndexPattern | undefined;
aggConfigs: AggConfigs | undefined;
aggs: AggConfig[];
timeRange: TimeRange;
}

export interface ConfigPanelProps {
schemas: Schemas;
editingState?: CreateAggConfigParams;
aggProps: AggProps;
activeSchemaFields: SchemaDisplayStates;
setActiveSchemaFields: React.Dispatch<React.SetStateAction<SchemaDisplayStates>>;
}

export function ConfigPanel({
schemas,
editingState,
aggProps,
activeSchemaFields,
setActiveSchemaFields,
}: ConfigPanelProps) {
if (!schemas) return null;

const mainPanel = mapSchemaToAggPanel(schemas);
const mainPanel = mapSchemaToAggPanel(
schemas,
aggProps,
activeSchemaFields,
setActiveSchemaFields
);

return (
<EuiForm className={`vbConfig ${editingState ? 'showSecondary' : ''}`}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export enum FIELD_SELECTOR_ID {
COUNT = 'preDefinedCountMetric',
CATEGORICAL = 'categoricalFields',
NUMERICAL = 'numericalFields',
META = 'metaFields',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { DropResult } from '@elastic/eui';
import { AnyAction } from 'redux';
import { createNewAggConfig } from '../utils/get_valid_aggregations';
import { updateAggConfigParams } from '../../../utils/state_management/visualization_slice';
import { Schemas } from '../../../../../../vis_default_editor/public';
import { AggProps } from '../config_panel';
import { SchemaDisplayStates } from '../index';
import { Dispatch } from '../../../../../../opensearch_dashboards_utils/common/state_containers/types';
import { AggsStart } from '../../../../../../data/common';

export interface DragDropProperties {
dropResult: DropResult;
schemas: Schemas;
aggProps: AggProps;
aggService: AggsStart;
activeSchemaFields: SchemaDisplayStates;
dispatch: Dispatch<AnyAction>;
}

export function addFieldToConfiguration({
dropResult,
schemas,
aggProps,
aggService,
activeSchemaFields,
dispatch,
}: DragDropProperties) {
const { source, destination, combine, draggableId } = dropResult;

const destinationSchemaName = destination?.droppableId;
const destinationSchema = schemas.all.find((schema) => schema.name === destinationSchemaName);

const newFieldToAdd = draggableId;

if (!destinationSchema || !destinationSchemaName) {
// Invalid drop target selected
return;
}

const destinationFields = activeSchemaFields[destinationSchemaName];

if (!combine && destination && destinationFields.length >= destinationSchema?.max) {
// Can't Add additional Fields
return;
}

// Adding the new field
createNewAggConfig({
fieldName: newFieldToAdd,
sourceGroup: source.droppableId,
destinationSchema,
aggProps,
aggService,
sourceAgg: null,
});

const updatedAggConfigs = aggProps.aggConfigs?.aggs;

if (updatedAggConfigs) {
dispatch(updateAggConfigParams(updatedAggConfigs.map((agg) => agg.serialize())));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { updateAggConfigParams } from '../../../utils/state_management/visualization_slice';
import { createNewAggConfig } from '../utils/get_valid_aggregations';
import { DragDropProperties } from './add_field_to_configuration';

export function moveFieldBetweenSchemas({
dropResult,
schemas,
aggProps,
aggService,
activeSchemaFields,
dispatch,
}: DragDropProperties) {
const { source, destination, combine, draggableId } = dropResult;

const destinationSchemaName = destination?.droppableId;
if (!destinationSchemaName) {
// Invalid Transition
return;
}
const sourceAggId = draggableId;

const destinationSchema = schemas.all.find(
(schema) => schema.name === (destination?.droppableId || combine?.droppableId)
);

if (!destinationSchema) {
// Invalid Transition
return;
}

const sourceAgg = aggProps.aggConfigs?.aggs.find((agg) => agg.id === sourceAggId);
const sourceFieldName = sourceAgg?.fieldName();

const destinationAggFields = activeSchemaFields[destinationSchemaName];

const destinationLimit = destinationSchema?.max;

if (destinationLimit && destinationAggFields.length <= destinationLimit) {
// destination schema has space for more items to be added
// We Need to update sourceAgg

createNewAggConfig({
fieldName: sourceFieldName,
sourceGroup: source.droppableId,
destinationSchema,
aggProps,
aggService,
sourceAgg,
});

// Remove the sourceAggConfig from the updated Config
const updatedAggConfig = aggProps.aggConfigs?.aggs.filter((agg) => agg.id !== sourceAggId);

if (updatedAggConfig?.length) {
dispatch(updateAggConfigParams(updatedAggConfig.map((agg) => agg.serialize())));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { reorderAgg } from '../../../utils/state_management/visualization_slice';
import { DragDropProperties } from './add_field_to_configuration';

export function reorderFieldsWithinSchema({
dropResult,
schemas,
activeSchemaFields,
dispatch,
}: DragDropProperties) {
const { destination, draggableId } = dropResult;

const destinationSchemaName = destination?.droppableId;
if (!destinationSchemaName) {
// Invalid Transition
return;
}
const destinationAggFields = activeSchemaFields[destinationSchemaName];

const sourceAggId = draggableId;
const destinationAggId = destinationAggFields[destination?.index].id;

const destinationSchema = schemas.all.find((schema) => schema.name === destination?.droppableId);

if (!destinationSchema) {
// Invalid Transition
return;
}

dispatch(
reorderAgg({
sourceId: sourceAggId,
destinationId: destinationAggId,
})
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { updateAggConfigParams } from '../../../utils/state_management/visualization_slice';
import { FIELD_SELECTOR_ID } from '../constants';
import { createNewAggConfig } from '../utils/get_valid_aggregations';
import { DragDropProperties } from './add_field_to_configuration';

export function replaceFieldInConfiguration({
dropResult,
schemas,
aggProps,
aggService,
dispatch,
}: DragDropProperties) {
const { source, combine, draggableId } = dropResult;

const destinationSchemaName = combine?.droppableId;
if (!destinationSchemaName) {
return;
}

const sourceAggId = draggableId;
const destinationAggId = combine?.draggableId;

const destinationSchema = schemas.all.find((schema) => schema.name === combine?.droppableId);

if (!destinationSchema) {
// Invalid Transition
return;
}

const sourceSchema = source.droppableId;

if (Object.values(FIELD_SELECTOR_ID).includes(sourceSchema as FIELD_SELECTOR_ID)) {
// Replacing an exisitng configuration with a new field from field selector panel

const newFieldToAdd = draggableId;
createNewAggConfig({
fieldName: newFieldToAdd,
sourceGroup: source.droppableId,
destinationSchema,
aggProps,
aggService,
sourceAgg: null,
});

// Removing the exisiting destination Aggregation
const updatedAggConfig = aggProps.aggConfigs?.aggs.filter((agg) => agg.id !== destinationAggId);

if (updatedAggConfig) {
dispatch(updateAggConfigParams(updatedAggConfig.map((agg) => agg.serialize())));
}
} else {
// Replacing an existing configuration with another exisiting configuration

const sourceAgg = aggProps.aggConfigs?.aggs.find((agg) => agg.id === sourceAggId);
const sourceFieldName = sourceAgg?.fieldName();

createNewAggConfig({
fieldName: sourceFieldName,
sourceGroup: source.droppableId,
destinationSchema,
aggProps,
aggService,
sourceAgg,
});

// Removing the exisiting destination and source Aggregation
const updatedAggConfig = aggProps.aggConfigs?.aggs.filter(
(agg) => agg.id !== destinationAggId && agg.id !== sourceAggId
);

if (updatedAggConfig) {
dispatch(updateAggConfigParams(updatedAggConfig.map((agg) => agg.serialize())));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
border-bottom: none;
}

&__droppable {
min-height: 1px;
}

&__container {
display: grid;
grid-gap: calc($euiSizeXS / 2);
Expand Down
Loading

0 comments on commit 5b7a9e3

Please sign in to comment.