Skip to content

Commit

Permalink
Support edit transformation name (opensearch-project#27)
Browse files Browse the repository at this point in the history
Support edit transformation name
  • Loading branch information
annie3431 authored Jun 25, 2021
1 parent 2fb5f94 commit 54b4c8f
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 12 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"devDependencies": {
"@elastic/elastic-eslint-config-kibana": "link:../../packages/opensearch-eslint-config-opensearch-dashboards",
"@elastic/eslint-import-resolver-kibana": "link:../../packages/osd-eslint-import-resolver-opensearch-dashboards",
"@testing-library/dom": "^7.24.2",
"@testing-library/user-event": "^13.1.9",
"@types/react-dom": "^16.9.8",
"@types/react-router-dom": "^5.1.5",
"cypress": "^6.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface DefineTransformsProps {
selectedAggregations: any;
aggList: TransformAggItem[];
onAggregationSelectionChange: (selectedFields: any, aggItem: TransformAggItem) => void;
onEditTransformation: (oldName: string, newName: string) => void;
onRemoveTransformation: (name: string) => void;
previewTransform: any[];
isReadOnly: boolean;
Expand All @@ -46,6 +47,7 @@ export default function DefineTransforms({
selectedAggregations,
aggList,
onAggregationSelectionChange,
onEditTransformation,
onRemoveTransformation,
previewTransform,
isReadOnly,
Expand Down Expand Up @@ -192,6 +194,7 @@ export default function DefineTransforms({
<PreviewTransform
previewTransform={previewTransform}
aggList={aggList}
onEditTransformation={onEditTransformation}
onRemoveTransformation={onRemoveTransformation}
isReadOnly={isReadOnly}
/>
Expand Down Expand Up @@ -242,6 +245,7 @@ export default function DefineTransforms({
<PreviewTransform
previewTransform={previewTransform}
aggList={aggList}
onEditTransformation={onEditTransformation}
onRemoveTransformation={onRemoveTransformation}
isReadOnly={isReadOnly}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import React, { useState } from "react";
import { EuiButton, EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiPanel, EuiSpacer, EuiText } from "@elastic/eui";
import { TransformAggItem } from "../../../../../../../models/interfaces";

interface EditTransformPanelProps {
name: string;
aggList: TransformAggItem[];
onEditTransformation: (oldName: string, newName: string) => void;
closePopover: () => void;
}

export default function EditTransformPanel({ name, aggList, onEditTransformation, closePopover }: EditTransformPanelProps) {
const [transformName, setTransformName] = useState(name);
const [transformNameError, setTransformNameError] = useState("");

// Function to check if newName is already used
const validateName = (newName: string) => {
const isDuplicate = aggList.some((item) => {
return item.name === newName;
});

if (name !== newName && isDuplicate) setTransformNameError(`Transformation with name "${newName}" already exists`);
else setTransformNameError("");
};

return (
<EuiPanel>
<EuiFormRow label="Transformation name" isInvalid={transformNameError !== ""} error={transformNameError}>
<EuiFieldText
value={transformName}
isInvalid={transformNameError !== ""}
onChange={(e) => {
validateName(e.target.value);
setTransformName(e.target.value);
}}
/>
</EuiFormRow>
<EuiSpacer size="s" />
<EuiFlexGroup justifyContent={"flexEnd"} gutterSize={"m"}>
<EuiFlexItem grow={false}>
<EuiButton fullWidth={false} onClick={() => closePopover()} style={{ minWidth: 84 }}>
Cancel
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
fullWidth={false}
disabled={transformNameError !== ""}
onClick={() => {
// Update transform name if new value specified
if (name !== transformName) onEditTransformation(name, transformName);
closePopover();
}}
style={{ minWidth: 55 }}
>
OK
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import EditTransformPanel from "./EditTransformPanel";

export default EditTransformPanel;
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,34 @@ import {
EuiToolTip,
} from "@elastic/eui";
import { useState } from "react";
import EditTransformPanel from "./Panels/EditTransformPanel";
import { TransformAggItem } from "../../../../../models/interfaces";

interface PreviewOptionsProps {
name: string;
aggList: TransformAggItem[];
onEditTransformation: (oldName: string, newName: string) => void;
onRemoveTransformation: (name: string) => void;
}

export default function PreviewOptions({ name, onRemoveTransformation }: PreviewOptionsProps) {
export default function PreviewOptions({ name, aggList, onEditTransformation, onRemoveTransformation }: PreviewOptionsProps) {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);

const closePopover = () => {
setIsPopoverOpen(false);
};

const button = <EuiButtonIcon color="danger" iconType="crossInACircleFilled" onClick={() => setIsPopoverOpen(!isPopoverOpen)} />;
const button = <EuiButtonIcon color="primary" iconType="pencil" onClick={() => setIsPopoverOpen(!isPopoverOpen)} />;

const panels: EuiContextMenuPanelDescriptor[] = [
{
id: 0,
title: "",
items: [
{
name: "Edit transformation",
panel: 1,
},
{
name: "Remove transformation",
onClick: () => {
Expand All @@ -50,6 +58,11 @@ export default function PreviewOptions({ name, onRemoveTransformation }: Preview
},
],
},
{
id: 1,
title: "Back",
content: <EditTransformPanel name={name} aggList={aggList} onEditTransformation={onEditTransformation} closePopover={closePopover} />,
},
];

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,18 @@ import { renderTime } from "../../../Transforms/utils/helpers";
interface PreviewTransformProps {
previewTransform: any[];
aggList: TransformAggItem[];
onEditTransformation: (oldName: string, newName: string) => void;
onRemoveTransformation: (name: string) => void;
isReadOnly: boolean;
}

export default function PreviewTransform({ previewTransform, aggList, onRemoveTransformation, isReadOnly }: PreviewTransformProps) {
export default function PreviewTransform({
previewTransform,
aggList,
onEditTransformation,
onRemoveTransformation,
isReadOnly,
}: PreviewTransformProps) {
const [previewColumns, setPreviewColumns] = useState<EuiDataGridColumn[]>([]);
const [visiblePreviewColumns, setVisiblePreviewColumns] = useState(() => previewColumns.map(({ id }) => id).slice(0, 5));

Expand Down Expand Up @@ -79,7 +86,14 @@ export default function PreviewTransform({ previewTransform, aggList, onRemoveTr
aggList.map((aggItem) => {
tempCol.push({
id: aggItem.name,
display: <PreviewOptions name={aggItem.name} onRemoveTransformation={onRemoveTransformation} />,
display: (
<PreviewOptions
name={aggItem.name}
aggList={aggList}
onEditTransformation={onEditTransformation}
onRemoveTransformation={onRemoveTransformation}
/>
),
actions: {
showHide: false,
showMoveLeft: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { getErrorMessage } from "../../../../utils/helpers";
import { EMPTY_TRANSFORM } from "../../utils/constants";
import SpecifyScheduleStep from "../SpecifyScheduleStep";
import ReviewAndCreateStep from "../ReviewAndCreateStep";
import { compareFieldItem, createdTransformToastMessage, parseFieldOptions } from "../../utils/helpers";
import { compareFieldItem, createdTransformToastMessage, isGroupBy, parseFieldOptions } from "../../utils/helpers";
import { CoreServicesContext } from "../../../../components/core_services";

interface CreateTransformFormProps extends RouteComponentProps {
Expand Down Expand Up @@ -167,14 +167,20 @@ export default class CreateTransformForm extends Component<CreateTransformFormPr
}
};

previewTransform = async (transform: any): Promise<void> => {
previewTransform = async (transform: any): Promise<boolean> => {
try {
const { transformService } = this.props;
const previewResponse = await transformService.previewTransform(transform);
if (previewResponse.ok) this.setState({ previewTransform: previewResponse.response.documents });
else this.context.notifications.toasts.addDanger(`Could not preview transform: ${previewResponse.error}`);
if (previewResponse.ok) {
this.setState({ previewTransform: previewResponse.response.documents });
return true;
} else {
this.context.notifications.toasts.addDanger(`Could not preview transform: ${previewResponse.error}`);
return false;
}
} catch (err) {
this.context.notifications.toasts.addDanger(getErrorMessage(err, "Could not load preview transform"));
return false;
}
};

Expand Down Expand Up @@ -302,18 +308,45 @@ export default class CreateTransformForm extends Component<CreateTransformFormPr
const { aggList } = this.state;
aggList.push(aggItem);
this.updateGroup();
const previewSuccess = await this.previewTransform(this.state.transformJSON);

await this.previewTransform(this.state.transformJSON);
this.setState({ selectedGroupField });
// If preview successfully update groupings, else remove from list of transformation
if (previewSuccess) this.setState({ selectedGroupField });
else await this.onRemoveTransformation(aggItem.name);
};

onAggregationSelectionChange = async (selectedAggregations: any, aggItem: TransformAggItem): Promise<void> => {
const { aggList } = this.state;
aggList.push(aggItem);
this.updateAggregation();
const previewSuccess = await this.previewTransform(this.state.transformJSON);

// If preview successfully update aggregations, else remove from list of transformation
if (previewSuccess) this.setState({ selectedAggregations: selectedAggregations });
else await this.onRemoveTransformation(aggItem.name);
};

onEditTransformation = async (oldName: string, newName: string): Promise<void> => {
const { aggList } = this.state;

const toEditIndex = aggList.findIndex((item) => {
return item.name === oldName;
});

let newAggItem = aggList[toEditIndex];
const type = aggList[toEditIndex].type;

// Modify the name of transform
newAggItem.name = newName;

// Also modify the target field if the transformation is a group by definition
if (isGroupBy(type)) newAggItem.item[type].target_field = newName;

this.setState({ aggList });

this.updateGroup();
this.updateAggregation();
await this.previewTransform(this.state.transformJSON);
this.setState({ selectedAggregations: selectedAggregations });
};

onRemoveTransformation = async (name: string): Promise<void> => {
Expand Down Expand Up @@ -512,6 +545,7 @@ export default class CreateTransformForm extends Component<CreateTransformFormPr
selectedAggregations={selectedAggregations}
onGroupSelectionChange={this.onGroupSelectionChange}
onAggregationSelectionChange={this.onAggregationSelectionChange}
onEditTransformation={this.onEditTransformation}
onRemoveTransformation={this.onRemoveTransformation}
previewTransform={previewTransform}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface DefineTransformsStepProps extends RouteComponentProps {
selectedAggregations: any;
aggList: TransformAggItem[];
onAggregationSelectionChange: (selectedFields: any, aggItem: TransformAggItem) => void;
onEditTransformation: (oldName: string, newName: string) => void;
onRemoveTransformation: (name: string) => void;
previewTransform: any[];
}
Expand Down Expand Up @@ -56,6 +57,7 @@ export default class DefineTransformsStep extends Component<DefineTransformsStep
onGroupSelectionChange,
selectedAggregations,
onAggregationSelectionChange,
onEditTransformation,
onRemoveTransformation,
} = this.props;
if (currentStep !== 2) return null;
Expand All @@ -80,6 +82,7 @@ export default class DefineTransformsStep extends Component<DefineTransformsStep
onGroupSelectionChange={onGroupSelectionChange}
selectedAggregations={selectedAggregations}
onAggregationSelectionChange={onAggregationSelectionChange}
onEditTransformation={onEditTransformation}
onRemoveTransformation={onRemoveTransformation}
isReadOnly={false}
/>
Expand Down
6 changes: 5 additions & 1 deletion public/pages/CreateTransform/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* GitHub history for details.
*/

import { FieldItem } from "../../../../models/interfaces";
import { FieldItem, TRANSFORM_AGG_TYPE } from "../../../../models/interfaces";

export const parseTimeunit = (timeunit: string): string => {
if (timeunit == "ms" || timeunit == "Milliseconds") return "millisecond(s)";
Expand Down Expand Up @@ -74,3 +74,7 @@ export const wrapQuotesAroundTransformId = (transformId: string, stringToSearch:
const idWrappedWithQuotes = `"${transformId}"`;
return stringToSearch.replace(regex, idWrappedWithQuotes);
};

export const isGroupBy = (type: string): boolean => {
return type == TRANSFORM_AGG_TYPE.histogram || type == TRANSFORM_AGG_TYPE.terms || type == TRANSFORM_AGG_TYPE.date_histogram;
};
Loading

0 comments on commit 54b4c8f

Please sign in to comment.