mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
Debounce, onchange, changelog (#4413)
This commit is contained in:
parent
9448c922d1
commit
fa3df0347b
4 changed files with 77 additions and 11 deletions
1
changes/issue-4365-sql-error-onchange
Normal file
1
changes/issue-4365-sql-error-onchange
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Users are presented with debounced SQL errors on change for labels, queries, and policies
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { IAceEditor } from "react-ace/lib/types";
|
||||
import { noop } from "lodash";
|
||||
import { noop, size } from "lodash";
|
||||
import { useDebouncedCallback } from "use-debounce/lib";
|
||||
|
||||
import { ILabel, ILabelFormData } from "interfaces/label";
|
||||
import Button from "components/buttons/Button"; // @ts-ignore
|
||||
|
|
@ -36,6 +37,18 @@ const platformOptions = [
|
|||
{ label: "Centos", value: "centos" },
|
||||
];
|
||||
|
||||
const validateQuerySQL = (query: string) => {
|
||||
const errors: { [key: string]: any } = {};
|
||||
const { error: queryError, valid: queryValid } = validateQuery(query);
|
||||
|
||||
if (!queryValid) {
|
||||
errors.query = queryError;
|
||||
}
|
||||
|
||||
const valid = !size(errors);
|
||||
return { valid, errors };
|
||||
};
|
||||
|
||||
const LabelForm = ({
|
||||
baseError,
|
||||
selectedLabel,
|
||||
|
|
@ -56,10 +69,28 @@ const LabelForm = ({
|
|||
selectedLabel?.platform || ""
|
||||
);
|
||||
|
||||
const debounceSQL = useDebouncedCallback((queryString: string) => {
|
||||
let valid = true;
|
||||
const { valid: isValidated, errors: newErrors } = validateQuerySQL(
|
||||
queryString
|
||||
);
|
||||
valid = isValidated;
|
||||
|
||||
if (query === "") {
|
||||
setQueryError("");
|
||||
} else {
|
||||
setQueryError(newErrors.query);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
setNameError(backendValidators.name);
|
||||
}, [backendValidators]);
|
||||
|
||||
useEffect(() => {
|
||||
debounceSQL(query);
|
||||
}, [query]);
|
||||
|
||||
const onLoad = (editor: IAceEditor) => {
|
||||
editor.setOptions({
|
||||
enableLinking: true,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */
|
||||
/* eslint-disable jsx-a11y/interactive-supports-focus */
|
||||
import React, { useState, useContext, KeyboardEvent } from "react";
|
||||
import React, { useState, useContext, useEffect, KeyboardEvent } from "react";
|
||||
import { IAceEditor } from "react-ace/lib/types";
|
||||
import { isUndefined } from "lodash";
|
||||
import { useDebouncedCallback } from "use-debounce/lib";
|
||||
import { isUndefined, size } from "lodash";
|
||||
import classnames from "classnames";
|
||||
|
||||
import { addGravatarUrlToResource } from "fleet/helpers";
|
||||
|
|
@ -15,6 +16,8 @@ import { IQueryPlatform } from "interfaces/query";
|
|||
|
||||
import Avatar from "components/Avatar";
|
||||
import FleetAce from "components/FleetAce";
|
||||
// @ts-ignore
|
||||
import validateQuery from "components/forms/validators/validate_query";
|
||||
import Button from "components/buttons/Button";
|
||||
import Checkbox from "components/forms/fields/Checkbox";
|
||||
import Spinner from "components/Spinner";
|
||||
|
|
@ -40,6 +43,18 @@ interface IPolicyFormProps {
|
|||
backendValidators: { [key: string]: string };
|
||||
}
|
||||
|
||||
const validateQuerySQL = (query: string) => {
|
||||
const errors: { [key: string]: any } = {};
|
||||
const { error: queryError, valid: queryValid } = validateQuery(query);
|
||||
|
||||
if (!queryValid) {
|
||||
errors.query = queryError;
|
||||
}
|
||||
|
||||
const valid = !size(errors);
|
||||
return { valid, errors };
|
||||
};
|
||||
|
||||
const PolicyForm = ({
|
||||
policyIdForEdit,
|
||||
showOpenSchemaActionText,
|
||||
|
|
@ -98,6 +113,22 @@ const PolicyForm = ({
|
|||
isTeamMaintainer,
|
||||
} = useContext(AppContext);
|
||||
|
||||
policyIdForEdit = policyIdForEdit || 0;
|
||||
|
||||
const debounceSQL = useDebouncedCallback((sql: string) => {
|
||||
let valid = true;
|
||||
const { valid: isValidated, errors: newErrors } = validateQuerySQL(sql);
|
||||
valid = isValidated;
|
||||
|
||||
setErrors({
|
||||
...newErrors,
|
||||
});
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
debounceSQL(lastEditedQueryBody);
|
||||
}, [lastEditedQueryBody]);
|
||||
|
||||
const isEditMode = !!policyIdForEdit && !isTeamObserver && !isGlobalObserver;
|
||||
|
||||
const hasSavePermissions =
|
||||
|
|
|
|||
|
|
@ -122,6 +122,16 @@ const QueryForm = ({
|
|||
{ leading: true }
|
||||
);
|
||||
|
||||
const debounceSQL = useDebouncedCallback((sql: string) => {
|
||||
let valid = true;
|
||||
const { valid: isValidated, errors: newErrors } = validateQuerySQL(sql);
|
||||
valid = isValidated;
|
||||
|
||||
setErrors({
|
||||
...newErrors,
|
||||
});
|
||||
}, 500);
|
||||
|
||||
queryIdForEdit = queryIdForEdit || 0;
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -129,14 +139,7 @@ const QueryForm = ({
|
|||
debounceCompatiblePlatforms(lastEditedQueryBody);
|
||||
}
|
||||
|
||||
let valid = true;
|
||||
const { valid: isValidated, errors: newErrors } = validateQuerySQL(
|
||||
lastEditedQueryBody
|
||||
);
|
||||
valid = isValidated;
|
||||
setErrors({
|
||||
...newErrors,
|
||||
});
|
||||
debounceSQL(lastEditedQueryBody);
|
||||
}, [lastEditedQueryBody, lastEditedQueryId]);
|
||||
|
||||
const hasTeamMaintainerPermissions = isEditMode
|
||||
|
|
|
|||
Loading…
Reference in a new issue