fleet/frontend/components/forms/LabelForm/LabelForm.jsx
Martavis Parker 5d647025f9
1497 improved query experience (#1998)
* Step 1 for improving query experience (#1591)

* fake change to create draft PR

* temp routes to work and not modify old query page

* created new API abstraction for query

* refactored App.jsx to prepare react-query

* fixed flow of redirects after page refresh; functional component added

* setup for getting data on edit

* implementing functions for query page

* Old form showing on new setup

* improving and breaking up query form

* no need for the helpers anymore; clean up

* added type for button component variant

* step toward new save modal; have to switch gears to #1619

* creating new query works

* clean up

* linting cleanup

* added default value for new query

* will address dynamic save disabled in edit step

* Step 2 for improving query experience (select targets) (#1732)

* fake change to create draft PR

* temp routes to work and not modify old query page

* created new API abstraction for query

* refactored App.jsx to prepare react-query

* fixed flow of redirects after page refresh; functional component added

* setup for getting data on edit

* implementing functions for query page

* Old form showing on new setup

* improving and breaking up query form

* no need for the helpers anymore; clean up

* added type for button component variant

* step toward new save modal; have to switch gears to #1619

* creating new query works

* clean up

* linting cleanup

* added default value for new query

* split steps into separate files for readability

* components laid out

* new targets picker

* function clean up

* styling tables

* fixing logic

* fixed logic to keep getting related hosts

* formatting targets for API

* fixed default query

* clean up

* styled target selectors; fixed target input styles

* began total count

* forgot to remove debugging code

* lint fixes

* added target count from API

* clean up

* able to remove selected host targets from table

* lint fixes

* Improving query experience - Step 3 (query results) (#1766)

* fake change to create draft PR

* temp routes to work and not modify old query page

* created new API abstraction for query

* refactored App.jsx to prepare react-query

* fixed flow of redirects after page refresh; functional component added

* setup for getting data on edit

* implementing functions for query page

* Old form showing on new setup

* improving and breaking up query form

* no need for the helpers anymore; clean up

* added type for button component variant

* step toward new save modal; have to switch gears to #1619

* creating new query works

* clean up

* linting cleanup

* added default value for new query

* split steps into separate files for readability

* components laid out

* new targets picker

* function clean up

* styling tables

* fixing logic

* fixed logic to keep getting related hosts

* formatting targets for API

* fixed default query

* clean up

* styled target selectors; fixed target input styles

* began total count

* forgot to remove debugging code

* lint fixes

* added target count from API

* clean up

* able to remove selected host targets from table

* lint fixes

* connected run query with modern React/JS; clean up

* linting fixes

* fixed logic to retrieve results from live query

* linting fixes

* created new, simpler query progress

* populating results and errors tables as expected

* syntax fixes

* fixing styles for query results

* more styling for query results

* manual merge from main

* Rename core->free and basic->premium

* Fix lint js

* Comment out portion of test that seems to timeout

* Rename tier  to premium if basic is still loaded

* go sum

* Query Experience Cleanup Tasks (#1807)

* fixes to get merged main branch to build and work

* moved screens for query pages; clean up

* updated and typed react ace for query form; clean up

* using console error instead

* added real types instead of `any` except for errors

* query side panel ts and functional. prep for close task.

* ability to hide, show query table sidebar

* improved live query status warning

* added loading and error state for targets search

* error screen for targets; improved loading display

* now using API-created label for all linux

* missed some files on previous commit

* able to edit query

* clean up

* lint fixes

* query results showing as they come

* remove unused code

* removed old query page. major file cleanup.

* removed selectedTargets redux implementation

* removed unused redux actions and reducers

* removed unused keys in initial state

* selectedOsqueryTable is now using context API

* removed all querypages redux code

* set up context for app and user

* fixed auth with temp fix for wrapper

* completed redux removal from query page

* fixed var names coming from main branch

* fixed var name changes coming from issue 1501

* fixed save popup bug; clean up

* added permissions

* fixed login redirect

* removed unused props

* linting fix

* clean up

* removed unused component, refactor, and clean up

* fixed styles for step 1 as admin

* fixed styles for step 1 as observer

* fixed percentage of online hosts

* added loading progress to query stop button

* reset query status on run again

* added download icon to export button text

* fixed error reset on name input; fixed styles

* fixed bug where query value wasn't saving

* fixed query value when blank

* fixed bug - default query was running every time

* auto adding host from url to targets

* fixed flows for repeating run and save steps

* fleet ace is now TS and functional

* fixed a couple of tests

* fixed issues with query value text inconsistencies

* fixed query side panel not showing

* hiding error count if not > 0

* fixed showing editor for different roles

* using integer for targets

* go sum

* fixed targets param

* catching all errors while running query

* fixed hover state for title and description

* ignore unit test for now; lint fixes

* locking react-ace version

* ignoring tests breaking in github actions

* brought tests back

* fixing file name

* fixing file name again

* fixed e2e test

* have to ignore tests for now

* ignore certain premium tests for now

* one last test to revamp

* another test

* fixed teamflow test

* fixed observer query 403

* lint fixes

* fixed maintainer test

* added changes file

Co-authored-by: Tomas Touceda <chiiph@gmail.com>
2021-09-10 12:06:37 -07:00

174 lines
4.8 KiB
JavaScript

import React, { Component } from "react";
import PropTypes from "prop-types";
import { noop } from "lodash";
import Button from "components/buttons/Button";
import Dropdown from "components/forms/fields/Dropdown";
import Form from "components/forms/Form";
import formFieldInterface from "interfaces/form_field";
import InputField from "components/forms/fields/InputField";
import FleetAce from "components/FleetAce";
import validate from "components/forms/LabelForm/validate";
const baseClass = "label-form";
const PLATFORM_STRINGS = {
darwin: "macOS",
windows: "MS Windows",
ubuntu: "Ubuntu Linux",
centos: "CentOS Linux",
};
const platformOptions = [
{ label: "All Platforms", value: "" },
{ label: "macOS", value: "darwin" },
{ label: "Windows", value: "windows" },
{ label: "Ubuntu", value: "ubuntu" },
{ label: "Centos", value: "centos" },
];
class LabelForm extends Component {
static propTypes = {
baseError: PropTypes.string,
fields: PropTypes.shape({
description: formFieldInterface.isRequired,
name: formFieldInterface.isRequired,
platform: formFieldInterface.isRequired,
query: formFieldInterface.isRequired,
}).isRequired,
formData: PropTypes.shape({
type: PropTypes.string,
label_type: PropTypes.string,
label_membership_type: PropTypes.string,
}),
handleSubmit: PropTypes.func.isRequired,
isEdit: PropTypes.bool,
onCancel: PropTypes.func.isRequired,
onOsqueryTableSelect: PropTypes.func,
};
static defaultProps = {
isEdit: false,
};
onLoad = (editor) => {
editor.setOptions({
enableLinking: true,
});
editor.on("linkClick", (data) => {
const { type, value } = data.token;
const { onOsqueryTableSelect } = this.props;
if (type === "osquery-token") {
return onOsqueryTableSelect(value);
}
return false;
});
};
render() {
const {
baseError,
fields,
handleSubmit,
isEdit,
onCancel,
formData,
} = this.props;
const { onLoad } = this;
const isBuiltin =
formData &&
(formData.label_type === "builtin" || formData.type === "status");
const isManual = formData && formData.label_membership_type === "manual";
const headerText = isEdit ? "Edit label" : "New label";
const saveBtnText = isEdit ? "Update label" : "Save label";
const aceHintText = isEdit
? "Label queries are immutable. To change the query, delete this label and create a new one."
: "";
const { platform } = fields;
if (isBuiltin) {
return (
<form className={`${baseClass}__wrapper`} onSubmit={handleSubmit}>
<h1>Built in labels cannot be edited</h1>
</form>
);
}
return (
<form className={`${baseClass}__wrapper`} onSubmit={handleSubmit}>
<h1>{headerText}</h1>
{!isManual && (
<FleetAce
{...fields.query}
label="SQL"
onLoad={onLoad}
readOnly={isEdit}
wrapperClassName={`${baseClass}__text-editor-wrapper`}
hint={aceHintText}
handleSubmit={noop}
/>
)}
{baseError && <div className="form__base-error">{baseError}</div>}
<InputField
{...fields.name}
inputClassName={`${baseClass}__label-title`}
label="Name"
/>
<InputField
{...fields.description}
inputClassName={`${baseClass}__label-description`}
label="Description"
type="textarea"
/>
{!isManual && !isEdit && (
<div className="form-field form-field--dropdown">
<label className="form-field__label" htmlFor="platform">
Platform
</label>
<Dropdown {...fields.platform} options={platformOptions} />
</div>
)}
{isEdit && platform && (
<div className={`${baseClass}__label-platform`}>
<p className="title">Platform</p>
<p>
{!platform.value
? "All platforms"
: PLATFORM_STRINGS[platform.value]}
</p>
<p className="hint">
Label platforms are immutable. To change the platform, delete this
label and create a new one.
</p>
</div>
)}
<div className={`${baseClass}__button-wrap`}>
<Button
className={`${baseClass}__cancel-btn`}
onClick={onCancel}
variant="inverse"
>
Cancel
</Button>
<Button
className={`${baseClass}__save-btn`}
type="submit"
variant="brand"
>
{saveBtnText}
</Button>
</div>
</form>
);
}
}
export default Form(LabelForm, {
fields: ["description", "name", "platform", "query"],
validate,
});