From 43262280fd24cc5dd098688ef6067739561406e0 Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Mon, 20 Oct 2025 14:09:36 +0200 Subject: [PATCH 01/10] get DiffTreeSummary using tanstack query --- .../api/get-diff-tree-summary-from-api.ts | 30 ++++++++++ .../diff/domain/get-diff-summary.query.ts | 18 ++++++ .../entities/diff/domain/get-diff-summary.ts | 26 +++++++++ .../proposed-changes/ui/diff-summary.tsx | 55 ++++++------------- 4 files changed, 90 insertions(+), 39 deletions(-) create mode 100644 frontend/app/src/entities/diff/api/get-diff-tree-summary-from-api.ts create mode 100644 frontend/app/src/entities/diff/domain/get-diff-summary.query.ts create mode 100644 frontend/app/src/entities/diff/domain/get-diff-summary.ts diff --git a/frontend/app/src/entities/diff/api/get-diff-tree-summary-from-api.ts b/frontend/app/src/entities/diff/api/get-diff-tree-summary-from-api.ts new file mode 100644 index 0000000000..abe66ad7d0 --- /dev/null +++ b/frontend/app/src/entities/diff/api/get-diff-tree-summary-from-api.ts @@ -0,0 +1,30 @@ +import { gql } from "@apollo/client"; + +import type { + Get_Diff_Tree_SummaryQuery, + Get_Diff_Tree_SummaryQueryVariables, +} from "@/shared/api/graphql/generated/graphql"; +import graphqlClient from "@/shared/api/graphql/graphqlClientApollo"; + +export const GET_PROPOSED_CHANGES_DIFF_SUMMARY = gql` + query GET_DIFF_TREE_SUMMARY($branch: String, $filters: DiffTreeQueryFilters) { + DiffTreeSummary(branch: $branch, filters: $filters) { + num_added + num_updated + num_removed + num_conflicts + } + } +`; + +export interface GetDiffTreeSummaryFromApiParams extends Get_Diff_Tree_SummaryQueryVariables {} + +export function getDiffTreeSummaryFromApi(variables: Get_Diff_Tree_SummaryQueryVariables) { + return graphqlClient.query({ + query: GET_PROPOSED_CHANGES_DIFF_SUMMARY, + variables, + context: { + processErrorMessage: () => {}, + }, + }); +} diff --git a/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts b/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts new file mode 100644 index 0000000000..1f6e4e4bbd --- /dev/null +++ b/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts @@ -0,0 +1,18 @@ +import { queryOptions, useQuery } from "@tanstack/react-query"; + +import type { QueryConfig } from "@/shared/api/types"; + +import { type GetDiffSummaryParams, getDiffSummary } from "@/entities/diff/domain/get-diff-summary"; + +export function getDiffSummaryQueryOptions({ branchName }: GetDiffSummaryParams) { + return queryOptions({ + queryKey: ["diff-summary", branchName], + queryFn: () => getDiffSummary({ branchName }), + }); +} + +export type useGetDiffSummaryConfig = QueryConfig; + +export function useGetDiffSummary(params: GetDiffSummaryParams, config?: useGetDiffSummaryConfig) { + return useQuery({ ...getDiffSummaryQueryOptions(params), ...config }); +} diff --git a/frontend/app/src/entities/diff/domain/get-diff-summary.ts b/frontend/app/src/entities/diff/domain/get-diff-summary.ts new file mode 100644 index 0000000000..59af52e8ab --- /dev/null +++ b/frontend/app/src/entities/diff/domain/get-diff-summary.ts @@ -0,0 +1,26 @@ +import { getDiffTreeSummaryFromApi } from "@/entities/diff/api/get-diff-tree-summary-from-api"; + +export type GetDiffSummaryParams = { branchName: string }; + +export type GetDiffSummaryResponse = { + num_added: number; + num_updated: number; + num_removed: number; + num_conflicts: number; +}; + +export type GetDiffSummary = ( + params: GetDiffSummaryParams +) => Promise; + +export const getDiffSummary: GetDiffSummary = async ({ branchName }) => { + const { data, errors } = await getDiffTreeSummaryFromApi({ + branch: branchName, + }); + + if (errors) { + throw new Error(errors.map((e) => e.message).join("; ")); + } + + return (data.DiffTreeSummary as GetDiffSummaryResponse) ?? null; +}; diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx index 47e1683c1d..5c1f06231a 100644 --- a/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx @@ -1,25 +1,15 @@ -import { useQuery } from "@apollo/client"; import type React from "react"; import { Link } from "react-router"; -import { toast } from "react-toastify"; import { QSP } from "@/config/qsp"; import { constructPath } from "@/shared/api/rest/fetch"; +import { Row } from "@/shared/components/container"; import ErrorScreen from "@/shared/components/errors/error-screen"; -import { ALERT_TYPES, Alert } from "@/shared/components/ui/alert"; +import { useGetDiffSummary } from "@/entities/diff/domain/get-diff-summary.query"; +import { DIFF_STATUS, type DiffStatus } from "@/entities/diff/node-diff/types"; import { DiffBadge } from "@/entities/diff/node-diff/utils"; -import { getProposedChangesDiffSummary } from "@/entities/proposed-changes/api/getProposedChangesDiffSummary"; - -import { DIFF_STATUS, type DiffStatus } from "../../diff/node-diff/types"; - -interface DiffTreeSummary { - num_added: number; - num_removed: number; - num_updated: number; - num_conflicts: number; -} interface ProposedChangeDiffSummaryProps { branchName: string; @@ -50,24 +40,9 @@ export const ProposedChangeDiffSummary: React.FC proposedChangeId, branchName, }) => { - const { error, data, loading } = useQuery<{ DiffTreeSummary: DiffTreeSummary }>( - getProposedChangesDiffSummary, - { - skip: !branchName, - variables: { branch: branchName }, - context: { - processErrorMessage: (message: string) => { - if (!message.includes("not found")) { - toast(, { - toastId: "alert-error", - }); - } - }, - }, - } - ); + const { error, data, isPending } = useGetDiffSummary({ branchName }); - if (loading) { + if (isPending) { return ; } @@ -81,40 +56,42 @@ export const ProposedChangeDiffSummary: React.FC ); } - const { DiffTreeSummary } = data || {}; + if (!data) { + return null; + } return ( -
+ -
+ ); }; const DiffSummarySkeleton: React.FC = () => { return ( -
+ {[...Array(4)].map((_, index) => (
))} -
+
); }; From 2e422ec641f485ba36718c095bd6646225ebfefe Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Mon, 20 Oct 2025 16:11:49 +0200 Subject: [PATCH 02/10] ts type rename --- .../app/src/entities/diff/domain/get-diff-summary.query.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts b/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts index 1f6e4e4bbd..43bfaf6821 100644 --- a/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts +++ b/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts @@ -11,8 +11,8 @@ export function getDiffSummaryQueryOptions({ branchName }: GetDiffSummaryParams) }); } -export type useGetDiffSummaryConfig = QueryConfig; +export type UseGetDiffSummaryConfig = QueryConfig; -export function useGetDiffSummary(params: GetDiffSummaryParams, config?: useGetDiffSummaryConfig) { +export function useGetDiffSummary(params: GetDiffSummaryParams, config?: UseGetDiffSummaryConfig) { return useQuery({ ...getDiffSummaryQueryOptions(params), ...config }); } From 1ee96bb8525ec71fdd7920b7b1e8f6822890003f Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Tue, 21 Oct 2025 12:27:06 +0200 Subject: [PATCH 03/10] use tag for diff summary --- .../proposed-changes/ui/diff-summary.tsx | 97 ------------------- .../ui/diff-summary/diff-summary-skeleton.tsx | 11 +++ .../diff-summary/diff-summary-tag-group.tsx | 88 +++++++++++++++++ .../proposed-change-diff-summary.tsx | 81 ++++++++++++++++ .../ui/proposed-change-item.tsx | 2 +- .../app/src/shared/components/style-rac.ts | 2 +- 6 files changed, 182 insertions(+), 99 deletions(-) delete mode 100644 frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx create mode 100644 frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton.tsx create mode 100644 frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx create mode 100644 frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx deleted file mode 100644 index 5c1f06231a..0000000000 --- a/frontend/app/src/entities/proposed-changes/ui/diff-summary.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import type React from "react"; -import { Link } from "react-router"; - -import { QSP } from "@/config/qsp"; - -import { constructPath } from "@/shared/api/rest/fetch"; -import { Row } from "@/shared/components/container"; -import ErrorScreen from "@/shared/components/errors/error-screen"; - -import { useGetDiffSummary } from "@/entities/diff/domain/get-diff-summary.query"; -import { DIFF_STATUS, type DiffStatus } from "@/entities/diff/node-diff/types"; -import { DiffBadge } from "@/entities/diff/node-diff/utils"; - -interface ProposedChangeDiffSummaryProps { - branchName: string; - proposedChangeId: string; -} - -const BadgeLink: React.FC<{ - status: DiffStatus; - count: number | undefined; - proposedChangeId: string; -}> = ({ status, count, proposedChangeId }) => { - const proposedChangeDetailsPath = `/proposed-changes/${proposedChangeId}`; - - return ( - - {count} - - ); -}; - -export const ProposedChangeDiffSummary: React.FC = ({ - proposedChangeId, - branchName, -}) => { - const { error, data, isPending } = useGetDiffSummary({ branchName }); - - if (isPending) { - return ; - } - - if (error) { - return ( - - ); - } - - if (!data) { - return null; - } - - return ( - - - - - - - ); -}; - -const DiffSummarySkeleton: React.FC = () => { - return ( - - {[...Array(4)].map((_, index) => ( -
- ))} - - ); -}; diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton.tsx new file mode 100644 index 0000000000..c6e41cc598 --- /dev/null +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton.tsx @@ -0,0 +1,11 @@ +import { Row } from "@/shared/components/container"; + +export function DiffSummarySkeleton() { + return ( + + {[...Array(4)].map((_, index) => ( +
+ ))} + + ); +} diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx new file mode 100644 index 0000000000..d303f349c7 --- /dev/null +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx @@ -0,0 +1,88 @@ +import { cva, type VariantProps } from "class-variance-authority"; +import { CircleMinusIcon, CirclePlusIcon, RefreshCcwIcon, TriangleAlertIcon } from "lucide-react"; +import { + Tag, + TagGroup, + type TagGroupProps, + TagList, + type TagListProps, + type TagProps, +} from "react-aria-components"; + +import { focusVisibleStyle } from "@/shared/components/style-rac"; +import { classNames } from "@/shared/utils/common"; + +export interface DiffSummaryProps + extends Omit, + Pick, "items" | "children" | "renderEmptyState"> {} + +export function DiffSummaryTagGroup({ + items, + children, + renderEmptyState, + ...props +}: DiffSummaryProps) { + return ( + + + + {children} + + + + ); +} + +const diffSummaryTagVariants = cva( + [ + focusVisibleStyle, + "inline-flex cursor-pointer items-center gap-1 rounded-full border border-transparent p-1 text-xs", + ], + { + variants: { + variant: { + added: "bg-green-200 text-green-800", + removed: "bg-red-200 text-red-800", + updated: "bg-blue-200 text-blue-800", + conflicts: "bg-yellow-200 text-yellow-800", + }, + }, + } +); + +export interface DiffSummaryTagProps extends VariantProps, TagProps { + count: number; +} + +export function DiffSummaryTag({ count, variant, ...props }: DiffSummaryTagProps) { + return ( + + + {count} + + ); +} + +export function DiffSummaryIcon({ + variant, + ...props +}: Pick, "variant">) { + const className = "size-3"; + + switch (variant) { + case "added": + return ; + case "removed": + return ; + case "updated": + return ; + case "conflicts": + return ; + default: + return null; + } +} diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx new file mode 100644 index 0000000000..d58227aa06 --- /dev/null +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx @@ -0,0 +1,81 @@ +import { QSP } from "@/config/qsp"; + +import { constructPath } from "@/shared/api/rest/fetch"; +import ErrorScreen from "@/shared/components/errors/error-screen"; + +import { useGetDiffSummary } from "@/entities/diff/domain/get-diff-summary.query"; +import { DIFF_STATUS } from "@/entities/diff/node-diff/types"; +import { DiffSummarySkeleton } from "@/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton"; +import { + DiffSummaryTag, + DiffSummaryTagGroup, +} from "@/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group"; + +interface ProposedChangeDiffSummaryProps { + branchName: string; + proposedChangeId: string; +} + +export function ProposedChangeDiffSummary({ + proposedChangeId, + branchName, +}: ProposedChangeDiffSummaryProps) { + const { error, data, isPending } = useGetDiffSummary({ branchName }); + + if (isPending) { + return ; + } + + if (error) { + return ( + + ); + } + + if (!data) { + return null; + } + + const proposedChangeDetailsPath = `/proposed-changes/${proposedChangeId}`; + + return ( + + + + + + + ); +} diff --git a/frontend/app/src/entities/proposed-changes/ui/proposed-change-item.tsx b/frontend/app/src/entities/proposed-changes/ui/proposed-change-item.tsx index f6e9f8f867..2bb49e8953 100644 --- a/frontend/app/src/entities/proposed-changes/ui/proposed-change-item.tsx +++ b/frontend/app/src/entities/proposed-changes/ui/proposed-change-item.tsx @@ -12,7 +12,7 @@ import { classNames } from "@/shared/utils/common"; import { useObjectsCount } from "@/entities/nodes/object/domain/get-objects-count.query"; import { useObjectTableContext } from "@/entities/nodes/object/ui/object-table/object-table-context"; import type { ProposedChangeItem } from "@/entities/proposed-changes/domain/get-proposed-changes"; -import { ProposedChangeDiffSummary } from "@/entities/proposed-changes/ui/diff-summary"; +import { ProposedChangeDiffSummary } from "@/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary"; import { ProposedChangesActionCell } from "@/entities/proposed-changes/ui/proposed-changes-actions-cell"; import { useSchema } from "@/entities/schema/ui/hooks/useSchema"; diff --git a/frontend/app/src/shared/components/style-rac.ts b/frontend/app/src/shared/components/style-rac.ts index 8666aa9b0a..c289e281ff 100644 --- a/frontend/app/src/shared/components/style-rac.ts +++ b/frontend/app/src/shared/components/style-rac.ts @@ -1,4 +1,4 @@ export const disabledStyle = "data-disabled:pointer-events-none data-disabled:opacity-50"; export const focusVisibleStyle = - "transition-colors data-focus-visible:outline-hidden data-focus-visible:ring-2 data-focus-visible:ring-custom-blue-600/25 data-focus-visible:border-custom-blue-600"; + "transition-all data-focus-visible:outline-hidden data-focus-visible:ring-2 data-focus-visible:ring-custom-blue-600/25 data-focus-visible:border-custom-blue-600"; From 00769ff80cfa3ff4e3d4e762f3e755aa9fd1531a Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Tue, 21 Oct 2025 14:10:56 +0200 Subject: [PATCH 04/10] icon ccw => cw --- .../ui/diff-summary/diff-summary-tag-group.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx index d303f349c7..3947e44803 100644 --- a/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx @@ -1,5 +1,5 @@ import { cva, type VariantProps } from "class-variance-authority"; -import { CircleMinusIcon, CirclePlusIcon, RefreshCcwIcon, TriangleAlertIcon } from "lucide-react"; +import { CircleMinusIcon, CirclePlusIcon, RefreshCwIcon, TriangleAlertIcon } from "lucide-react"; import { Tag, TagGroup, @@ -79,7 +79,7 @@ export function DiffSummaryIcon({ case "removed": return ; case "updated": - return ; + return ; case "conflicts": return ; default: From 78ac2bc69e347c305581446fc6a36b16adf11334 Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Tue, 21 Oct 2025 16:59:00 +0200 Subject: [PATCH 05/10] count data and schema tab --- .../diff/domain/get-diff-summary.query.ts | 6 +- .../entities/diff/domain/get-diff-summary.ts | 13 +- .../app/src/entities/diff/node-diff/index.tsx | 27 ++- .../proposed-changes/ui/diff-filter.tsx | 155 ++++++------------ .../diff-summary/diff-summary-tag-group.tsx | 55 ++++++- .../proposed-change-diff-summary.tsx | 2 +- 6 files changed, 121 insertions(+), 137 deletions(-) diff --git a/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts b/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts index 43bfaf6821..0163fda309 100644 --- a/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts +++ b/frontend/app/src/entities/diff/domain/get-diff-summary.query.ts @@ -4,10 +4,10 @@ import type { QueryConfig } from "@/shared/api/types"; import { type GetDiffSummaryParams, getDiffSummary } from "@/entities/diff/domain/get-diff-summary"; -export function getDiffSummaryQueryOptions({ branchName }: GetDiffSummaryParams) { +export function getDiffSummaryQueryOptions({ branch, filters }: GetDiffSummaryParams) { return queryOptions({ - queryKey: ["diff-summary", branchName], - queryFn: () => getDiffSummary({ branchName }), + queryKey: ["diff-summary", branch, filters], + queryFn: () => getDiffSummary({ branch, filters }), }); } diff --git a/frontend/app/src/entities/diff/domain/get-diff-summary.ts b/frontend/app/src/entities/diff/domain/get-diff-summary.ts index 59af52e8ab..6d59417e23 100644 --- a/frontend/app/src/entities/diff/domain/get-diff-summary.ts +++ b/frontend/app/src/entities/diff/domain/get-diff-summary.ts @@ -1,6 +1,9 @@ -import { getDiffTreeSummaryFromApi } from "@/entities/diff/api/get-diff-tree-summary-from-api"; +import { + type GetDiffTreeSummaryFromApiParams, + getDiffTreeSummaryFromApi, +} from "@/entities/diff/api/get-diff-tree-summary-from-api"; -export type GetDiffSummaryParams = { branchName: string }; +export type GetDiffSummaryParams = GetDiffTreeSummaryFromApiParams; export type GetDiffSummaryResponse = { num_added: number; @@ -13,10 +16,8 @@ export type GetDiffSummary = ( params: GetDiffSummaryParams ) => Promise; -export const getDiffSummary: GetDiffSummary = async ({ branchName }) => { - const { data, errors } = await getDiffTreeSummaryFromApi({ - branch: branchName, - }); +export const getDiffSummary: GetDiffSummary = async (params) => { + const { data, errors } = await getDiffTreeSummaryFromApi(params); if (errors) { throw new Error(errors.map((e) => e.message).join("; ")); diff --git a/frontend/app/src/entities/diff/node-diff/index.tsx b/frontend/app/src/entities/diff/node-diff/index.tsx index 979929da09..2d8d8c95b8 100644 --- a/frontend/app/src/entities/diff/node-diff/index.tsx +++ b/frontend/app/src/entities/diff/node-diff/index.tsx @@ -9,7 +9,9 @@ import { DateDisplay } from "@/shared/components/display/date-display"; import ErrorScreen from "@/shared/components/errors/error-screen"; import { LoadingIndicator } from "@/shared/components/loading/loading-indicator"; +import type { GetDiffSummaryParams } from "@/entities/diff/domain/get-diff-summary"; import { useDiffTreeInfiniteQuery } from "@/entities/diff/domain/get-diff-tree"; +import { DiffNode } from "@/entities/diff/node-diff/node"; import { DIFF_STATUS, type DiffNode as DiffNodeType } from "@/entities/diff/node-diff/types"; import { buildFilters } from "@/entities/diff/node-diff/utils"; import { DiffComputing } from "@/entities/diff/ui/diff-computing"; @@ -19,29 +21,24 @@ import { DiffRebaseButton } from "@/entities/diff/ui/diff-rebase-button"; import { DiffRefreshButton } from "@/entities/diff/ui/diff-refresh-button"; import DiffTree from "@/entities/diff/ui/diff-tree"; import { proposedChangedState } from "@/entities/proposed-changes/stores/proposedChanges.atom"; - -import { type DiffFilter, ProposedChangeDiffFilter } from "../../proposed-changes/ui/diff-filter"; -import { DiffNode } from "./node"; +import { DiffFilter } from "@/entities/proposed-changes/ui/diff-filter"; export const DiffContext = createContext({}); -type NodeDiffProps = { - filters: DiffFilter; - branchName: string; -}; +type NodeDiffProps = GetDiffSummaryParams; -export const NodeDiff = ({ branchName, filters }: NodeDiffProps) => { +export const NodeDiff = ({ branch, filters }: NodeDiffProps) => { const [qspStatus] = useQueryState(QSP.STATUS); const proposedChangesDetails = useAtomValue(proposedChangedState); - const branch = proposedChangesDetails?.source_branch?.value || branchName; // Used in proposed changes view and branch view + const branchName: string = proposedChangesDetails?.source_branch?.value || branch; // Used in proposed changes view and branch view // Get filters merged with status filter const finalFilters = buildFilters(filters, qspStatus); const { data, isPending, error, hasNextPage, fetchNextPage, isFetchingNextPage } = useDiffTreeInfiniteQuery({ - branchName: branch, + branchName, filters: finalFilters, }); @@ -66,14 +63,14 @@ export const NodeDiff = ({ branchName, filters }: NodeDiffProps) => { if (!firstPageNodes) { return ( ); } if (!qspStatus && firstPageNodes.nodes?.length === 0) { - return ; + return ; } const nodes = @@ -89,12 +86,12 @@ export const NodeDiff = ({ branchName, filters }: NodeDiffProps) => { return (
- + Updated - - + +
diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-filter.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-filter.tsx index c0a51de413..b8a3237664 100644 --- a/frontend/app/src/entities/proposed-changes/ui/diff-filter.tsx +++ b/frontend/app/src/entities/proposed-changes/ui/diff-filter.tsx @@ -1,62 +1,36 @@ -import { useQuery } from "@apollo/client"; import { parseAsString, useQueryState } from "nuqs"; -import { toast } from "react-toastify"; import { QSP } from "@/config/qsp"; -import { Button, type ButtonProps } from "@/shared/components/buttons/button-primitive"; import ErrorScreen from "@/shared/components/errors/error-screen"; -import { ALERT_TYPES, Alert } from "@/shared/components/ui/alert"; -import { classNames } from "@/shared/utils/common"; -import { DIFF_STATUS } from "@/entities/diff/node-diff/types"; -import { DiffBadge } from "@/entities/diff/node-diff/utils"; +import type { GetDiffSummaryParams } from "@/entities/diff/domain/get-diff-summary"; +import { useGetDiffSummary } from "@/entities/diff/domain/get-diff-summary.query"; +import { DIFF_STATUS, type DiffStatus } from "@/entities/diff/node-diff/types"; +import { DiffSummarySkeleton } from "@/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton"; import { - CloseBadgeAdded, - CloseBadgeConflict, - CloseBadgeRemoved, - CloseBadgeUpdated, -} from "@/entities/diff/ui/diff-badge"; -import { getProposedChangesDiffSummary } from "@/entities/proposed-changes/api/getProposedChangesDiffSummary"; + DiffSummaryTag, + DiffSummaryTagGroup, +} from "@/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group"; -export type DiffFilter = { - namespace?: { - excludes?: string[]; - includes?: string[]; - }; - status?: { - excludes?: string[]; - includes?: string[]; - }; -}; - -type ProposedChangeDiffFilterProps = { - branch: string; - filters?: DiffFilter; -}; - -export const ProposedChangeDiffFilter = ({ branch, filters }: ProposedChangeDiffFilterProps) => { - const [qsp, setQsp] = useQueryState(QSP.STATUS, parseAsString.withOptions({ shallow: false })); +type DiffFilterProps = GetDiffSummaryParams; - const { error, data = {} } = useQuery(getProposedChangesDiffSummary, { - skip: !branch, - variables: { branch, filters }, - context: { - processErrorMessage: (message: string) => { - // If the branch is not found, then do not display alert - if (message.includes("not found")) return; +export function DiffFilter({ branch, filters }: DiffFilterProps) { + const [statusFilterQSP, setQsp] = useQueryState( + QSP.STATUS, + parseAsString.withOptions({ shallow: false }) + ); - toast(, { - toastId: "alert-error", - }); - }, - }, - }); + const { error, data, isPending } = useGetDiffSummary({ branch, filters }); - const handleFilter = (value: string) => { - setQsp(value === qsp ? null : value); + const handleFilter = (value: DiffStatus) => { + setQsp(value === statusFilterQSP ? null : value); }; + if (isPending) { + return ; + } + if (error) { return ( - + handleFilter(DIFF_STATUS.ADDED)} /> - handleFilter(DIFF_STATUS.REMOVED)} /> - handleFilter(DIFF_STATUS.UPDATED)} /> - handleFilter(DIFF_STATUS.CONFLICT)} /> -
+ ); -}; - -interface FilterButtonProps extends ButtonProps { - status: string; - count: number; - currentFilter: string | null | undefined; - onFilter: (value: string) => void; } - -const FilterButton = ({ status, count, currentFilter, onFilter, ...props }: FilterButtonProps) => { - const isMuted = !!currentFilter && currentFilter !== status; - const isDisabled = !count && currentFilter !== status; - - const CloseBadge = - status === DIFF_STATUS.ADDED - ? CloseBadgeAdded - : status === DIFF_STATUS.REMOVED - ? CloseBadgeRemoved - : status === DIFF_STATUS.UPDATED - ? CloseBadgeUpdated - : status === DIFF_STATUS.CONFLICT - ? CloseBadgeConflict - : null; - - return ( - - ); -}; diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx index 3947e44803..7596d8558e 100644 --- a/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group.tsx @@ -1,3 +1,4 @@ +import { Icon } from "@iconify-icon/react"; import { cva, type VariantProps } from "class-variance-authority"; import { CircleMinusIcon, CirclePlusIcon, RefreshCwIcon, TriangleAlertIcon } from "lucide-react"; import { @@ -9,7 +10,7 @@ import { type TagProps, } from "react-aria-components"; -import { focusVisibleStyle } from "@/shared/components/style-rac"; +import { disabledStyle, focusVisibleStyle } from "@/shared/components/style-rac"; import { classNames } from "@/shared/utils/common"; export interface DiffSummaryProps @@ -33,10 +34,11 @@ export function DiffSummaryTagGroup({ ); } -const diffSummaryTagVariants = cva( +const diffSummaryTagStyles = cva( [ + disabledStyle, focusVisibleStyle, - "inline-flex cursor-pointer items-center gap-1 rounded-full border border-transparent p-1 text-xs", + "relative inline-flex cursor-pointer items-center gap-1 rounded-full border border-transparent p-1 text-xs", ], { variants: { @@ -46,23 +48,36 @@ const diffSummaryTagVariants = cva( updated: "bg-blue-200 text-blue-800", conflicts: "bg-yellow-200 text-yellow-800", }, + isMuted: { + true: "opacity-50", + }, }, } ); -export interface DiffSummaryTagProps extends VariantProps, TagProps { +export interface DiffSummaryTagProps extends VariantProps, TagProps { count: number; + isClosable?: boolean; } -export function DiffSummaryTag({ count, variant, ...props }: DiffSummaryTagProps) { +export function DiffSummaryTag({ + count, + variant, + className, + isClosable, + isMuted, + children, + ...props +}: DiffSummaryTagProps) { return ( {count} + {isClosable && } ); } @@ -70,7 +85,7 @@ export function DiffSummaryTag({ count, variant, ...props }: DiffSummaryTagProps export function DiffSummaryIcon({ variant, ...props -}: Pick, "variant">) { +}: Pick, "variant">) { const className = "size-3"; switch (variant) { @@ -86,3 +101,29 @@ export function DiffSummaryIcon({ return null; } } + +const diffSummaryCloseStyles = cva( + "-top-2 -right-2 absolute flex items-center justify-center rounded-full border-2 border-white", + { + variants: { + variant: { + added: "bg-green-200 text-green-800", + removed: "bg-red-200 text-red-800", + updated: "bg-blue-200 text-blue-800", + conflicts: "bg-yellow-200 text-yellow-800", + }, + }, + } +); + +export interface DiffSummaryCloseProps + extends React.HTMLProps, + VariantProps {} + +export function DiffSummaryClose({ className, variant, ...props }: DiffSummaryCloseProps) { + return ( +
+ +
+ ); +} diff --git a/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx b/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx index d58227aa06..069ba0f320 100644 --- a/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx +++ b/frontend/app/src/entities/proposed-changes/ui/diff-summary/proposed-change-diff-summary.tsx @@ -20,7 +20,7 @@ export function ProposedChangeDiffSummary({ proposedChangeId, branchName, }: ProposedChangeDiffSummaryProps) { - const { error, data, isPending } = useGetDiffSummary({ branchName }); + const { error, data, isPending } = useGetDiffSummary({ branch: branchName }); if (isPending) { return ; From 37f3b9d1df2cde17f29bf67b266ae0bdebe11c8f Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Tue, 21 Oct 2025 16:59:36 +0200 Subject: [PATCH 06/10] unused file --- .../api/getProposedChangesDiffSummary.ts | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 frontend/app/src/entities/proposed-changes/api/getProposedChangesDiffSummary.ts diff --git a/frontend/app/src/entities/proposed-changes/api/getProposedChangesDiffSummary.ts b/frontend/app/src/entities/proposed-changes/api/getProposedChangesDiffSummary.ts deleted file mode 100644 index 21ef69a0c8..0000000000 --- a/frontend/app/src/entities/proposed-changes/api/getProposedChangesDiffSummary.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from "@apollo/client"; - -export const getProposedChangesDiffSummary = gql` - query GET_PROPOSED_CHANGES_DIFF_SUMMARY($branch: String) { - DiffTreeSummary(branch: $branch) { - num_added - num_updated - num_removed - num_conflicts - } - } -`; From 7ffe1ac6605c1d0ef8e4a751a1a591a016bcfecf Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Tue, 21 Oct 2025 17:00:23 +0200 Subject: [PATCH 07/10] branch --- frontend/app/src/pages/branches/details.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/src/pages/branches/details.tsx b/frontend/app/src/pages/branches/details.tsx index 747e94f853..d20cf4a4a8 100644 --- a/frontend/app/src/pages/branches/details.tsx +++ b/frontend/app/src/pages/branches/details.tsx @@ -99,7 +99,7 @@ const BranchContent = ({ branchName }: { branchName: string }) => { case DIFF_TABS.SCHEMA: { return ( { case DIFF_TABS.DATA: { return ( Date: Tue, 21 Oct 2025 17:08:46 +0200 Subject: [PATCH 08/10] unused --- .../app/src/entities/diff/ui/diff-badge.tsx | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/frontend/app/src/entities/diff/ui/diff-badge.tsx b/frontend/app/src/entities/diff/ui/diff-badge.tsx index 167a660663..db3b38e92f 100644 --- a/frontend/app/src/entities/diff/ui/diff-badge.tsx +++ b/frontend/app/src/entities/diff/ui/diff-badge.tsx @@ -8,10 +8,6 @@ export interface DiffBadgeProps extends BadgeProps { icon?: string; } -type CloseBadgeProps = { - className?: string; -}; - export type BadgeType = | typeof BadgeAdded | typeof BadgeRemoved @@ -53,10 +49,6 @@ export const BadgeAdded = ({ className, ...props }: DiffBadgeProps) => { ); }; -export const CloseBadgeAdded = () => { - return ; -}; - export const BadgeRemoved = ({ className, ...props }: DiffBadgeProps) => { return ( { ); }; -export const CloseBadgeRemoved = () => { - return ; -}; - export const BadgeConflict = ({ className, ...props }: DiffBadgeProps) => { return ( { ); }; -export const CloseBadgeConflict = () => { - return ; -}; - export const BadgeUpdated = ({ className, ...props }: DiffBadgeProps) => { return ( { /> ); }; - -export const CloseBadgeUpdated = () => { - return ; -}; - -const CloseBadge = ({ className }: CloseBadgeProps) => { - return ( -
- -
- ); -}; From fc46fb402bc951b2cc106fdd249e1d54ede6e6e0 Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Tue, 21 Oct 2025 17:09:15 +0200 Subject: [PATCH 09/10] import --- frontend/app/src/entities/diff/node-diff/utils.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/app/src/entities/diff/node-diff/utils.tsx b/frontend/app/src/entities/diff/node-diff/utils.tsx index 3ced9e71f6..386ecd7fa8 100644 --- a/frontend/app/src/entities/diff/node-diff/utils.tsx +++ b/frontend/app/src/entities/diff/node-diff/utils.tsx @@ -6,8 +6,6 @@ import { classNames, warnUnexpectedType } from "@/shared/utils/common"; import { capitalizeFirstLetter } from "@/shared/utils/string"; import { DIFF_STATUS, type DiffProperty, type DiffStatus } from "@/entities/diff/node-diff/types"; -import type { DiffFilter } from "@/entities/proposed-changes/ui/diff-filter"; - import { BadgeAdded, BadgeConflict, @@ -16,7 +14,8 @@ import { BadgeUnchanged, BadgeUpdated, type DiffBadgeProps, -} from "../ui/diff-badge"; +} from "@/entities/diff/ui/diff-badge"; +import type { DiffFilter } from "@/entities/proposed-changes/ui/diff-filter"; export const diffBadges: { [key: string]: BadgeType } = { ADDED: BadgeAdded, From 0685ff3c993c6d663ead3e267f6ecaf62bd38b3b Mon Sep 17 00:00:00 2001 From: bilalabbad Date: Wed, 22 Oct 2025 10:47:15 +0200 Subject: [PATCH 10/10] added cahngelog --- changelog/+diff-summary.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/+diff-summary.fixed.md diff --git a/changelog/+diff-summary.fixed.md b/changelog/+diff-summary.fixed.md new file mode 100644 index 0000000000..830ccccf8a --- /dev/null +++ b/changelog/+diff-summary.fixed.md @@ -0,0 +1 @@ +Fixed incorrect data diff counter when viewing a branch or proposed changes