diff --git a/.github/workflows/lint-js.yml b/.github/workflows/lint-js.yml
new file mode 100644
index 000000000..0590e8a38
--- /dev/null
+++ b/.github/workflows/lint-js.yml
@@ -0,0 +1,51 @@
+name: Lint Frontend
+
+on:
+ pull_request:
+ paths:
+ - "src/frontend/**"
+
+env:
+ NODE_VERSION: "21"
+
+jobs:
+ run-linters:
+ name: Run linters
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ id: setup-node
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Cache Node.js dependencies
+ uses: actions/cache@v4
+ id: npm-cache
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ hashFiles('src/frontend/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-
+
+ - name: Install Node.js dependencies
+ run: |
+ cd src/frontend
+ npm ci
+ if: ${{ steps.setup-node.outputs.cache-hit != 'true' }}
+
+ - name: Run linters
+ uses: wearerequired/lint-action@v1
+ with:
+ github_token: ${{ secrets.github_token }}
+ auto_fix: true
+ git_email: "gabriel@langflow.org"
+ # Enable linters
+ eslint: true
+ prettier: true
+ prettier_args: '--write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore'
+
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint-py.yml
similarity index 75%
rename from .github/workflows/lint.yml
rename to .github/workflows/lint-py.yml
index 3c5898369..6182f91fc 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint-py.yml
@@ -1,17 +1,12 @@
-name: lint
+name: Lint Python
on:
- push:
- branches: [main]
- paths:
- - "poetry.lock"
- - "pyproject.toml"
- - "src/backend/**"
pull_request:
paths:
- "poetry.lock"
- "pyproject.toml"
- "src/backend/**"
+ - "tests/**"
env:
POETRY_VERSION: "1.8.2"
@@ -45,6 +40,13 @@ jobs:
path: |
./.mypy_cache
key: ${{ runner.os }}-mypy-${{ hashFiles('**/pyproject.toml') }}
- - name: Lint check
- run: |
- make lint
+ - name: Run linters
+ uses: wearerequired/lint-action@v1
+ with:
+ github_token: ${{ secrets.github_token }}
+ # Enable linters
+ git_email: "gabriel@langflow.org"
+ mypy: true
+ mypy_args: '--namespace-packages -p "langflow"'
+ mypy_command_prefix: "poetry run"
+
diff --git a/.github/workflows/matchers/ruff.json b/.github/workflows/matchers/ruff.json
new file mode 100644
index 000000000..53b21be23
--- /dev/null
+++ b/.github/workflows/matchers/ruff.json
@@ -0,0 +1,14 @@
+{
+ "problemMatcher": [
+ {
+ "owner": "ruff",
+ "pattern": [
+ {
+ "regexp": "^(Would reformat): (.+)$",
+ "message": 1,
+ "file": 2
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.github/workflows/style-check-py.yml b/.github/workflows/style-check-py.yml
new file mode 100644
index 000000000..4063cd48d
--- /dev/null
+++ b/.github/workflows/style-check-py.yml
@@ -0,0 +1,39 @@
+name: Ruff Style Check
+
+on:
+ pull_request:
+ paths:
+ - "poetry.lock"
+ - "pyproject.toml"
+ - "src/backend/**"
+ - "tests/**"
+
+env:
+ POETRY_VERSION: "1.8.2"
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version:
+ - "3.12"
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
+ uses: "./.github/actions/poetry_caching"
+ with:
+ python-version: ${{ matrix.python-version }}
+ poetry-version: ${{ env.POETRY_VERSION }}
+ cache-key: ${{ runner.os }}-poetry-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
+ - name: Install Python dependencies
+ run: |
+ poetry env use ${{ matrix.python-version }}
+ poetry install
+ - name: Register problem matcher
+ run: echo "::add-matcher::.github/workflows/matchers/ruff.json"
+ - name: Run Ruff
+ run: poetry run ruff check --output-format=github .
+ - name: Run Ruff format
+ run: poetry run ruff format --check .
+
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d03df05b9..16599a199 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,18 +1,5 @@
fail_fast: true
repos:
- - repo: https://github.com/pre-commit/mirrors-eslint
- rev: "v9.1.1"
- hooks:
- - id: eslint
- files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
- types: [file]
- args: ["--fix", "--no-warn-ignored"]
- additional_dependencies:
- - eslint@9.1.1
- - eslint-plugin-prettier
- - eslint-config-prettier
- - prettier
- - eslint-plugin-react@latest
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
@@ -25,16 +12,3 @@ repos:
args:
- --fix=lf
- id: trailing-whitespace
- - repo: https://github.com/astral-sh/ruff-pre-commit
- # Ruff version.
- rev: v0.4.2
- hooks:
- # Run the linter.
- - id: ruff
- # Python
- files: \.py$
- types: [file]
- # Run the formatter.
- - id: ruff-format
- files: \.py$
- types: [file]
diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx
index 849244999..b84c0d792 100644
--- a/src/frontend/src/App.tsx
+++ b/src/frontend/src/App.tsx
@@ -18,13 +18,13 @@ import { autoLogin, getGlobalVariables, getHealth } from "./controllers/API";
import { setupAxiosDefaults } from "./controllers/API/utils";
import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path";
import Router from "./routes";
+import { Case } from "./shared/components/caseComponent";
import useAlertStore from "./stores/alertStore";
import { useDarkStore } from "./stores/darkStore";
import useFlowsManagerStore from "./stores/flowsManagerStore";
import { useFolderStore } from "./stores/foldersStore";
import { useGlobalVariablesStore } from "./stores/globalVariablesStore/globalVariables";
import { useStoreStore } from "./stores/storeStore";
-import { useTypesStore } from "./stores/typesStore";
export default function App() {
useTrackLastVisitedPath();
@@ -43,10 +43,8 @@ export default function App() {
const { isAuthenticated, login, setUserData, setAutoLogin, getUser } =
useContext(AuthContext);
- const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
const setLoading = useAlertStore((state) => state.setLoading);
const fetchApiData = useStoreStore((state) => state.fetchApiData);
- const getTypes = useTypesStore((state) => state.getTypes);
const refreshVersion = useDarkStore((state) => state.refreshVersion);
const refreshStars = useDarkStore((state) => state.refreshStars);
const setGlobalVariables = useGlobalVariablesStore(
@@ -56,8 +54,7 @@ export default function App() {
const navigate = useNavigate();
const dark = useDarkStore((state) => state.dark);
- const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
- const loadingFolders = useFolderStore((state) => state.loading);
+ const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
const [isLoadingHealth, setIsLoadingHealth] = useState(false);
@@ -115,13 +112,13 @@ export default function App() {
if (isAuthenticated) {
try {
await setupAxiosDefaults();
- await getFoldersApi();
- await getTypes();
- await refreshFlows();
+
const res = await getGlobalVariables();
setGlobalVariables(res);
+
checkHasStore();
fetchApiData();
+
resolve();
} catch (error) {
console.error("Failed to fetch data:", error);
@@ -174,6 +171,8 @@ export default function App() {
}
};
+ const isLoadingApplication = isLoading || isLoadingFolders;
+
return (
//need parent component with width and height
@@ -196,15 +195,15 @@ export default function App() {
>
}
- {isLoading || loadingFolders ? (
+
- ) : (
- <>
-
- >
- )}
+
+
+
+
+
>
diff --git a/src/frontend/src/components/sidebarComponent/components/sideBarFolderButtons/index.tsx b/src/frontend/src/components/sidebarComponent/components/sideBarFolderButtons/index.tsx
index 234eb9304..ff5c17a15 100644
--- a/src/frontend/src/components/sidebarComponent/components/sideBarFolderButtons/index.tsx
+++ b/src/frontend/src/components/sidebarComponent/components/sideBarFolderButtons/index.tsx
@@ -37,8 +37,8 @@ const SideBarFoldersButtonsComponent = ({
const currentFolder = pathname.split("/");
const urlWithoutPath = pathname.split("/").length < 4;
const myCollectionId = useFolderStore((state) => state.myCollectionId);
- const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
+ const refreshFolders = useFolderStore((state) => state.refreshFolders);
const checkPathName = (itemId: string) => {
if (urlWithoutPath && itemId === myCollectionId) {
@@ -85,7 +85,7 @@ const SideBarFoldersButtonsComponent = ({
function addNewFolder() {
addFolder({ name: "New Folder", parent_id: null, description: "" }).then(
(res) => {
- getFoldersApi(true);
+ refreshFolders();
}
);
}
diff --git a/src/frontend/src/components/sidebarComponent/hooks/use-on-file-drop.tsx b/src/frontend/src/components/sidebarComponent/hooks/use-on-file-drop.tsx
index f10733468..ab4b9d27f 100644
--- a/src/frontend/src/components/sidebarComponent/hooks/use-on-file-drop.tsx
+++ b/src/frontend/src/components/sidebarComponent/hooks/use-on-file-drop.tsx
@@ -16,7 +16,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
);
const setErrorData = useAlertStore((state) => state.setErrorData);
- const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
+ const refreshFolders = useFolderStore((state) => state.refreshFolders);
const flows = useFlowsManagerStore((state) => state.flows);
const triggerFolderChange = (folderId) => {
@@ -118,7 +118,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
setFolderIdDragging("");
updateFlowInDatabase(updatedFlow).then(() => {
- getFoldersApi(true);
+ refreshFolders();
triggerFolderChange(folderId);
});
};
@@ -129,7 +129,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
setFolderDragging(false);
setFolderIdDragging("");
uploadFlowsFromFolders(formData).then(() => {
- getFoldersApi(true);
+ refreshFolders();
triggerFolderChange(folderId);
});
};
diff --git a/src/frontend/src/components/sidebarComponent/index.tsx b/src/frontend/src/components/sidebarComponent/index.tsx
index efec5da1e..8cdbe5907 100644
--- a/src/frontend/src/components/sidebarComponent/index.tsx
+++ b/src/frontend/src/components/sidebarComponent/index.tsx
@@ -28,7 +28,7 @@ export default function SidebarNav({
}: SidebarNavProps) {
const location = useLocation();
const pathname = location.pathname;
- const loadingFolders = useFolderStore((state) => state.loading);
+ const loadingFolders = useFolderStore((state) => state.isLoadingFolders);
const folders = useFolderStore((state) => state.folders);
const pathValues = ["folder", "components", "flows", "all"];
diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx
index 126d4f3f2..954d7d257 100644
--- a/src/frontend/src/components/tableComponent/index.tsx
+++ b/src/frontend/src/components/tableComponent/index.tsx
@@ -105,7 +105,7 @@ const TableComponent = forwardRef<
}
}, 50);
setTimeout(() => {
- realRef.current.api.hideOverlay();
+ realRef?.current?.api?.hideOverlay();
}, 1000);
if (props.onGridReady) props.onGridReady(params);
};
diff --git a/src/frontend/src/contexts/authContext.tsx b/src/frontend/src/contexts/authContext.tsx
index 1817447f1..f6b81a235 100644
--- a/src/frontend/src/contexts/authContext.tsx
+++ b/src/frontend/src/contexts/authContext.tsx
@@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom";
import Cookies from "universal-cookie";
import { getLoggedUser, requestLogout } from "../controllers/API";
import useAlertStore from "../stores/alertStore";
+import { useFolderStore } from "../stores/foldersStore";
import { Users } from "../types/api";
import { AuthContextType } from "../types/contexts/auth";
@@ -42,7 +43,8 @@ export function AuthProvider({ children }): React.ReactElement {
const [apiKey, setApiKey] = useState
(
cookies.get("apikey_tkn_lflw")
);
- // const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
+
+ const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
useEffect(() => {
const storedAccessToken = cookies.get("access_token_lf");
@@ -64,7 +66,8 @@ export function AuthProvider({ children }): React.ReactElement {
setUserData(user);
const isSuperUser = user!.is_superuser;
setIsAdmin(isSuperUser);
- // await getFoldersApi(true);
+
+ getFoldersApi(true, true);
})
.catch((error) => {
setLoading(false);
diff --git a/src/frontend/src/controllers/API/api.tsx b/src/frontend/src/controllers/API/api.tsx
index 2a305cf5a..6bd73f5f1 100644
--- a/src/frontend/src/controllers/API/api.tsx
+++ b/src/frontend/src/controllers/API/api.tsx
@@ -87,6 +87,7 @@ function ApiInterceptor() {
if (!checkRequest) {
controller.abort("Duplicate Request");
+ console.error("Duplicate Request");
}
const accessToken = cookies.get("access_token_lf");
diff --git a/src/frontend/src/controllers/API/helpers/check-duplicate-requests.ts b/src/frontend/src/controllers/API/helpers/check-duplicate-requests.ts
index 6486de541..ec3c74268 100644
--- a/src/frontend/src/controllers/API/helpers/check-duplicate-requests.ts
+++ b/src/frontend/src/controllers/API/helpers/check-duplicate-requests.ts
@@ -4,9 +4,10 @@ export function checkDuplicateRequestAndStoreRequest(config) {
const lastUrl = localStorage.getItem("lastUrlCalled");
const lastMethodCalled = localStorage.getItem("lastMethodCalled");
const lastRequestTime = localStorage.getItem("lastRequestTime");
+ const lastCurrentUrl = localStorage.getItem("lastCurrentUrl");
+ const currentUrl = window.location.pathname;
const currentTime = Date.now();
-
const isContained = AUTHORIZED_DUPLICATE_REQUESTS.some((request) =>
config?.url!.includes(request)
);
@@ -17,7 +18,8 @@ export function checkDuplicateRequestAndStoreRequest(config) {
lastMethodCalled === config.method &&
lastMethodCalled === "get" && // Assuming you want to check only for GET requests
lastRequestTime &&
- currentTime - parseInt(lastRequestTime, 10) < 800
+ currentTime - parseInt(lastRequestTime, 10) < 300 &&
+ lastCurrentUrl === currentUrl
) {
return false;
}
@@ -25,6 +27,7 @@ export function checkDuplicateRequestAndStoreRequest(config) {
localStorage.setItem("lastUrlCalled", config.url ?? "");
localStorage.setItem("lastMethodCalled", config.method ?? "");
localStorage.setItem("lastRequestTime", currentTime.toString());
+ localStorage.setItem("lastCurrentUrl", currentUrl);
return true;
}
diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts
index 8afc5073d..dfc01345f 100644
--- a/src/frontend/src/controllers/API/index.ts
+++ b/src/frontend/src/controllers/API/index.ts
@@ -1094,8 +1094,6 @@ export async function getMessagesTable(
const rowsOrganized = rows.data;
- console.log(rowsOrganized);
-
const columns = extractColumnsFromRows(rowsOrganized, mode, excludedFields);
const sessions = new Set();
rowsOrganized.forEach((row) => {
diff --git a/src/frontend/src/pages/AdminPage/LoginPage/index.tsx b/src/frontend/src/pages/AdminPage/LoginPage/index.tsx
index b1772baa5..0c7e073df 100644
--- a/src/frontend/src/pages/AdminPage/LoginPage/index.tsx
+++ b/src/frontend/src/pages/AdminPage/LoginPage/index.tsx
@@ -19,6 +19,7 @@ export default function LoginAdminPage() {
const [inputState, setInputState] =
useState(CONTROL_LOGIN_STATE);
const { login, isAuthenticated, setUserData } = useContext(AuthContext);
+ const setLoading = useAlertStore((state) => state.setLoading);
const { password, username } = inputState;
const setErrorData = useAlertStore((state) => state.setErrorData);
@@ -35,6 +36,10 @@ export default function LoginAdminPage() {
};
onLogin(user)
.then((user) => {
+ console.log("admin page");
+
+ setLoading(true);
+
login(user.access_token);
navigate("/admin/");
})
diff --git a/src/frontend/src/pages/LoginPage/index.tsx b/src/frontend/src/pages/LoginPage/index.tsx
index 826b2a931..d25d1c2e1 100644
--- a/src/frontend/src/pages/LoginPage/index.tsx
+++ b/src/frontend/src/pages/LoginPage/index.tsx
@@ -9,6 +9,7 @@ import { CONTROL_LOGIN_STATE } from "../../constants/constants";
import { AuthContext } from "../../contexts/authContext";
import { onLogin } from "../../controllers/API";
import useAlertStore from "../../stores/alertStore";
+import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { LoginType } from "../../types/api";
import {
inputHandlerEventType,
@@ -23,6 +24,7 @@ export default function LoginPage(): JSX.Element {
const { login } = useContext(AuthContext);
const navigate = useNavigate();
const setErrorData = useAlertStore((state) => state.setErrorData);
+ const setLoading = useFlowsManagerStore((state) => state.setIsLoading);
function handleInput({
target: { name, value },
@@ -37,6 +39,9 @@ export default function LoginPage(): JSX.Element {
};
onLogin(user)
.then((user) => {
+ console.log("login page");
+
+ setLoading(true);
login(user.access_token);
navigate("/");
})
diff --git a/src/frontend/src/pages/MainPage/components/myCollectionComponent/components/headerTabsSearchComponent/index.tsx b/src/frontend/src/pages/MainPage/components/myCollectionComponent/components/headerTabsSearchComponent/index.tsx
index 17916f05b..b023216ab 100644
--- a/src/frontend/src/pages/MainPage/components/myCollectionComponent/components/headerTabsSearchComponent/index.tsx
+++ b/src/frontend/src/pages/MainPage/components/myCollectionComponent/components/headerTabsSearchComponent/index.tsx
@@ -1,39 +1,19 @@
import { useState } from "react";
-import { useLocation } from "react-router-dom";
-import useAlertStore from "../../../../../../stores/alertStore";
import useFlowsManagerStore from "../../../../../../stores/flowsManagerStore";
-import { useFolderStore } from "../../../../../../stores/foldersStore";
-import { handleDownloadFolderFn } from "../../../../utils/handle-download-folder";
import InputSearchComponent from "../inputSearchComponent";
import TabsSearchComponent from "../tabsComponent";
type HeaderTabsSearchComponentProps = {};
const HeaderTabsSearchComponent = ({}: HeaderTabsSearchComponentProps) => {
- const location = useLocation();
- const myCollectionId = useFolderStore((state) => state.myCollectionId);
- const folderId = location?.state?.folderId || myCollectionId;
const isLoading = useFlowsManagerStore((state) => state.isLoading);
const [tabActive, setTabActive] = useState("Flows");
- const setErrorData = useAlertStore((state) => state.setErrorData);
- const allFlows = useFlowsManagerStore((state) => state.allFlows);
const [inputValue, setInputValue] = useState("");
const setSearchFlowsComponents = useFlowsManagerStore(
(state) => state.setSearchFlowsComponents
);
- const handleDownloadFolder = () => {
- if (allFlows.length === 0) {
- setErrorData({
- title: "Folder is empty",
- list: [],
- });
- return;
- }
- handleDownloadFolderFn(folderId);
- };
-
return (
<>
diff --git a/src/frontend/src/pages/MainPage/hooks/use-delete-folder.tsx b/src/frontend/src/pages/MainPage/hooks/use-delete-folder.tsx
index 257f1b6d2..0d093bc32 100644
--- a/src/frontend/src/pages/MainPage/hooks/use-delete-folder.tsx
+++ b/src/frontend/src/pages/MainPage/hooks/use-delete-folder.tsx
@@ -2,11 +2,12 @@ import useAlertStore from "../../../stores/alertStore";
import { useFolderStore } from "../../../stores/foldersStore";
import { deleteFolder, getFolderById } from "../services";
-const useDeleteFolder = ({ navigate, getFoldersApi }) => {
+const useDeleteFolder = ({ navigate }) => {
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const setErrorData = useAlertStore((state) => state.setErrorData);
const folderToEdit = useFolderStore((state) => state.folderToEdit);
const myCollectionId = useFolderStore((state) => state.myCollectionId);
+ const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
const handleDeleteFolder = () => {
deleteFolder(folderToEdit?.id!)
diff --git a/src/frontend/src/pages/MainPage/pages/mainPage/index.tsx b/src/frontend/src/pages/MainPage/pages/mainPage/index.tsx
index 0daa61257..39add5211 100644
--- a/src/frontend/src/pages/MainPage/pages/mainPage/index.tsx
+++ b/src/frontend/src/pages/MainPage/pages/mainPage/index.tsx
@@ -25,16 +25,9 @@ export default function HomePage(): JSX.Element {
const [openFolderModal, setOpenFolderModal] = useState(false);
const [openDeleteFolderModal, setOpenDeleteFolderModal] = useState(false);
const is_component = pathname === "/components";
- const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
const setFolderToEdit = useFolderStore((state) => state.setFolderToEdit);
const navigate = useNavigate();
- useEffect(() => {
- setTimeout(() => {
- getFoldersApi();
- }, 300);
- }, []);
-
useEffect(() => {
setCurrentFlowId("");
}, [pathname]);
@@ -45,7 +38,7 @@ export default function HomePage(): JSX.Element {
is_component,
});
- const { handleDeleteFolder } = useDeleteFolder({ navigate, getFoldersApi });
+ const { handleDeleteFolder } = useDeleteFolder({ navigate });
return (
<>
diff --git a/src/frontend/src/stores/foldersStore.tsx b/src/frontend/src/stores/foldersStore.tsx
index ce858c3be..8e42026b4 100644
--- a/src/frontend/src/stores/foldersStore.tsx
+++ b/src/frontend/src/stores/foldersStore.tsx
@@ -7,64 +7,100 @@ import {
} from "../pages/MainPage/services";
import { FoldersStoreType } from "../types/zustand/folders";
import useFlowsManagerStore from "./flowsManagerStore";
+import { useTypesStore } from "./typesStore";
export const useFolderStore = create
((set, get) => ({
folders: [],
- getFoldersApi: (refetch = false) => {
+ getFoldersApi: (refetch = false, startupApplication: boolean = false) => {
return new Promise((resolve, reject) => {
if (get()?.folders.length === 0 || refetch === true) {
- get().setLoading(true);
+ get().setIsLoadingFolders(true);
getFolders().then(
- (res) => {
+ async (res) => {
const foldersWithoutStarterProjects = res?.filter(
- (folder) => folder.name !== STARTER_FOLDER_NAME,
+ (folder) => folder.name !== STARTER_FOLDER_NAME
);
const starterProjects = res?.find(
- (folder) => folder.name === STARTER_FOLDER_NAME,
+ (folder) => folder.name === STARTER_FOLDER_NAME
);
set({ starterProjectId: starterProjects!.id ?? "" });
set({ folders: foldersWithoutStarterProjects });
const myCollectionId = res?.find(
- (f) => f.name === DEFAULT_FOLDER,
+ (f) => f.name === DEFAULT_FOLDER
)?.id;
set({ myCollectionId });
- if (refetch === true) {
- useFlowsManagerStore.getState().refreshFlows();
- useFlowsManagerStore.getState().setAllFlows;
- }
+ const { refreshFlows } = useFlowsManagerStore.getState();
+ const { getTypes } = useTypesStore.getState();
+ const { setIsLoadingFolders } = get();
+
+ if (refetch) {
+ if (startupApplication) {
+ await refreshFlows();
+ await getTypes();
+ } else {
+ refreshFlows();
+ getTypes();
+ }
+ }
+ setIsLoadingFolders(false);
- get().setLoading(false);
resolve();
},
(error) => {
set({ folders: [] });
- get().setLoading(false);
+ get().setIsLoadingFolders(false);
reject(error);
- },
+ }
);
}
});
},
+ refreshFolders: () => {
+ return new Promise((resolve, reject) => {
+ getFolders().then(
+ async (res) => {
+ const foldersWithoutStarterProjects = res?.filter(
+ (folder) => folder.name !== STARTER_FOLDER_NAME
+ );
+
+ const starterProjects = res?.find(
+ (folder) => folder.name === STARTER_FOLDER_NAME
+ );
+
+ set({ starterProjectId: starterProjects!.id ?? "" });
+ set({ folders: foldersWithoutStarterProjects });
+
+ const myCollectionId = res?.find(
+ (f) => f.name === DEFAULT_FOLDER
+ )?.id;
+
+ set({ myCollectionId });
+
+ resolve();
+ },
+ (error) => {
+ set({ folders: [] });
+ get().setIsLoadingFolders(false);
+ reject(error);
+ }
+ );
+ });
+ },
setFolders: (folders) => set(() => ({ folders: folders })),
- loading: false,
- setLoading: (loading) => set(() => ({ loading: loading })),
+ isLoadingFolders: false,
+ setIsLoadingFolders: (isLoadingFolders) => set(() => ({ isLoadingFolders })),
getFolderById: (id) => {
if (id) {
- getFolderById(id).then(
- (res) => {
- const setAllFlows = useFlowsManagerStore.getState().setAllFlows;
- setAllFlows(res.flows);
- set({ selectedFolder: res });
- },
- () => {
- get().getFoldersApi(true);
- },
- );
+ getFolderById(id).then((res) => {
+ const setAllFlows = useFlowsManagerStore.getState().setAllFlows;
+ setAllFlows(res.flows);
+ set({ selectedFolder: res });
+ });
}
},
selectedFolder: null,
diff --git a/src/frontend/src/types/zustand/folders/index.ts b/src/frontend/src/types/zustand/folders/index.ts
index 5e41677b2..45c1e0bd9 100644
--- a/src/frontend/src/types/zustand/folders/index.ts
+++ b/src/frontend/src/types/zustand/folders/index.ts
@@ -2,10 +2,13 @@ import { FolderType } from "../../../pages/MainPage/entities";
export type FoldersStoreType = {
folders: FolderType[];
- getFoldersApi: (refetch?: boolean) => Promise;
+ getFoldersApi: (
+ refetch?: boolean,
+ startupApplication?: boolean
+ ) => Promise;
setFolders: (folders: FolderType[]) => void;
- loading: boolean;
- setLoading: (loading: boolean) => void;
+ isLoadingFolders: boolean;
+ setIsLoadingFolders: (isLoadingFolders: boolean) => void;
selectedFolder: FolderType | null;
getFolderById: (id: string) => void;
getMyCollectionFolder: () => void;
@@ -23,4 +26,5 @@ export type FoldersStoreType = {
setFolderIdDragging: (id: string) => void;
starterProjectId: string;
setStarterProjectId: (id: string) => void;
+ refreshFolders: () => void;
};
diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts
index b16cb37ae..92e0efe98 100644
--- a/src/frontend/src/utils/utils.ts
+++ b/src/frontend/src/utils/utils.ts
@@ -56,7 +56,7 @@ export function normalCaseToSnakeCase(str: string): string {
export function toTitleCase(
str: string | undefined,
- isNodeField?: boolean,
+ isNodeField?: boolean
): string {
if (!str) return "";
let result = str
@@ -65,7 +65,7 @@ export function toTitleCase(
if (isNodeField) return word;
if (index === 0) {
return checkUpperWords(
- word[0].toUpperCase() + word.slice(1).toLowerCase(),
+ word[0].toUpperCase() + word.slice(1).toLowerCase()
);
}
return checkUpperWords(word.toLowerCase());
@@ -78,7 +78,7 @@ export function toTitleCase(
if (isNodeField) return word;
if (index === 0) {
return checkUpperWords(
- word[0].toUpperCase() + word.slice(1).toLowerCase(),
+ word[0].toUpperCase() + word.slice(1).toLowerCase()
);
}
return checkUpperWords(word.toLowerCase());
@@ -182,7 +182,7 @@ export function checkLocalStorageKey(key: string): boolean {
export function IncrementObjectKey(
object: object,
- key: string,
+ key: string
): { newKey: string; increment: number } {
let count = 1;
const type = removeCountFromString(key);
@@ -217,7 +217,7 @@ export function groupByFamily(
data: APIDataType,
baseClasses: string,
left: boolean,
- flow?: NodeType[],
+ flow?: NodeType[]
): groupedObjType[] {
const baseClassesSet = new Set(baseClasses.split("\n"));
let arrOfPossibleInputs: Array<{
@@ -263,7 +263,7 @@ export function groupByFamily(
hasBaseClassInBaseClasses:
foundNode?.hasBaseClassInBaseClasses ||
nodeData.node!.base_classes?.some((baseClass) =>
- baseClassesSet.has(baseClass),
+ baseClassesSet.has(baseClass)
), //seta como anterior ou verifica se o node tem base class
displayName: nodeData.node?.display_name,
});
@@ -280,10 +280,10 @@ export function groupByFamily(
if (!foundNode) {
foundNode = {
hasBaseClassInTemplate: Object.values(node!.template).some(
- checkBaseClass,
+ checkBaseClass
),
hasBaseClassInBaseClasses: node!.base_classes?.some((baseClass) =>
- baseClassesSet.has(baseClass),
+ baseClassesSet.has(baseClass)
),
displayName: node?.display_name,
};
@@ -355,7 +355,7 @@ export function isTimeStampString(str: string): boolean {
export function extractColumnsFromRows(
rows: object[],
mode: "intersection" | "union",
- excludeColumns?: Array,
+ excludeColumns?: Array
): (ColDef | ColGroupDef)[] {
let columnsKeys: { [key: string]: ColDef | ColGroupDef } = {};
if (rows.length === 0) {