Skip to content
Closed
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
12 changes: 12 additions & 0 deletions .github/workflows/sync-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
paths:
- 'docs/docs/**'
- 'docs/sidebars.ts'
- 'docs/sidebar-releases.ts'
- 'docs/plugins/**'
- 'docs/src/components/ReleaseFeed/**'
workflow_dispatch:

jobs:
Expand All @@ -32,10 +35,19 @@ jobs:
# Remove existing files in target repo
rm -rf target-repo/docs/docs/*
rm -f target-repo/docs/sidebars.ts
rm -f target-repo/docs/sidebar-releases.ts
rm -rf target-repo/docs/plugins
rm -rf target-repo/docs/src/components/ReleaseFeed

# Copy files from source repo to target repo
cp -r source-repo/docs/docs/* target-repo/docs/docs/
cp source-repo/docs/sidebars.ts target-repo/docs/sidebars.ts
# sidebars.ts imports ./sidebar-releases; the ReleaseFeed component and
# release-notes-data plugin power the /release-notes/infrahub feed.
cp source-repo/docs/sidebar-releases.ts target-repo/docs/sidebar-releases.ts
cp -r source-repo/docs/plugins target-repo/docs/plugins
mkdir -p target-repo/docs/src/components
cp -r source-repo/docs/src/components/ReleaseFeed target-repo/docs/src/components/ReleaseFeed

# Commit and push changes to target repository
cd target-repo
Expand Down
1 change: 1 addition & 0 deletions changelog/9892.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Following an IP prefix or address link from the relationship tabs of an IPAM namespace now keeps you in that namespace, instead of redirecting to the default namespace.
32 changes: 16 additions & 16 deletions docs/package-lock.json

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

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LinkButton } from "@infrahub/ui";
import type { PressEvent } from "react-aria-components";

import type { overrideQueryParams } from "@/shared/api/rest/fetch";
import { Checkbox } from "@/shared/components/aria/checkbox";

import { useAuth } from "@/entities/authentication/ui/useAuth";
Expand All @@ -13,6 +14,7 @@ export interface TableIdentifierCellProps {
label: React.ReactNode;
isSelected?: boolean;
onClickCheckbox?: (e: PressEvent) => void;
overrideParams?: overrideQueryParams[];
}

export function TableIdentifierCell({
Expand All @@ -21,6 +23,7 @@ export function TableIdentifierCell({
label,
isSelected,
onClickCheckbox,
overrideParams,
}: TableIdentifierCellProps) {
const { isAuthenticated } = useAuth();
return (
Expand All @@ -36,7 +39,7 @@ export function TableIdentifierCell({
<LinkButton
variant="ghost"
size="sm"
href={getObjectDetailsUrl(objectKind, objectId)}
href={getObjectDetailsUrl(objectKind, objectId, overrideParams)}
className="-mx-1 truncate rounded-xl px-2 text-custom-blue-700 hover:underline"
>
{label}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { PopoverTriggerProps } from "@radix-ui/react-popover";
import { type ColumnDef, createColumnHelper } from "@tanstack/react-table";

import type { overrideQueryParams } from "@/shared/api/rest/fetch";
import { FROM_RESOURCE_POOL_SUFFIX } from "@/shared/components/form/constants";
import { TableCell } from "@/shared/components/table/table-cell";
import { sortByOrderWeight } from "@/shared/utils/common";
Expand Down Expand Up @@ -34,7 +35,8 @@ import { isGenericSchema } from "@/entities/schema/utils/is-generic-schema";
const columnHelper = createColumnHelper<NodeObject>();

export function getObjectIdentifierColumns(
schema: ModelSchema
schema: ModelSchema,
identifierOverrideParams?: overrideQueryParams[]
): Array<ColumnDef<NodeObject, string>> {
return [
columnHelper.accessor((node) => getNodeLabel(node), {
Expand All @@ -59,6 +61,7 @@ export function getObjectIdentifierColumns(
label={label}
isSelected={row.getIsSelected()}
onClickCheckbox={getToggleSelectedRowHandler({ row, table })}
overrideParams={identifierOverrideParams}
/>
);
},
Expand Down Expand Up @@ -145,10 +148,11 @@ export function getObjectFieldsColumns(

export const getObjectTableColumns = (
schema: ModelSchema,
headerProps?: PopoverTriggerProps
headerProps?: PopoverTriggerProps,
identifierOverrideParams?: overrideQueryParams[]
): Array<ColumnDef<NodeObject>> => {
return [
...getObjectIdentifierColumns(schema),
...getObjectIdentifierColumns(schema, identifierOverrideParams),
...getObjectGenericColumns(schema),
...getObjectFieldsColumns(schema, headerProps),
] as Array<ColumnDef<NodeObject>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DataTable } from "@/shared/components/table/data-table";
import { InfiniteScroll } from "@/shared/components/utils/infinite-scroll";
import useFilters from "@/shared/hooks/useFilters";

import { IP_NAMESPACE_GENERIC, IPAM_QSP } from "@/entities/ipam/constants";
import { ObjectTableEmpty } from "@/entities/nodes/object/ui/object-table/object-table-empty";
import { getObjectTableColumns } from "@/entities/nodes/object/ui/object-table/utils/get-object-table-columns";
import {
Expand All @@ -15,6 +16,7 @@ import { ToolbarDissociateAction } from "@/entities/nodes/relationships/ui/relat
import { canDissociateRelationship } from "@/entities/nodes/relationships/utils/can-dissociate-relationship";
import { useGetObjectPermissions } from "@/entities/permission/ui/queries/get-object-permissions.query";
import { useSchema } from "@/entities/schema/ui/hooks/useSchema";
import { isOfKind } from "@/entities/schema/utils/is-of-kind";

export interface RelationshipTableProps extends UseObjectRelationshipsParams {}

Expand Down Expand Up @@ -49,8 +51,18 @@ export function RelationshipTable({
}

const flatData = data?.pages?.flat() ?? [];

// On an IP namespace's relationship tabs (e.g. its prefixes/addresses), the active
// namespace lives in the route path, not the `namespace` query param that IPAM links
// rely on. Forward it explicitly so child IP links stay in this namespace instead of
// falling back to the default one.
const identifierOverrideParams =
parentSchema && isOfKind(IP_NAMESPACE_GENERIC, parentSchema)
? [{ name: IPAM_QSP.NAMESPACE, value: parentId }]
: undefined;

const columns = [
...getObjectTableColumns(relationshipSchema, { disabled: true }),
...getObjectTableColumns(relationshipSchema, { disabled: true }, identifierOverrideParams),
getRelationshipActionsColumn({
parentId,
parentKind,
Expand Down
49 changes: 49 additions & 0 deletions frontend/app/src/entities/nodes/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { afterEach, describe, expect, it } from "vitest";

import { store } from "@/shared/stores";

import { IP_PREFIX_GENERIC, IPAM_QSP } from "@/entities/ipam/constants";
import { getObjectDetailsUrl } from "@/entities/nodes/utils";
import {
genericSchemasAtom,
nodeSchemasAtom,
profileSchemasAtom,
templateSchemasAtom,
} from "@/entities/schema/stores/schema.atom";

import { generateNodeSchema } from "../../../tests/fake/schema";

const ipPrefixSchema = generateNodeSchema({
kind: "BuiltinIPPrefix",
name: "IPPrefix",
namespace: "Builtin",
inherit_from: [IP_PREFIX_GENERIC],
});

describe("getObjectDetailsUrl", () => {
afterEach(() => {
store.set(nodeSchemasAtom, []);
store.set(genericSchemasAtom, []);
store.set(profileSchemasAtom, []);
store.set(templateSchemasAtom, []);
});

it("keeps the namespace context for an IP prefix link when passed as an override param", () => {
store.set(nodeSchemasAtom, [ipPrefixSchema]);

const url = getObjectDetailsUrl("BuiltinIPPrefix", "prefix-1", [
{ name: IPAM_QSP.NAMESPACE, value: "namespace-1" },
]);

expect(url).toContain("/ipam/BuiltinIPPrefix/prefix-1");
expect(url).toContain(`${IPAM_QSP.NAMESPACE}=namespace-1`);
});

it("does not add a namespace param to an IP prefix link when none is provided", () => {
store.set(nodeSchemasAtom, [ipPrefixSchema]);

const url = getObjectDetailsUrl("BuiltinIPPrefix", "prefix-1");

expect(url).toBe("/ipam/BuiltinIPPrefix/prefix-1");
});
});
36 changes: 18 additions & 18 deletions frontend/packages/plugins/template/package-lock.json

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

Loading
Loading