mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
UI: Enter button presses action button for forms/modals (#4939)
This commit is contained in:
parent
e675afc6cb
commit
d1860ad86d
14 changed files with 298 additions and 229 deletions
1
changes/issue-4864-enter-submits-form
Normal file
1
changes/issue-4864-enter-submits-form
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Pressing enter submits forms app-wide
|
||||
|
|
@ -49,7 +49,7 @@ describe("Labels flow", () => {
|
|||
cy.findByText(/show all mac usernames/i).click();
|
||||
});
|
||||
cy.getAttached(".manage-hosts__label-block button").last().click();
|
||||
cy.getAttached(".manage-hosts__modal-buttons > .button--alert")
|
||||
cy.getAttached(".delete-label-modal")
|
||||
.contains("button", /delete/i)
|
||||
.click();
|
||||
cy.getAttached(".host-side-panel").within(() => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
// @ts-ignore
|
||||
|
|
@ -31,6 +31,20 @@ const EnrollSecretModal = ({
|
|||
setSelectedSecret,
|
||||
globalSecrets,
|
||||
}: IEnrollSecretModal): JSX.Element => {
|
||||
useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
||||
event.preventDefault();
|
||||
onReturnToApp();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", listener);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const renderTeam = () => {
|
||||
if (typeof selectedTeam === "string") {
|
||||
selectedTeam = parseInt(selectedTeam, 10);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,25 @@ const LabelForm = ({
|
|||
debounceSQL(query);
|
||||
}, [query]);
|
||||
|
||||
useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
||||
event.preventDefault();
|
||||
handleSubmit({
|
||||
name,
|
||||
query,
|
||||
description,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", listener);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
};
|
||||
}, [name, query, description, platform]);
|
||||
|
||||
const onLoad = (editor: IAceEditor) => {
|
||||
editor.setOptions({
|
||||
enableLinking: true,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ const EditPackForm = ({
|
|||
|
||||
const onChangePackName = (value: string) => {
|
||||
setPackName(value);
|
||||
setErrors({});
|
||||
};
|
||||
|
||||
const onChangePackDescription = (value: string) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useCallback, useState } from "react";
|
||||
import React, { useCallback, useState, useEffect } from "react";
|
||||
|
||||
import { INewMembersBody, ITeam } from "interfaces/team";
|
||||
import endpoints from "fleet/endpoints";
|
||||
|
|
@ -41,7 +41,7 @@ const AddMemberModal = ({
|
|||
}, [selectedMembers, onSubmit]);
|
||||
|
||||
return (
|
||||
<Modal onExit={onCancel} title={"Add Members"} className={baseClass}>
|
||||
<Modal onExit={onCancel} title={"Add members"} className={baseClass}>
|
||||
<form className={`${baseClass}__form`}>
|
||||
<p className="title">Add team members</p>
|
||||
<AutocompleteDropdown
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
|
|
@ -18,8 +18,21 @@ const RemoveMemberModal = ({
|
|||
onSubmit,
|
||||
onCancel,
|
||||
}: IDeleteTeamModalProps): JSX.Element => {
|
||||
useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
||||
event.preventDefault();
|
||||
onSubmit();
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", listener);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal title={"Delete team"} onExit={onCancel} className={baseClass}>
|
||||
<Modal title={"Remove team member"} onExit={onCancel} className={baseClass}>
|
||||
<form className={`${baseClass}__form`}>
|
||||
<p>
|
||||
You are about to remove{" "}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ import Button from "components/buttons/Button"; // @ts-ignore
|
|||
import Dropdown from "components/forms/fields/Dropdown";
|
||||
import HostSidePanel from "components/side_panels/HostSidePanel"; // @ts-ignore
|
||||
import LabelForm from "components/forms/LabelForm";
|
||||
import Modal from "components/Modal";
|
||||
import QuerySidePanel from "components/side_panels/QuerySidePanel";
|
||||
import TableContainer from "components/TableContainer";
|
||||
import TableDataError from "components/TableDataError";
|
||||
|
|
@ -84,6 +83,7 @@ import PoliciesFilter from "./components/PoliciesFilter"; // @ts-ignore
|
|||
import EditColumnsModal from "./components/EditColumnsModal/EditColumnsModal";
|
||||
import TransferHostModal from "./components/TransferHostModal";
|
||||
import DeleteHostModal from "./components/DeleteHostModal";
|
||||
import DeleteLabelModal from "./components/DeleteLabelModal";
|
||||
import SoftwareVulnerabilities from "./components/SoftwareVulnerabilities";
|
||||
import EditColumnsIcon from "../../../../assets/images/icon-edit-columns-16x16@2x.png";
|
||||
import PencilIcon from "../../../../assets/images/icon-pencil-14x14@2x.png";
|
||||
|
|
@ -378,7 +378,6 @@ const ManageHostsPage = ({
|
|||
setShowEnrollSecretModal(!showEnrollSecretModal);
|
||||
};
|
||||
|
||||
// this is called when we click add or edit
|
||||
const toggleSecretEditorModal = () => {
|
||||
// open and closes add/edit modal
|
||||
setShowSecretEditorModal(!showSecretEditorModal);
|
||||
|
|
@ -402,6 +401,10 @@ const ManageHostsPage = ({
|
|||
setShowAddHostsModal(!showAddHostsModal);
|
||||
};
|
||||
|
||||
const toggleEditColumnsModal = () => {
|
||||
setShowEditColumnsModal(!showEditColumnsModal);
|
||||
};
|
||||
|
||||
const toggleAllMatchingHosts = (shouldSelect: boolean) => {
|
||||
if (typeof shouldSelect !== "undefined") {
|
||||
setIsAllMatchingHostsSelected(shouldSelect);
|
||||
|
|
@ -674,25 +677,13 @@ const ManageHostsPage = ({
|
|||
);
|
||||
};
|
||||
|
||||
const onEditColumnsClick = () => {
|
||||
setShowEditColumnsModal(true);
|
||||
};
|
||||
|
||||
const onCancelColumns = () => {
|
||||
setShowEditColumnsModal(false);
|
||||
};
|
||||
|
||||
const onSaveColumns = (newHiddenColumns: string[]) => {
|
||||
localStorage.setItem("hostHiddenColumns", JSON.stringify(newHiddenColumns));
|
||||
setHiddenColumns(newHiddenColumns);
|
||||
setShowEditColumnsModal(false);
|
||||
};
|
||||
|
||||
const onCancelAddLabel = () => {
|
||||
router.goBack();
|
||||
};
|
||||
|
||||
const onCancelEditLabel = () => {
|
||||
const onCancelLabel = () => {
|
||||
router.goBack();
|
||||
};
|
||||
|
||||
|
|
@ -1086,28 +1077,26 @@ const ManageHostsPage = ({
|
|||
/>
|
||||
);
|
||||
|
||||
const renderPoliciesFilterBlock = () => {
|
||||
return (
|
||||
<div className={`${baseClass}__policies-filter-block`}>
|
||||
<PoliciesFilter
|
||||
policyResponse={policyResponse}
|
||||
onChange={handleChangePoliciesFilter}
|
||||
/>
|
||||
<div className={`${baseClass}__policies-filter-name-card`}>
|
||||
<img src={PolicyIcon} alt="Policy" />
|
||||
{policy?.name}
|
||||
<Button
|
||||
className={`${baseClass}__clear-policies-filter`}
|
||||
onClick={handleClearPoliciesFilter}
|
||||
variant={"small-text-icon"}
|
||||
title={policy?.name}
|
||||
>
|
||||
<img src={CloseIcon} alt="Remove policy filter" />
|
||||
</Button>
|
||||
</div>
|
||||
const renderPoliciesFilterBlock = () => (
|
||||
<div className={`${baseClass}__policies-filter-block`}>
|
||||
<PoliciesFilter
|
||||
policyResponse={policyResponse}
|
||||
onChange={handleChangePoliciesFilter}
|
||||
/>
|
||||
<div className={`${baseClass}__policies-filter-name-card`}>
|
||||
<img src={PolicyIcon} alt="Policy" />
|
||||
{policy?.name}
|
||||
<Button
|
||||
className={`${baseClass}__clear-policies-filter`}
|
||||
onClick={handleClearPoliciesFilter}
|
||||
variant={"small-text-icon"}
|
||||
title={policy?.name}
|
||||
>
|
||||
<img src={CloseIcon} alt="Remove policy filter" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderSoftwareFilterBlock = () => {
|
||||
if (softwareDetails) {
|
||||
|
|
@ -1155,120 +1144,68 @@ const ManageHostsPage = ({
|
|||
};
|
||||
|
||||
const renderEditColumnsModal = () => {
|
||||
if (!showEditColumnsModal || !config || !currentUser) {
|
||||
if (!config || !currentUser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Edit columns"
|
||||
onExit={() => setShowEditColumnsModal(false)}
|
||||
className={`${baseClass}__invite-modal`}
|
||||
>
|
||||
<EditColumnsModal
|
||||
columns={generateAvailableTableHeaders(
|
||||
config,
|
||||
currentUser,
|
||||
currentTeam
|
||||
)}
|
||||
hiddenColumns={hiddenColumns}
|
||||
onSaveColumns={onSaveColumns}
|
||||
onCancelColumns={onCancelColumns}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const renderSecretEditorModal = () => {
|
||||
if (!canEnrollHosts || !showSecretEditorModal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SecretEditorModal
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
onSaveSecret={onSaveSecret}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
selectedSecret={selectedSecret}
|
||||
<EditColumnsModal
|
||||
columns={generateAvailableTableHeaders(
|
||||
config,
|
||||
currentUser,
|
||||
currentTeam
|
||||
)}
|
||||
hiddenColumns={hiddenColumns}
|
||||
onSaveColumns={onSaveColumns}
|
||||
onCancelColumns={toggleEditColumnsModal}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderDeleteSecretModal = () => {
|
||||
if (!canEnrollHosts || !showDeleteSecretModal) {
|
||||
return null;
|
||||
}
|
||||
const renderSecretEditorModal = () => (
|
||||
<SecretEditorModal
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
onSaveSecret={onSaveSecret}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
selectedSecret={selectedSecret}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<DeleteSecretModal
|
||||
onDeleteSecret={onDeleteSecret}
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderDeleteSecretModal = () => (
|
||||
<DeleteSecretModal
|
||||
onDeleteSecret={onDeleteSecret}
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderEnrollSecretModal = () => {
|
||||
if (!canEnrollHosts || !showEnrollSecretModal) {
|
||||
return null;
|
||||
}
|
||||
const renderEnrollSecretModal = () => (
|
||||
<EnrollSecretModal
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
onReturnToApp={() => setShowEnrollSecretModal(false)}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
setSelectedSecret={setSelectedSecret}
|
||||
globalSecrets={globalSecrets}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<EnrollSecretModal
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
onReturnToApp={() => setShowEnrollSecretModal(false)}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
setSelectedSecret={setSelectedSecret}
|
||||
globalSecrets={globalSecrets}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderDeleteLabelModal = () => (
|
||||
<DeleteLabelModal
|
||||
onSubmit={onDeleteLabel}
|
||||
onCancel={toggleDeleteLabelModal}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderDeleteLabelModal = () => {
|
||||
if (!showDeleteLabelModal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Delete label"
|
||||
onExit={toggleDeleteLabelModal}
|
||||
className={`${baseClass}_delete-label__modal`}
|
||||
>
|
||||
<>
|
||||
<p>Are you sure you wish to delete this label?</p>
|
||||
<div className={`${baseClass}__modal-buttons`}>
|
||||
<Button onClick={toggleDeleteLabelModal} variant="inverse-alert">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={onDeleteLabel} variant="alert">
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const renderAddHostsModal = () => {
|
||||
if (!showAddHostsModal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AddHostsModal
|
||||
onCancel={toggleAddHostsModal}
|
||||
selectedTeam={addHostsTeam}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderAddHostsModal = () => (
|
||||
<AddHostsModal onCancel={toggleAddHostsModal} selectedTeam={addHostsTeam} />
|
||||
);
|
||||
|
||||
const renderTransferHostModal = () => {
|
||||
if (!showTransferHostModal || !teams) {
|
||||
if (!teams) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -1282,20 +1219,14 @@ const ManageHostsPage = ({
|
|||
);
|
||||
};
|
||||
|
||||
const renderDeleteHostModal = () => {
|
||||
if (!showDeleteHostModal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<DeleteHostModal
|
||||
selectedHostIds={selectedHostIds}
|
||||
onSubmit={onDeleteHostSubmit}
|
||||
onCancel={toggleDeleteHostModal}
|
||||
isAllMatchingHostsSelected={isAllMatchingHostsSelected}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderDeleteHostModal = () => (
|
||||
<DeleteHostModal
|
||||
selectedHostIds={selectedHostIds}
|
||||
onSubmit={onDeleteHostSubmit}
|
||||
onCancel={toggleDeleteHostModal}
|
||||
isAllMatchingHostsSelected={isAllMatchingHostsSelected}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderHeaderLabelBlock = () => {
|
||||
if (selectedLabel) {
|
||||
|
|
@ -1332,25 +1263,23 @@ const ManageHostsPage = ({
|
|||
return null;
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className={`${baseClass}__header`}>
|
||||
<div className={`${baseClass}__text`}>
|
||||
<div className={`${baseClass}__title`}>
|
||||
{isFreeTier && <h1>Hosts</h1>}
|
||||
{isPremiumTier &&
|
||||
availableTeams &&
|
||||
(availableTeams.length > 1 || isOnGlobalTeam) &&
|
||||
renderTeamsFilterDropdown()}
|
||||
{isPremiumTier &&
|
||||
!isOnGlobalTeam &&
|
||||
availableTeams &&
|
||||
availableTeams.length === 1 && <h1>{availableTeams[0].name}</h1>}
|
||||
</div>
|
||||
const renderHeader = () => (
|
||||
<div className={`${baseClass}__header`}>
|
||||
<div className={`${baseClass}__text`}>
|
||||
<div className={`${baseClass}__title`}>
|
||||
{isFreeTier && <h1>Hosts</h1>}
|
||||
{isPremiumTier &&
|
||||
availableTeams &&
|
||||
(availableTeams.length > 1 || isOnGlobalTeam) &&
|
||||
renderTeamsFilterDropdown()}
|
||||
{isPremiumTier &&
|
||||
!isOnGlobalTeam &&
|
||||
availableTeams &&
|
||||
availableTeams.length === 1 && <h1>{availableTeams[0].name}</h1>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
);
|
||||
|
||||
const onExportHostsResults = async (
|
||||
evt: React.MouseEvent<HTMLButtonElement>
|
||||
|
|
@ -1455,7 +1384,7 @@ const ManageHostsPage = ({
|
|||
return (
|
||||
<div className="body-wrap">
|
||||
<LabelForm
|
||||
onCancel={onCancelAddLabel}
|
||||
onCancel={onCancelLabel}
|
||||
onOsqueryTableSelect={onOsqueryTableSelect}
|
||||
handleSubmit={onSaveAddLabel}
|
||||
baseError={labelsError?.message || ""}
|
||||
|
|
@ -1470,7 +1399,7 @@ const ManageHostsPage = ({
|
|||
<div className="body-wrap">
|
||||
<LabelForm
|
||||
selectedLabel={selectedLabel}
|
||||
onCancel={onCancelEditLabel}
|
||||
onCancel={onCancelLabel}
|
||||
onOsqueryTableSelect={onOsqueryTableSelect}
|
||||
handleSubmit={onEditLabel}
|
||||
baseError={labelsError?.message || ""}
|
||||
|
|
@ -1512,17 +1441,15 @@ const ManageHostsPage = ({
|
|||
return SidePanel;
|
||||
};
|
||||
|
||||
const renderStatusDropdown = () => {
|
||||
return (
|
||||
<Dropdown
|
||||
value={getStatusSelected() || ALL_HOSTS_LABEL}
|
||||
className={`${baseClass}__status_dropdown`}
|
||||
options={HOST_SELECT_STATUSES}
|
||||
searchable={false}
|
||||
onChange={handleStatusDropdownChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderStatusDropdown = () => (
|
||||
<Dropdown
|
||||
value={getStatusSelected() || ALL_HOSTS_LABEL}
|
||||
className={`${baseClass}__status_dropdown`}
|
||||
options={HOST_SELECT_STATUSES}
|
||||
searchable={false}
|
||||
onChange={handleStatusDropdownChange}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderTable = () => {
|
||||
if (
|
||||
|
|
@ -1606,7 +1533,7 @@ const ManageHostsPage = ({
|
|||
}
|
||||
emptyComponent={EmptyHosts}
|
||||
customControl={renderStatusDropdown}
|
||||
onActionButtonClick={onEditColumnsClick}
|
||||
onActionButtonClick={toggleEditColumnsModal}
|
||||
onPrimarySelectActionClick={onDeleteHostsClick}
|
||||
onQueryChange={onTableQueryChange}
|
||||
toggleAllPagesSelected={toggleAllMatchingHosts}
|
||||
|
|
@ -1703,14 +1630,14 @@ const ManageHostsPage = ({
|
|||
</div>
|
||||
)}
|
||||
{renderSidePanel()}
|
||||
{renderDeleteSecretModal()}
|
||||
{renderSecretEditorModal()}
|
||||
{renderEnrollSecretModal()}
|
||||
{renderEditColumnsModal()}
|
||||
{renderDeleteLabelModal()}
|
||||
{renderAddHostsModal()}
|
||||
{renderTransferHostModal()}
|
||||
{renderDeleteHostModal()}
|
||||
{canEnrollHosts && showDeleteSecretModal && renderDeleteSecretModal()}
|
||||
{canEnrollHosts && showSecretEditorModal && renderSecretEditorModal()}
|
||||
{canEnrollHosts && showEnrollSecretModal && renderEnrollSecretModal()}
|
||||
{showEditColumnsModal && renderEditColumnsModal()}
|
||||
{showDeleteLabelModal && renderDeleteLabelModal()}
|
||||
{showAddHostsModal && renderAddHostsModal()}
|
||||
{showTransferHostModal && renderTransferHostModal()}
|
||||
{showDeleteHostModal && renderDeleteHostModal()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
import React, { useEffect } from "react";
|
||||
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
|
||||
const baseClass = "delete-label-modal";
|
||||
|
||||
interface IDeleteLabelModalProps {
|
||||
onSubmit: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const DeleteLabelModal = ({
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}: IDeleteLabelModalProps): JSX.Element => {
|
||||
useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
||||
event.preventDefault();
|
||||
onSubmit();
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", listener);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal title="Delete label" onExit={onCancel} className={baseClass}>
|
||||
<>
|
||||
<p>Are you sure you wish to delete this label?</p>
|
||||
<div className={`${baseClass}__btn-wrap`}>
|
||||
<Button onClick={onCancel} variant="inverse-alert">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={onSubmit} variant="alert">
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteLabelModal;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
.delete-label-modal {
|
||||
&__btn-wrap {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
margin-top: $pad-xxlarge;
|
||||
}
|
||||
|
||||
&__btn {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./DeleteLabelModal";
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Modal from "components/Modal";
|
||||
import Checkbox from "../../../../../components/forms/fields/Checkbox";
|
||||
import Button from "../../../../../components/buttons/Button";
|
||||
|
||||
|
|
@ -57,37 +58,43 @@ const EditColumnsModal = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<div className={"edit-column-modal"}>
|
||||
<p>Choose which columns you see:</p>
|
||||
<div className={"modal-items"}>
|
||||
{columnItems.map((column) => {
|
||||
if (column.disableHidden) return null;
|
||||
return (
|
||||
<div key={column.accessor}>
|
||||
<Checkbox
|
||||
name={column.name}
|
||||
value={column.isChecked}
|
||||
onChange={() => updateColumnItems(column.accessor)}
|
||||
>
|
||||
<span>{column.name}</span>
|
||||
</Checkbox>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className={"button-actions"}>
|
||||
<Button onClick={onCancelColumns} variant={"inverse"}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
className={"save-button"}
|
||||
onClick={() => onSaveColumns(getHiddenColumns(columnItems))}
|
||||
variant={"default"}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Modal
|
||||
title="Edit columns"
|
||||
onExit={onCancelColumns}
|
||||
className={"edit-columns-modal"}
|
||||
>
|
||||
<>
|
||||
<p>Choose which columns you see:</p>
|
||||
<div className={"modal-items"}>
|
||||
{columnItems.map((column) => {
|
||||
if (column.disableHidden) return null;
|
||||
return (
|
||||
<div key={column.accessor}>
|
||||
<Checkbox
|
||||
name={column.name}
|
||||
value={column.isChecked}
|
||||
onChange={() => updateColumnItems(column.accessor)}
|
||||
>
|
||||
<span>{column.name}</span>
|
||||
</Checkbox>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className={"button-actions"}>
|
||||
<Button onClick={onCancelColumns} variant={"inverse"}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
className={"save-button"}
|
||||
onClick={() => onSaveColumns(getHiddenColumns(columnItems))}
|
||||
variant={"default"}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { IPolicy } from "interfaces/policy";
|
||||
import { IWebhookFailingPolicies } from "interfaces/webhook";
|
||||
|
|
@ -120,7 +120,9 @@ const ManageAutomationsModal = ({
|
|||
setDestinationUrl(value);
|
||||
};
|
||||
|
||||
const handleSaveAutomation = (evt: React.MouseEvent<HTMLFormElement>) => {
|
||||
const handleSaveAutomation = (
|
||||
evt: React.MouseEvent<HTMLFormElement> | KeyboardEvent
|
||||
) => {
|
||||
evt.preventDefault();
|
||||
|
||||
const { valid, errors: newErrors } = validateWebhookURL(destination_url);
|
||||
|
|
@ -147,6 +149,19 @@ const ManageAutomationsModal = ({
|
|||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
||||
event.preventDefault();
|
||||
handleSaveAutomation(event);
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", listener);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
};
|
||||
}, [handleSaveAutomation]);
|
||||
|
||||
if (showPreviewPayloadModal) {
|
||||
return <PreviewPayloadModal onCancel={togglePreviewPayloadModal} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* This component is used for creating and editing both global and team scheduled queries */
|
||||
|
||||
import React, { useState, useCallback, useContext } from "react";
|
||||
import React, { useState, useCallback, useContext, useEffect } from "react";
|
||||
import { pull } from "lodash";
|
||||
import { AppContext } from "context/app";
|
||||
|
||||
|
|
@ -218,6 +218,19 @@ const ScheduleEditorModal = ({
|
|||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
||||
event.preventDefault();
|
||||
onFormSubmit();
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", listener);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", listener);
|
||||
};
|
||||
}, [onFormSubmit]);
|
||||
|
||||
if (showPreviewDataModal) {
|
||||
return <PreviewDataModal onCancel={togglePreviewDataModal} />;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue