Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pluginJs from "@eslint/js";
import pluginReact from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import globals from "globals";
import tseslint from "typescript-eslint";
Expand All @@ -11,8 +12,20 @@ export default [
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
reactHooks.configs.flat.recommended,
{
rules: {
"react-hooks/exhaustive-deps": [
"warn",
// I left this commented out because it causes infinite loops in the codebase,
// but may useful for mass-refactoring.
// {
// enableDangerousAutofixThisMayCauseInfiniteLoops: true,
// },
],
"react-hooks/set-state-in-effect": "warn",
"react-hooks/refs": "warn",
"react-hooks/immutability": "warn",
"@typescript-eslint/no-explicit-any": "off",
"react/react-in-jsx-scope": "off",
"@typescript-eslint/no-empty-object-type": "off",
Expand Down
42 changes: 40 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:headed": "playwright test --headed",
"lint": "eslint src --config eslint.config.js",
"lint": "eslint --quiet src --config eslint.config.js",
"lint:all": "eslint src --config eslint.config.js",
"format": "prettier --write .",
"typecheck": "tsc --noEmit",
"gh-pages": "npm run build:ghpages && gh-pages -d dist",
Expand Down Expand Up @@ -115,6 +116,7 @@
"@vitest/coverage-v8": "^3.2.4",
"eslint": "^9.39.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"globals": "^16.5.0",
"jsdom": "^27.2.0",
"knip": "^5.63.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const InputValueEditor = ({

setValidationError(null);
},
[input.name, currentSubgraphSpec],
[input.name, componentSpec],
);

const hasChanges = useCallback(() => {
Expand Down Expand Up @@ -203,7 +203,7 @@ export const InputValueEditor = ({
void navigator.clipboard.writeText(inputValue.trim());
notify("Input value copied to clipboard", "success");
}
}, [inputValue]);
}, [inputValue, notify]);

const deleteNode = useCallback(async () => {
if (!currentSubgraphSpec.inputs) return;
Expand Down Expand Up @@ -258,17 +258,21 @@ export const InputValueEditor = ({
}, []);

useEffect(() => {
setInputValue(initialInputValue);
setInputName(input.name);
setInputType(input.type?.toString() ?? "any");
setInputOptional(initialIsOptional);
setValidationError(null);
queueMicrotask(() => {
setInputValue(initialInputValue);
setInputName(input.name);
setInputType(input.type?.toString() ?? "any");
setInputOptional(initialIsOptional);
setValidationError(null);
});
}, [input, initialInputValue, initialIsOptional]);

useEffect(() => {
if (triggerSave) {
saveChanges();
setTriggerSave(false);
queueMicrotask(() => {
saveChanges();
setTriggerSave(false);
});
}
}, [triggerSave, saveChanges]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const OutputNameEditor = ({

setValidationError(null);
},
[currentSubgraphSpec, output.name],
[componentSpec, output.name],
);

const deleteNode = useCallback(async () => {
Expand Down Expand Up @@ -161,7 +161,9 @@ export const OutputNameEditor = ({
]);

useEffect(() => {
setOutputName(output.name);
queueMicrotask(() => {
setOutputName(output.name);
});
}, [output.name]);

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/Home/PipelineSection/BulkActionsBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const BulkActionsBar = ({
const errorMessage = getErrorMessage(error);
notify("Failed to delete some pipelines: " + errorMessage, "error");
}
}, [selectedPipelines, onDeleteSuccess]);
}, [selectedPipelines, onDeleteSuccess, notify]);

return (
<div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-background border border-border rounded-lg shadow-lg p-4 z-50">
Expand Down
2 changes: 1 addition & 1 deletion src/components/Home/PipelineSection/PipelineRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const PipelineRow = ({
};

await deletePipeline(name, deleteCallback);
}, [name]);
}, [name, onDelete]);

const handleClick = useCallback((e: MouseEvent) => {
// Prevent row click when clicking on the checkbox
Expand Down
2 changes: 1 addition & 1 deletion src/components/Home/RunSection/RunRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const RunRow = ({ run }: { run: PipelineRunResponse }) => {
navigator.clipboard.writeText(createdBy);
notify(`"${createdBy}" copied to clipboard`, "success");
},
[createdBy],
[createdBy, notify],
);

const statusCounts = convertExecutionStatsToStatusCounts(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const CancelPipelineRunButton = ({
} catch (error) {
notify(`Error cancelling run: ${error}`, "error");
}
}, [runId, available]);
}, [runId, available, notify, cancelPipeline]);

const onClick = useCallback(() => {
setIsOpen(true);
Expand Down
9 changes: 6 additions & 3 deletions src/components/PipelineRun/components/RerunPipelineButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ export const RerunPipelineButton = ({
const { awaitAuthorization, isAuthorized } = useAwaitAuthorization();
const { getToken } = useAuthLocalStorage();

const onSuccess = useCallback((response: PipelineRun) => {
navigate({ to: `${APP_ROUTES.RUNS}/${response.id}` });
}, []);
const onSuccess = useCallback(
(response: PipelineRun) => {
navigate({ to: `${APP_ROUTES.RUNS}/${response.id}` });
},
[navigate],
);

const onError = useCallback(
(error: Error | string) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { LogOutIcon } from "lucide-react";
import { useEffectEvent, useSyncExternalStore } from "react";
import { useCallback, useSyncExternalStore } from "react";

import { Icon } from "@/components/ui/icon";
import { Spinner } from "@/components/ui/spinner";
Expand Down Expand Up @@ -52,10 +52,11 @@ export function AuthorizedUserProfile() {
);
const profile = localTokenStorage.getJWT();

const onLogoutSuccess = useEffectEvent(() => {
const onLogoutSuccess = useCallback(() => {
queryClient.invalidateQueries({ queryKey: ["user"] });
localTokenStorage.clear();
});
}, [queryClient, localTokenStorage]);

const { mutate: logout, isPending } = useLogout({
onSuccess: onLogoutSuccess,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ export const PythonComponentEditor = withSuspenseWrapper(
setValidationErrors(errors);
}
},
[yamlGenerator, onComponentTextChange, yamlGeneratorOptions],
[
yamlGenerator,
yamlGeneratorOptions,
onComponentTextChange,
onErrorsChange,
],
);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const YamlComponentEditor = withSuspenseWrapper(
setValidationErrors([]);
onErrorsChange([]);
},
[onComponentTextChange, validateComponentSpec],
[onComponentTextChange, onErrorsChange, validateComponentSpec],
);

return (
Expand Down
14 changes: 9 additions & 5 deletions src/components/shared/Dialogs/BackendConfigurationDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,18 @@ const BackendConfigurationDialog = ({
}, [isConfiguredFromEnv, isConfiguredFromRelativePath, setOpen]);

useEffect(() => {
setIsEnvConfig(isConfiguredFromEnv);
setIsRelativePathConfig(isConfiguredFromRelativePath);
queueMicrotask(() => {
setIsEnvConfig(isConfiguredFromEnv);
setIsRelativePathConfig(isConfiguredFromRelativePath);
});
}, [isConfiguredFromEnv, isConfiguredFromRelativePath]);

useEffect(() => {
setInputBackendUrl(
isConfiguredFromEnv || isConfiguredFromRelativePath ? "" : backendUrl,
);
queueMicrotask(() => {
setInputBackendUrl(
isConfiguredFromEnv || isConfiguredFromRelativePath ? "" : backendUrl,
);
});
}, [isConfiguredFromEnv, isConfiguredFromRelativePath, backendUrl]);

const hasBackendConfigured =
Expand Down
17 changes: 10 additions & 7 deletions src/components/shared/Dialogs/ComponentDetailsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,15 @@ const ComponentDetails = ({
setIsEditDialogOpen(false);
}, []);

const onOpenChange = useCallback((open: boolean) => {
setOpen(open);
if (!open) {
onClose?.();
}
}, []);
const onOpenChange = useCallback(
(open: boolean) => {
setOpen(open);
if (!open) {
onClose?.();
}
},
[onClose],
);

const handleEditComponent = useCallback(() => {
setIsEditDialogOpen(true);
Expand All @@ -227,7 +230,7 @@ const ComponentDetails = ({
);

return [...actions, EditButton];
}, [actions, hasEnabledInAppEditor, handleEditComponent]);
}, [hasEnabledInAppEditor, actions, handleEditComponent, displayName]);

return (
<>
Expand Down
8 changes: 4 additions & 4 deletions src/components/shared/Dialogs/ComponentDuplicateDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const ComponentDuplicateDialog = ({
);
setNewDigest(digest);
}
}, [newComponent, newName]);
}, [newComponent, newComponentDigest, newName]);

const handleOnOpenChange = useCallback(
(open: boolean) => {
Expand All @@ -82,7 +82,7 @@ const ComponentDuplicateDialog = ({

setClose();
},
[handleImportComponent, setClose],
[handleImportComponent, newComponent, setClose],
);

const handleReplaceAndImport = useCallback(async () => {
Expand All @@ -94,7 +94,7 @@ const ComponentDuplicateDialog = ({
handleImportComponent(yamlString);

setClose();
}, [handleImportComponent, setClose]);
}, [existingComponent?.name, handleImportComponent, newComponent, setClose]);

const handleCancel = useCallback(() => {
setClose();
Expand All @@ -118,7 +118,7 @@ const ComponentDuplicateDialog = ({
}

generateNewDigest();
}, [existingComponent, newComponent]);
}, [existingComponent, newComponent, newComponentDigest]);

return (
<Dialog open={open} onOpenChange={handleOnOpenChange}>
Expand Down
10 changes: 7 additions & 3 deletions src/components/shared/Dialogs/InputDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,19 @@ export function InputDialog({

useEffect(() => {
if (isOpen) {
setValue(defaultValue);
setError(null);
queueMicrotask(() => {
setValue(defaultValue);
setError(null);
});
}
}, [isOpen, defaultValue]);

useEffect(() => {
if (isOpen && defaultValue && validate) {
const validationError = validate(defaultValue.trim());
setError(validationError);
queueMicrotask(() => {
setError(validationError);
});
}
}, [isOpen, defaultValue, validate]);

Expand Down
Loading