Skip to content

Commit

Permalink
ensure api query reacts to branch and date changes (#5771)
Browse files Browse the repository at this point in the history
  • Loading branch information
bilalabbad authored Feb 18, 2025
1 parent fbce413 commit 35396e2
Show file tree
Hide file tree
Showing 38 changed files with 352 additions and 259 deletions.
2 changes: 0 additions & 2 deletions frontend/app/src/config/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ export const PROFILE_KIND = "CoreProfile";

export const TASK_TARGET = "CoreTaskTarget";

export const DATA_CHECK_OBJECT = "CoreDataCheck";

export const ACCOUNT_GENERIC_OBJECT = "CoreGenericAccount";
export const ACCOUNT_OBJECT = "CoreAccount";

Expand Down
58 changes: 38 additions & 20 deletions frontend/app/src/entities/branches/ui/branches-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,70 @@ import { QSP } from "@/config/qsp";
import { useGetBranches } from "@/entities/branches/domain/get-branches.query";
import { currentBranchAtom } from "@/entities/branches/stores";
import { findSelectedBranch } from "@/entities/branches/utils";
import { Branch } from "@/shared/api/graphql/generated/graphql";
import ErrorScreen from "@/shared/components/errors/error-screen";
import { InfrahubLoading } from "@/shared/components/loading/infrahub-loading";
import { ALERT_TYPES, Alert } from "@/shared/components/ui/alert";
import { useSetAtom } from "jotai";
import { useAtom } from "jotai";
import React, { useEffect } from "react";
import { useNavigate } from "react-router";
import { toast } from "react-toastify";
import { StringParam, useQueryParam } from "use-query-params";

type BranchContext = {
currentBranch: Branch;
setCurrentBranch: (branch: Branch) => void;
};

export const BranchContext = React.createContext<BranchContext | null>(null);

export function useCurrentBranch() {
const context = React.use(BranchContext);
if (!context) {
throw new Error("useCurrentBranch must be used within a BranchesProvider.");
}

return context;
}

export const BranchesProvider = ({ children }: { children?: React.ReactNode }) => {
const { data: branches, isPending, error } = useGetBranches();
const setCurrentBranch = useSetAtom(currentBranchAtom);
const [currentBranch, setCurrentBranch] = useAtom(currentBranchAtom);
const [branchInQueryString] = useQueryParam(QSP.BRANCH, StringParam);
const navigate = useNavigate();

useEffect(() => {
if (isPending || error) return;

const selectedBranch = findSelectedBranch(branches, branchInQueryString);
if (branchInQueryString && !selectedBranch) {
toast(
<Alert
type={ALERT_TYPES.ERROR}
message={
<>
Branch <b>{branchInQueryString}</b> not found, you have been redirected to the main
branch.
</>
}
/>
);
const mainBranch = findSelectedBranch(branches, DEFAULT_BRANCH_NAME);
setCurrentBranch(mainBranch);
navigate("/");
if (selectedBranch) {
setCurrentBranch(selectedBranch);
return;
}

setCurrentBranch(selectedBranch);
toast(
<Alert
type={ALERT_TYPES.ERROR}
message={
<>
Branch <b>{branchInQueryString}</b> not found, you have been redirected to the main
branch.
</>
}
/>
);
const mainBranch = findSelectedBranch(branches, DEFAULT_BRANCH_NAME);
setCurrentBranch(mainBranch);
navigate("/");
}, [branches, branchInQueryString]);

if (isPending) {
if (isPending || !currentBranch) {
return <InfrahubLoading>loading branches...</InfrahubLoading>;
}

if (error) {
return <ErrorScreen message={error.message} />;
}

return children;
return <BranchContext value={{ currentBranch, setCurrentBranch }}>{children}</BranchContext>;
};

This file was deleted.

5 changes: 2 additions & 3 deletions frontend/app/src/entities/diff/api/get-diff-tree-from-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DiffTreeQueryFilters } from "@/shared/api/graphql/generated/graphql";
import graphqlClient from "@/shared/api/graphql/graphqlClientApollo";
import { PaginationParams } from "@/shared/api/types";
import { gql } from "@apollo/client";

export const DIFF_TREE_QUERY = gql`
Expand Down Expand Up @@ -127,11 +128,9 @@ export const DIFF_TREE_QUERY = gql`
}
`;

export type GetDiffTreeFromApiParams = {
export type GetDiffTreeFromApiParams = PaginationParams & {
branchName: string;
filters?: DiffTreeQueryFilters;
limit?: number;
offset?: number;
};

export const getDiffTreeFromApi = async ({
Expand Down
5 changes: 2 additions & 3 deletions frontend/app/src/entities/diff/domain/get-diff-tree.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { getDiffTreeFromApi } from "@/entities/diff/api/get-diff-tree-from-api";
import { DiffTree, DiffTreeQueryFilters } from "@/shared/api/graphql/generated/graphql";
import { PaginationParams } from "@/shared/api/types";
import { infiniteQueryOptions, useInfiniteQuery } from "@tanstack/react-query";

export const DIFF_TREE_PER_PAGE = 300;

export type GetDiffTreeParams = {
export type GetDiffTreeParams = PaginationParams & {
branchName: string;
filters?: DiffTreeQueryFilters;
limit?: number;
offset: number;
};

export type GetDiffTree = (params: GetDiffTreeParams) => Promise<DiffTree>;
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/src/entities/diff/node-diff/conflict.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useAuth } from "@/entities/authentication/ui/useAuth";
import { currentBranchAtom } from "@/entities/branches/stores";
import { useCurrentBranch } from "@/entities/branches/ui/branches-provider";
import { resolveConflict } from "@/entities/diff/api/resolveConflict";
import { proposedChangedState } from "@/entities/proposed-changes/stores/proposedChanges.atom";
import graphqlClient from "@/shared/api/graphql/graphqlClientApollo";
Expand All @@ -16,7 +16,7 @@ import { useState } from "react";
import { toast } from "react-toastify";

export const Conflict = ({ conflict }: any) => {
const currentBranch = useAtomValue(currentBranchAtom);
const { currentBranch } = useCurrentBranch();
const date = useAtomValue(datetimeAtom);
const [isLoading, setIsLoading] = useState(false);
const proposedChangesDetails = useAtomValue(proposedChangedState);
Expand Down
6 changes: 2 additions & 4 deletions frontend/app/src/entities/ipam/ip-namespace-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { currentBranchAtom } from "@/entities/branches/stores";
import { GET_IP_NAMESPACES } from "@/entities/ipam/api/ip-namespaces";
import { IpamNamespace } from "@/shared/api/graphql/generated/graphql";
import useQuery from "@/shared/api/graphql/useQuery";
Expand All @@ -11,7 +10,7 @@ import {
ComboboxTrigger,
} from "@/shared/components/ui/combobox";
import { Icon } from "@iconify-icon/react";
import { useAtomValue, useSetAtom } from "jotai";
import { useSetAtom } from "jotai";
import { useEffect, useId } from "react";
import { useNavigate, useParams } from "react-router";
import { StringParam, useQueryParam } from "use-query-params";
Expand All @@ -20,8 +19,7 @@ import { constructPathForIpam } from "./common/utils";
import { IPAM_QSP, IPAM_ROUTE, IPAM_TABS, NAMESPACE_GENERIC } from "./constants";

export default function IpNamespaceSelector() {
const currentBranchName = useAtomValue(currentBranchAtom);
const { loading, data, error } = useQuery(GET_IP_NAMESPACES, { skip: !currentBranchName });
const { loading, data, error } = useQuery(GET_IP_NAMESPACES);

if (loading) {
return <Skeleton className="h-10 w-80" />;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PaginationParams } from "@/shared/api/types";
import { jsonToGraphQLQuery } from "json-to-graphql-query";

export const generateRelationshipListQuery = ({
Expand All @@ -7,11 +8,9 @@ export const generateRelationshipListQuery = ({
offset = 0,
search = "",
peerField,
}: {
}: PaginationParams & {
peer: string;
parent?: { name?: string; value?: string };
limit?: number;
offset?: number;
search?: string;
peerField?: string;
}): string => {
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/src/entities/nodes/hierarchical-tree.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { currentBranchAtom } from "@/entities/branches/stores";
import { useCurrentBranch } from "@/entities/branches/ui/branches-provider";
import { TREE_ROOT_ID } from "@/entities/ipam/constants";
import { EMPTY_TREE, PrefixNode, updateTreeData } from "@/entities/ipam/ipam-tree/utils";
import {
Expand Down Expand Up @@ -30,7 +30,7 @@ export type HierarchicalTreeProps = {

export const HierarchicalTree = ({ schema, currentNodeId, className }: HierarchicalTreeProps) => {
const navigate = useNavigate();
const currentBranch = useAtomValue(currentBranchAtom);
const { currentBranch } = useCurrentBranch();
const currentDate = useAtomValue(datetimeAtom);
const [filters] = useFilters();
const hasAutoGeneratedFiltered = filters.some(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import graphqlClient from "@/shared/api/graphql/graphqlClientApollo";
import { ContextParams } from "@/shared/api/types";
import { gql } from "@apollo/client";
import { jsonToGraphQLQuery } from "json-to-graphql-query";

Expand All @@ -22,7 +23,7 @@ export function deleteObjectFromApi({
objectId,
branchName,
atDate,
}: { objectKind: string; objectId: string; branchName: string; atDate: Date | null }) {
}: ContextParams & { objectKind: string; objectId: string }) {
return graphqlClient.mutate({
mutation: gql(getDeleteObjectQuery(objectKind, objectId)),
context: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getCurrentBranchName } from "@/entities/branches/domain/get-current-branch";
import { useCurrentBranch } from "@/entities/branches/ui/branches-provider";
import { queryClient } from "@/shared/api/rest/client";
import { store } from "@/shared/stores";
import { datetimeAtom } from "@/shared/stores/time.atom";
import { useMutation } from "@tanstack/react-query";
import { useAtomValue } from "jotai";
import { deleteObject } from "./delete-object";

export interface DeleteObjectParams {
Expand All @@ -11,22 +11,24 @@ export interface DeleteObjectParams {
}

export function useDeleteObject() {
const currentBranchName = getCurrentBranchName();
const timeMachineDate = store.get(datetimeAtom);
const { currentBranch } = useCurrentBranch();
const timeMachineDate = useAtomValue(datetimeAtom);

return useMutation({
mutationFn: async ({ objectKind, objectId }: DeleteObjectParams) => {
await deleteObject({
objectKind,
objectId,
branchName: currentBranchName,
branchName: currentBranch.name,
atDate: timeMachineDate,
});

return { objectKind, objectId };
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["objects"] });
queryClient.invalidateQueries({
predicate: (query) => query.queryKey.includes("objects"),
});
},
});
}
13 changes: 7 additions & 6 deletions frontend/app/src/entities/nodes/object/domain/delete-object.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { deleteObjectFromApi } from "@/entities/nodes/object/api/delete-object-from-api";
import { ContextParams } from "@/shared/api/types";

export type DeleteObject = (data: {
objectKind: string;
objectId: string;
branchName: string;
atDate: Date | null;
}) => Promise<void>;
export type DeleteObject = (
data: ContextParams & {
objectKind: string;
objectId: string;
}
) => Promise<void>;

export const deleteObject: DeleteObject = async (data) => {
await deleteObjectFromApi(data);
Expand Down
38 changes: 28 additions & 10 deletions frontend/app/src/entities/nodes/object/domain/get-objects.query.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import { getCurrentBranchName } from "@/entities/branches/domain/get-current-branch";
import { useCurrentBranch } from "@/entities/branches/ui/branches-provider";
import { IModelSchema } from "@/entities/schema/stores/schema.atom";
import { ContextParams } from "@/shared/api/types";
import { Filter } from "@/shared/hooks/useFilters";
import { store } from "@/shared/stores";
import { datetimeAtom } from "@/shared/stores/time.atom";
import { infiniteQueryOptions } from "@tanstack/react-query";
import { infiniteQueryOptions, useInfiniteQuery } from "@tanstack/react-query";
import { useAtomValue } from "jotai";
import { OBJECTS_PER_PAGE, getObjects } from "./get-objects";

type GetObjectsQueryParams = ContextParams & {
schema: IModelSchema;
filters?: Array<Filter>;
};

export function getObjectsInfiniteQueryOptions({
schema,
filters,
}: { schema: IModelSchema; filters?: Array<Filter> }) {
const currentBranchName = getCurrentBranchName();
const timeMachineDate = store.get(datetimeAtom);

branchName,
atDate,
}: GetObjectsQueryParams) {
return infiniteQueryOptions({
queryKey: ["objects", schema.kind, currentBranchName, timeMachineDate, JSON.stringify(filters)],
queryKey: [branchName, atDate, "objects", schema.kind, JSON.stringify(filters)],
queryFn: ({ pageParam }) => {
return getObjects({
schema,
offset: pageParam,
branchName: currentBranchName,
atDate: timeMachineDate,
branchName,
atDate,
filters,
});
},
Expand All @@ -33,3 +38,16 @@ export function getObjectsInfiniteQueryOptions({
},
});
}

export function useObjects(params: Omit<GetObjectsQueryParams, "branchName" | "atDate">) {
const { currentBranch } = useCurrentBranch();
const timeMachineDate = useAtomValue(datetimeAtom);

return useInfiniteQuery(
getObjectsInfiniteQueryOptions({
...params,
branchName: currentBranch.name,
atDate: timeMachineDate,
})
);
}
26 changes: 17 additions & 9 deletions frontend/app/src/entities/nodes/object/domain/get-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NodeObject } from "@/entities/nodes/types";
import { IModelSchema } from "@/entities/schema/stores/schema.atom";
import graphqlClient from "@/shared/api/graphql/graphqlClientApollo";
import { addAttributesToRequest, addRelationshipsToRequest } from "@/shared/api/graphql/utils";
import { ContextParams, PaginationParams } from "@/shared/api/types";
import { Filter } from "@/shared/hooks/useFilters";
import { gql } from "@apollo/client";
import { jsonToGraphQLQuery } from "json-to-graphql-query";
Expand All @@ -14,15 +15,22 @@ export const OBJECTS_PER_PAGE = 40;

////////////////////////////////////////////////////////////////////////////////////////////////////

export type GetObjects = (args: {
schema: IModelSchema;
offset?: number;
branchName: string;
atDate?: Date | null;
filters?: Array<Filter>;
}) => Promise<Array<NodeObject>>;
export type GetObjects = (
args: ContextParams &
PaginationParams & {
schema: IModelSchema;
filters?: Array<Filter>;
}
) => Promise<Array<NodeObject>>;

export const getObjects: GetObjects = async ({ schema, offset, branchName, atDate, filters }) => {
export const getObjects: GetObjects = async ({
schema,
limit = OBJECTS_PER_PAGE,
offset,
branchName,
atDate,
filters,
}) => {
const attributesVisible = getAttributesVisibleInListView(schema.attributes ?? []);
const relationshipsVisible = getRelationshipsVisibleInListView(schema.relationships ?? []);

Expand All @@ -35,7 +43,7 @@ export const getObjects: GetObjects = async ({ schema, offset, branchName, atDat
__name: `GetObjects${schemaKind}`,
[schemaKindToQuery]: {
__args: {
limit: OBJECTS_PER_PAGE,
limit,
offset,
...(filters
? filters.reduce(
Expand Down
Loading

0 comments on commit 35396e2

Please sign in to comment.