Skip to content

Commit

Permalink
Implemented alias action UX. (#754)
Browse files Browse the repository at this point in the history
* Implemented UX component for configuring and editing alias actions.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Implemented unit and integration tests for alias action UX.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Refactored existing test to accommodate addition of alias action UX.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Fixed a bug preventing validation messages from appearing under both combo boxes at once.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Removed redundant 'popout' icons from 'Learn more' links. Having 'target="_blank"' in the link attributes provides the icon. Updated snapshots.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Added unit tests for AliasUiAction.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Refactored alias action UX to include toggles to hide/display the add/remove combo boxes. Implemented a modal to confirm clearing combo box entries when toggling display.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Refactored UX to remove the alias combo box clear confirmation modal based on PR feedback.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

* Updated the 2.8 release notes.

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>

---------

Signed-off-by: AWSHurneyt <hurneyt@amazon.com>
(cherry picked from commit 5f5a172)
  • Loading branch information
AWSHurneyt authored and github-actions[bot] committed May 31, 2023
1 parent 5c882d7 commit 8830d75
Show file tree
Hide file tree
Showing 38 changed files with 1,426 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"policy": {
"policy_id": "test_alias_policy_id",
"description": "Example policy with an alias action.",
"default_state": "alias-state",
"states": [
{
"name": "alias-state",
"actions": [
{
"alias": {
"actions": [
{
"remove": {
"aliases": ["alias1", "alias2"]
}
},
{
"remove": {
"alias": "alias3"
}
},
{
"add": {
"aliases": ["alias4", "alias5"]
}
},
{
"add": {
"aliases": "alias6"
}
}
]
}
}
],
"transitions": []
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { BASE_PATH, IM_PLUGIN_NAME } from "../../../utils/constants";
import samplePolicy from "../../../fixtures/plugins/index-management-dashboards-plugin/sample_policy";
import sampleAliasPolicy from "../../../fixtures/plugins/index-management-dashboards-plugin/sample_policy_alias_action.json";

const POLICY_ID = "test_policy_id";

Expand Down Expand Up @@ -64,13 +65,106 @@ describe("Policies", () => {
// Confirm we can see the created policy's description in table
cy.contains("A simple description");
});

it("with an alias action using the visual editor", () => {
/* Create a policy with an alias action */
const aliasPolicyId = "visual-editor-alias-policy";
const testInputs = {
add: ["alias1", "alias2"],
remove: ["alias3", "alias5", "alias6"],
};

// Route us to create policy page
cy.contains("Create policy").click({ force: true });

// Use the visual editor
cy.contains("Visual editor").click({ force: true });
cy.contains("Continue").click({ force: true });

// Wait for input to load and then type in the policy ID
cy.get(`input[placeholder="hot_cold_workflow"]`).type(aliasPolicyId, {
force: true,
});

// Type in the policy description
cy.get(`[data-test-subj="create-policy-description"]`).type("{selectall}{backspace}" + sampleAliasPolicy.policy.description);

// Add a state
cy.get("button").contains("Add state").click({ force: true });

// Enter a state name
cy.get(`[data-test-subj="create-state-state-name"]`).type(sampleAliasPolicy.policy.states[0].name);

// Add a new action
cy.get("button").contains("+ Add action").click({ force: true });

// Select 'Alias' type
cy.get(`[data-test-subj="create-state-action-type"]`).select("Add / remove aliases");

// Confirm 'Add action' button is disabled
cy.get(`[data-test-subj="flyout-footer-action-button"]`).should("be.disabled");

// Toggle the add alias combo box
cy.get(`[data-test-subj="add-alias-toggle"]`).click({ force: true });

// Enter aliases to add
cy.get(`[data-test-subj="add-alias-combo-box"]`).click({ force: true }).type(testInputs.add.join("{enter}"));

// Toggle the add alias combo box
cy.get(`[data-test-subj="remove-alias-toggle"]`).click({ force: true });

// Enter aliases to remove
cy.get(`[data-test-subj="remove-alias-combo-box"]`).click({ force: true }).type(testInputs.remove.join("{enter}"));

// Click the 'Add action' button
cy.get(`[data-test-subj="flyout-footer-action-button"]`).click({ force: true });

// Click the 'Save action' button
cy.get("button").contains("Save state").click({ force: true });

// Click the 'Create' button
cy.get("button").contains("Create").click({ force: true });

/* Confirm policy was created as expected */

// Wait for the 'State management' dashboard to load
cy.contains("State management policies (", { timeout: 60000 });

// Click on the test alias to navigate to the details page
cy.contains(aliasPolicyId).click({ force: true });

// Wait for the details page to load, and click the 'Edit' button
cy.url({ timeout: 60000 }).should("include", "policy-details");
cy.contains("Edit").click({ force: true });

// Use the visual editor
cy.contains("Visual editor").click({ force: true });
cy.contains("Continue").click({ force: true });

// Click the state edit icon
cy.get(`[aria-label="Edit"]`).click({ force: true });
cy.get(`[data-test-subj="draggable"]`).within(() => {
cy.get(`[aria-label="Edit"]`).click({ force: true });
});

// Confirm all of the expected inputs are in the 'Add' combo box
testInputs.add.forEach((alias) => {
cy.get(`[data-test-subj="add-alias-combo-box"]`).contains(alias);
});

// Confirm all of the expected inputs are in the 'Remove' combo box
testInputs.remove.forEach((alias) => {
cy.get(`[data-test-subj="remove-alias-combo-box"]`).contains(alias);
});
});
});

describe("can be edited", () => {
before(() => {
cy.deleteAllIndices();
cy.deleteIMJobs();
cy.createPolicy(POLICY_ID, samplePolicy);
cy.createPolicy(sampleAliasPolicy.policy.policy_id, sampleAliasPolicy);
});

it("successfully", () => {
Expand Down Expand Up @@ -116,6 +210,79 @@ describe("Policies", () => {
// Confirm new description shows in table
cy.contains("A new description");
});

it("with more aliases", () => {
// Click on the test alias to navigate to the details page
const testInputs = {
add: ["alias4", "alias6"],
remove: ["alias1", "alias2", "alias3", "alias7"],
};
/* Edit the policy */

// Click on the test alias to navigate to the details page
cy.contains(sampleAliasPolicy.policy.policy_id).click({ force: true });

// Wait for the details page to load, and click the 'Edit' button
cy.url({ timeout: 60000 }).should("include", "policy-details");
cy.contains("Edit").click({ force: true });

// Use the visual editor
cy.contains("Visual editor").click({ force: true });
cy.contains("Continue").click({ force: true });

// Click the 'Edit state' icon
cy.get(`[aria-label="Edit"]`).click({ force: true });

// Click the 'Edit action' icon
cy.get(`[data-test-subj="draggable"]`).within(() => {
cy.get(`[aria-label="Edit"]`).click({ force: true });
});

// Remove an alias from the 'Add' combo box
cy.get(`[aria-label="Remove alias5 from selection in this group"]`).click({ force: true });

// Add a new alias to the 'Remove' combo box
cy.get(`[data-test-subj="remove-alias-combo-box"]`).click({ force: true }).type("alias7{enter}");

// Save the edits
cy.get(`[data-test-subj="flyout-footer-action-button"]`).click({ force: true });
cy.get("button").contains("Update state").click({ force: true });
cy.get("button").contains("Update").click({ force: true });

/* Confirm policy was edited as expected */

// Wait for the 'State management' dashboard to load
cy.contains("State management policies (", { timeout: 60000 });

// Click on the test alias to navigate to the details page
cy.contains(sampleAliasPolicy.policy.policy_id).click({ force: true });

// Wait for the details page to load, and click the 'Edit' button
cy.url({ timeout: 60000 }).should("include", "policy-details");
cy.contains("Edit").click({ force: true });

// Use the visual editor
cy.contains("Visual editor").click({ force: true });
cy.contains("Continue").click({ force: true });

// Click the 'Edit state' icon
cy.get(`[aria-label="Edit"]`).click({ force: true });

// Click the 'Edit action' icon
cy.get(`[data-test-subj="draggable"]`).within(() => {
cy.get(`[aria-label="Edit"]`).click({ force: true });
});

// Confirm all of the expected inputs are in the 'Add' combo box
testInputs.add.forEach((alias) => {
cy.get(`[data-test-subj="add-alias-combo-box"]`).contains(alias);
});

// Confirm all of the expected inputs are in the 'Remove' combo box
testInputs.remove.forEach((alias) => {
cy.get(`[data-test-subj="remove-alias-combo-box"]`).contains(alias);
});
});
});

describe("can be deleted", () => {
Expand Down
19 changes: 19 additions & 0 deletions models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ export interface UIAction<Data> {
clone: (action: Data) => UIAction<Data>;
content: () => JSX.Element | string | null;
toAction: () => Action;
customDisplayText?: string;
}

export interface ForceMergeAction extends Action {
Expand Down Expand Up @@ -433,6 +434,24 @@ export interface IndexPriorityAction extends Action {
};
}

export enum AliasActions {
ADD = "add",
REMOVE = "remove",
}

export type AliasActionItem = {
[key in AliasActions]: {
alias?: string;
aliases?: string[];
};
};

export interface AliasAction extends Action {
alias: {
actions: AliasActionItem[];
};
}

export interface AllocationAction extends Action {
allocation: {
// TODO: These require a complete UI and we are only supporting JSON editor for allocation for now
Expand Down
2 changes: 1 addition & 1 deletion public/containers/ErrorNotification/ErrorNotification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class ErrorNotification extends Component<ErrorNotificationProps, ErrorNotificat
<p style={{ fontWeight: 200 }}>
You can set up an error notification for when a policy execution fails.{" "}
<EuiLink href={ERROR_NOTIFICATION_DOCUMENTATION_URL} target="_blank" rel="noopener noreferrer">
Learn more <EuiIcon type="popout" size="s" />
Learn more
</EuiLink>
</p>
</EuiText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ exports[`<ErrorNotification /> spec renders the component 1`] = `
rel="noopener noreferrer"
target="_blank"
>
Learn more
EuiIconMock
Learn more
EuiIconMock
<span
class="euiScreenReaderOnly"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default class NewPolicy extends React.Component<NewPolicyProps, NewPolicy
<p>
When the new policy will take effect depends on the current state of indices and the states of the new policy.{" "}
<EuiLink href={DOCUMENTATION_URL} target="_blank" rel="noopener noreferrer">
Learn more <EuiIcon type="popout" size="s" />
Learn more
</EuiLink>
</p>
</EuiText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ exports[`<NewPolicy /> spec renders the component 1`] = `
rel="noopener noreferrer"
target="_blank"
>
Learn more
EuiIconMock
Learn more
EuiIconMock
<span
class="euiScreenReaderOnly"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ exports[`<ChangePolicy /> spec renders the component 1`] = `
rel="noopener noreferrer"
target="_blank"
>
Learn more
EuiIconMock
Learn more
EuiIconMock
<span
class="euiScreenReaderOnly"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const DefinePolicy = ({ jsonString, onChange, onAutoIndent, hasJSONError }: Defi
You can think of policies as state machines. "Actions" are the operations ISM performs when an index is in a certain state.
"Transitions" define when to move from one state to another.{" "}
<EuiLink href={DOCUMENTATION_URL} target="_blank" rel="noopener noreferrer">
Learn more <EuiIcon type="popout" size="s" />
Learn more
</EuiLink>
</p>
</EuiText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ exports[`<DefinePolicy /> spec renders the component 1`] = `
rel="noopener noreferrer"
target="_blank"
>
Learn more
EuiIconMock
Learn more
EuiIconMock
<span
class="euiScreenReaderOnly"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export default class CreatePolicy extends Component<CreatePolicyProps, CreatePol
over your edits to these indices, please use the "Change Policy" under "Managed Indices" to reapply the policy after submitting
your edits.{" "}
<EuiLink href={DOCUMENTATION_URL} target="_blank" rel="noopener noreferrer">
Learn more <EuiIcon type="popout" size="s" />
Learn more
</EuiLink>
</p>
</EuiCallOut>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,7 @@ exports[`<CreatePolicy /> spec renders the edit component 1`] = `
rel="noopener noreferrer"
target="_blank"
>
Learn more
EuiIconMock
Learn more
EuiIconMock
<span
class="euiScreenReaderOnly"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`inputLimitText renders the component with 0 inputs 1`] = `
<div
class="euiText euiText--extraSmall"
>
<div
class="euiTextColor euiTextColor--subdued"
>
You can add up to 10 more aliases.
</div>
</div>
`;

exports[`inputLimitText renders the component with 0 inputs remaining 1`] = `
<div
class="euiText euiText--extraSmall"
>
<div
class="euiTextColor euiTextColor--subdued"
>
You have reached the limit of 10 aliases.
</div>
</div>
`;

exports[`inputLimitText renders the component with 1 input remaining 1`] = `
<div
class="euiText euiText--extraSmall"
>
<div
class="euiTextColor euiTextColor--subdued"
>
You can add up to 1 more alias.
</div>
</div>
`;
Loading

0 comments on commit 8830d75

Please sign in to comment.