", () => {
p.dispatch = jest.fn(() => Promise.resolve());
const wrapper = mount(
);
clickButton(wrapper, 2, "delete");
- const expectedUuid = p.current && p.current.uuid;
+ const expectedUuid = p.current?.uuid;
expect(destroy).toHaveBeenCalledWith(expectedUuid);
});
@@ -74,7 +74,7 @@ describe("
", () => {
const p = fakeProps();
const wrapper = mount(
);
clickButton(wrapper, 0, "save", { partial_match: true });
- const expectedUuid = p.current && p.current.uuid;
+ const expectedUuid = p.current?.uuid;
expect(save).toHaveBeenCalledWith(expectedUuid);
});
});
diff --git a/frontend/resources/__tests__/selectors_test.ts b/frontend/resources/__tests__/selectors_test.ts
index 84accec40..49f4a5678 100644
--- a/frontend/resources/__tests__/selectors_test.ts
+++ b/frontend/resources/__tests__/selectors_test.ts
@@ -177,7 +177,7 @@ describe("maybeGetSequence", () => {
const i = buildResourceIndex([s]);
const result = Selector.maybeGetSequence(i.index, s.uuid);
expect(result).toBeTruthy();
- result && expect(result.uuid).toBe(s.uuid);
+ expect(result?.uuid).toBe(s.uuid);
});
});
diff --git a/frontend/resources/reducer_support.ts b/frontend/resources/reducer_support.ts
index ebc0385e5..9b43e5b08 100644
--- a/frontend/resources/reducer_support.ts
+++ b/frontend/resources/reducer_support.ts
@@ -188,7 +188,7 @@ const reindexAllSequences = (i: ResourceIndex) => {
const mapper = reindexSequences(i);
betterCompact(Object.keys(i.byKind["Sequence"]).map(uuid => {
const resource = i.references[uuid];
- return (resource && resource.kind == "Sequence") ? resource : undefined;
+ return (resource?.kind == "Sequence") ? resource : undefined;
})).map(mapper);
};
@@ -283,7 +283,7 @@ const AFTER_HOOKS: IndexerHook = {
FbosConfig: (i) => {
const conf = getFbosConfig(i);
- if (conf && conf.body.boot_sequence_id) {
+ if (conf?.body.boot_sequence_id) {
const { boot_sequence_id } = conf.body;
const tracker = i.inUse["Sequence.FbosConfig"];
const uuid = i.byKindAndId[joinKindAndId("Sequence", boot_sequence_id)];
@@ -345,7 +345,7 @@ export const indexUpsert: IndexUpsert = (db, resources, strategy) => {
const { kind } = arrayUnwrap(resources);
// Clean up indexes (if needed)
const before = BEFORE_HOOKS[kind];
- before && before(db, strategy);
+ before?.(db, strategy);
// Run indexers
ups.map(callback => {
@@ -354,14 +354,14 @@ export const indexUpsert: IndexUpsert = (db, resources, strategy) => {
// Finalize indexing (if needed)
const after = AFTER_HOOKS[kind];
- after && after(db, strategy);
+ after?.(db, strategy);
};
export function indexRemove(db: ResourceIndex, resource: TaggedResource) {
downs.map(callback => arrayWrap(resource).map(r => callback(r, db)));
// Finalize indexing (if needed)
const after = AFTER_HOOKS[resource.kind];
- after && after(db, "ongoing");
+ after?.(db, "ongoing");
}
export const beforeEach = (state: RestResources,
diff --git a/frontend/resources/selectors.ts b/frontend/resources/selectors.ts
index 3f7044b5c..2085525ce 100644
--- a/frontend/resources/selectors.ts
+++ b/frontend/resources/selectors.ts
@@ -77,7 +77,7 @@ export function findPointerByTypeAndId(index: ResourceIndex,
const uuid = "" + index.byKindAndId[pni];
const resource = index.references[uuid];
- if (resource && resource.kind === "Point") {
+ if (resource?.kind === "Point") {
return resource;
} else {
// We might have a sequence dependency leak if this exception is ever
@@ -204,7 +204,7 @@ export function maybeGetTimeSettings(index: ResourceIndex): TimeSettings {
export function maybeGetDevice(index: ResourceIndex): TaggedDevice | undefined {
const dev = index.references[Object.keys(index.byKind.Device)[0] || "nope"];
- return (dev && dev.kind === "Device") ?
+ return (dev?.kind === "Device") ?
dev : undefined;
}
@@ -227,7 +227,7 @@ export function maybeFetchUser(index: ResourceIndex):
if (user && sanityCheck(user) && list.length > 1) {
throw new Error("PROBLEM: Expected 1 user. Got: " + list.length);
}
- if ((list.length === 1) && user && user.kind === "User") {
+ if ((list.length === 1) && user?.kind === "User") {
return user;
} else {
return undefined;
diff --git a/frontend/resources/sequence_meta.ts b/frontend/resources/sequence_meta.ts
index 2a58274de..be03fff20 100644
--- a/frontend/resources/sequence_meta.ts
+++ b/frontend/resources/sequence_meta.ts
@@ -50,7 +50,7 @@ export const determineVector =
return ts ? ts.body : undefined;
case "identifier":
const variable = maybeFindVariable(node.args.label, resources, uuid);
- return variable && variable.vector;
+ return variable?.vector;
}
return undefined;
};
diff --git a/frontend/sequences/__tests__/sequence_editor_middle_active_test.tsx b/frontend/sequences/__tests__/sequence_editor_middle_active_test.tsx
index b6d641419..d51394e5b 100644
--- a/frontend/sequences/__tests__/sequence_editor_middle_active_test.tsx
+++ b/frontend/sequences/__tests__/sequence_editor_middle_active_test.tsx
@@ -127,7 +127,7 @@ describe("
", () => {
p.dispatch = dispatch;
const wrapper = mount(
);
const props = wrapper.find("DropArea").props() as DropAreaProps;
- props.callback && props.callback("key");
+ props.callback?.("key");
dispatch.mock.calls[0][0](() =>
({ value: 1, intent: "step_splice", draggerId: 2 }));
expect(splice).toHaveBeenCalledWith(expect.objectContaining({
diff --git a/frontend/sequences/sequence_editor_middle_active.tsx b/frontend/sequences/sequence_editor_middle_active.tsx
index 8a8c18886..0f1436d79 100644
--- a/frontend/sequences/sequence_editor_middle_active.tsx
+++ b/frontend/sequences/sequence_editor_middle_active.tsx
@@ -148,7 +148,7 @@ const SequenceBtnGroup = ({
onClick={() => {
const confirm = getWebAppConfigValue(
BooleanSetting.confirm_sequence_deletion);
- const force = isUndefined(confirm) ? false : !confirm;
+ const force = !(confirm ?? true);
dispatch(destroy(sequence.uuid, force))
.then(() => push("/app/sequences/"));
}}>
diff --git a/frontend/sequences/state_to_props.ts b/frontend/sequences/state_to_props.ts
index 7a4902cf3..b7377fe41 100644
--- a/frontend/sequences/state_to_props.ts
+++ b/frontend/sequences/state_to_props.ts
@@ -19,7 +19,7 @@ import {
export function mapStateToProps(props: Everything): Props {
const uuid = props.resources.consumers.sequences.current;
const sequence = uuid ? findSequence(props.resources.index, uuid) : undefined;
- sequence && (sequence.body.body || []).map(x => getStepTag(x));
+ (sequence?.body.body || []).map(x => getStepTag(x));
const fwConfig = validFwConfig(getFirmwareConfig(props.resources.index));
const { mcu_params } = props.bot.hardware;
diff --git a/frontend/sequences/step_tiles/__tests__/tile_execute_script_test.tsx b/frontend/sequences/step_tiles/__tests__/tile_execute_script_test.tsx
index e94b49fc7..a9980223e 100644
--- a/frontend/sequences/step_tiles/__tests__/tile_execute_script_test.tsx
+++ b/frontend/sequences/step_tiles/__tests__/tile_execute_script_test.tsx
@@ -83,7 +83,7 @@ describe("
", () => {
it("shows special 1st-party Farmware name", () => {
const p = fakeProps();
(p.currentStep as ExecuteScript).args.label = "plant-detection";
- p.farmwareData && p.farmwareData.farmwareNames.push("plant-detection");
+ p.farmwareData?.farmwareNames.push("plant-detection");
const wrapper = mount(
);
expect(wrapper.find("label").length).toEqual(1);
expect(wrapper.text()).toContain("Weed Detector");
diff --git a/frontend/sequences/step_tiles/tile_execute_script.tsx b/frontend/sequences/step_tiles/tile_execute_script.tsx
index 5d764b23f..27a6187bd 100644
--- a/frontend/sequences/step_tiles/tile_execute_script.tsx
+++ b/frontend/sequences/step_tiles/tile_execute_script.tsx
@@ -54,7 +54,7 @@ export function TileExecuteScript(props: StepParams) {
/** Configs (inputs) from Farmware manifest for
. */
const currentFarmwareConfigDefaults = (fwName: string): FarmwareConfig[] => {
- return farmwareData && farmwareData.farmwareConfigs[fwName]
+ return farmwareData?.farmwareConfigs[fwName]
? farmwareData.farmwareConfigs[fwName]
: [];
};
diff --git a/frontend/sequences/step_tiles/tile_if/__tests__/index_test.tsx b/frontend/sequences/step_tiles/tile_if/__tests__/index_test.tsx
index b9b5f9215..12c7f39a9 100644
--- a/frontend/sequences/step_tiles/tile_if/__tests__/index_test.tsx
+++ b/frontend/sequences/step_tiles/tile_if/__tests__/index_test.tsx
@@ -24,8 +24,8 @@ import {
const fakeResourceIndex = buildResourceIndex(FAKE_RESOURCES).index;
const fakeTaggedSequence = fakeResourceIndex
.references[Object.keys(fakeResourceIndex.byKind.Sequence)[0]] as TaggedSequence;
-const fakeId = fakeTaggedSequence && fakeTaggedSequence.body.id || 0;
-const fakeName = fakeTaggedSequence && fakeTaggedSequence.body.name || "";
+const fakeId = fakeTaggedSequence.body.id || 0;
+const fakeName = fakeTaggedSequence.body.name || "";
const expectedItem = { label: fakeName, value: fakeId };
function fakeProps(): IfParams {
diff --git a/frontend/sync/actions.ts b/frontend/sync/actions.ts
index edb942a24..3aa64e4df 100644
--- a/frontend/sync/actions.ts
+++ b/frontend/sync/actions.ts
@@ -30,7 +30,7 @@ export const newTaggedResource =
(kind: T["kind"],
return {
kind: kind as TaggedResource["kind"],
body: body as TaggedResource["body"],
- uuid: generateUuid(body && body.id ? body.id : undefined, kind),
+ uuid: generateUuid(body?.id, kind),
specialStatus
} as T;
});
diff --git a/frontend/tools/components/toolbay_list.tsx b/frontend/tools/components/toolbay_list.tsx
index 7549d684e..76c722556 100644
--- a/frontend/tools/components/toolbay_list.tsx
+++ b/frontend/tools/components/toolbay_list.tsx
@@ -11,7 +11,7 @@ export class ToolBayList extends React.Component {
ToolSlotListItem = (slot: TaggedToolSlotPointer, index: number) => {
const { getToolByToolSlotUUID } = this.props;
const tool = getToolByToolSlotUUID(slot.uuid);
- const name = (tool && tool.body.name) || t("None");
+ const name = (tool?.body.name) || t("None");
return
{slot.body.gantry_mounted ? t("Gantry") : slot.body.x}
diff --git a/frontend/ui/back_arrow.tsx b/frontend/ui/back_arrow.tsx
index b8e9d5b44..f317111bf 100644
--- a/frontend/ui/back_arrow.tsx
+++ b/frontend/ui/back_arrow.tsx
@@ -6,7 +6,7 @@ interface BackArrowProps {
export function BackArrow(props: BackArrowProps) {
const onClick = () => {
history.back();
- props.onClick && props.onClick();
+ props.onClick?.();
};
return
diff --git a/frontend/ui/blurable_input.tsx b/frontend/ui/blurable_input.tsx
index 3b89ff3cb..e2d72a659 100644
--- a/frontend/ui/blurable_input.tsx
+++ b/frontend/ui/blurable_input.tsx
@@ -47,7 +47,7 @@ export class BlurableInput extends React.Component> {
withinLimits = (options?: { toasts?: boolean }): boolean => {
const onError = (msg: string) => {
this.setState({ error: msg });
- options && options.toasts && error(msg);
+ options?.toasts && error(msg);
};
if (this.props.type === "number") {
diff --git a/frontend/util/__tests__/util_test.ts b/frontend/util/__tests__/util_test.ts
index cf1e89ea4..fcd4f2632 100644
--- a/frontend/util/__tests__/util_test.ts
+++ b/frontend/util/__tests__/util_test.ts
@@ -131,18 +131,6 @@ describe("util", () => {
});
});
- describe("isUndefined()", () => {
- it("undefined", () => {
- const result = Util.isUndefined(undefined);
- expect(result).toBeTruthy();
- });
-
- it("defined", () => {
- const result = Util.isUndefined({});
- expect(result).toBeFalsy();
- });
- });
-
describe("randomColor()", () => {
it("only picks valid colors", () => {
times(Util.colors.length * 1.5, () =>
diff --git a/frontend/util/errors.ts b/frontend/util/errors.ts
index eec02cc82..0e7a43488 100644
--- a/frontend/util/errors.ts
+++ b/frontend/util/errors.ts
@@ -28,7 +28,7 @@ export function prettyPrintApiErrors(err: AxiosErrorResponse) {
function safelyFetchErrors(err: AxiosErrorResponse): Dictionary {
// In case the interpreter gives us an oddball error message.
- if (err && err.response && err.response.data) {
+ if (err.response?.data) {
return err.response.data;
} else {
return {
@@ -42,7 +42,7 @@ export function bail(message: string): never {
}
export const catchErrors = (error: Error) => {
- if (window.Rollbar && window.Rollbar.error) {
+ if (window.Rollbar?.error) {
window.Rollbar.error(error);
} else {
throw error;
diff --git a/frontend/util/util.ts b/frontend/util/util.ts
index 45ae09d9f..517c79924 100644
--- a/frontend/util/util.ts
+++ b/frontend/util/util.ts
@@ -14,7 +14,6 @@ import {
sortBy,
merge,
isNumber,
- isUndefined as lodashIsUndefined
} from "lodash";
import { t } from "../i18next_wrapper";
@@ -88,10 +87,6 @@ export type CowardlyDictionary = Dictionary;
*/
export const NOT_SAVED = -1;
-export function isUndefined(x: object | undefined): x is undefined {
- return lodashIsUndefined(x);
-}
-
/** Better than Array.proto.filter and compact() because the type checker
* knows what's going on.
*/
@@ -190,7 +185,7 @@ export function validBotLocationData(
*/
export function validFwConfig(config: TaggedFirmwareConfig | undefined):
TaggedFirmwareConfig["body"] | undefined {
- return (config && config.body.api_migrated)
+ return (config?.body.api_migrated)
? config.body
: undefined;
}
@@ -200,7 +195,7 @@ export function validFwConfig(config: TaggedFirmwareConfig | undefined):
*/
export function validFbosConfig(
config: TaggedFbosConfig | undefined): TaggedFbosConfig["body"] | undefined {
- return (config && config.body.api_migrated)
+ return (config?.body.api_migrated)
? config.body
: undefined;
}
@@ -232,4 +227,4 @@ export const parseIntInput = (input: string): number => {
export const timeFormatString =
(timeSettings: TimeSettings | undefined): string =>
- (timeSettings && timeSettings.hour24) ? "H:mm" : "h:mma";
+ (timeSettings?.hour24) ? "H:mm" : "h:mma";