mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 05:26:25 +00:00
chore: minor ui improvements
This commit is contained in:
@@ -1,13 +1,21 @@
|
|||||||
import { useState } from "react";
|
/* eslint-disable no-nested-ternary */
|
||||||
import { faChevronRight, faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
|
import { useEffect, useState } from "react";
|
||||||
|
import {
|
||||||
|
faChevronRight,
|
||||||
|
faExclamationTriangle,
|
||||||
|
faEye,
|
||||||
|
faEyeSlash
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||||
|
import { AxiosError } from "axios";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { FormControl, FormLabel, SecretInput, Spinner, Tooltip } from "@app/components/v2";
|
import { FormControl, FormLabel, SecretInput, Spinner, Tooltip } from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useGetSecretReferenceTree } from "@app/hooks/api";
|
import { useGetSecretReferenceTree } from "@app/hooks/api";
|
||||||
import { TSecretReferenceTraceNode } from "@app/hooks/api/types";
|
import { ApiErrorTypes, TApiErrors, TSecretReferenceTraceNode } from "@app/hooks/api/types";
|
||||||
|
|
||||||
import style from "./SecretReferenceDetails.module.css";
|
import style from "./SecretReferenceDetails.module.css";
|
||||||
|
|
||||||
@@ -84,7 +92,7 @@ export const SecretReferenceTree = ({ secretPath, environment, secretKey }: Prop
|
|||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const projectId = currentWorkspace?.id || "";
|
const projectId = currentWorkspace?.id || "";
|
||||||
|
|
||||||
const { data, isPending } = useGetSecretReferenceTree({
|
const { data, isPending, isError, error } = useGetSecretReferenceTree({
|
||||||
secretPath,
|
secretPath,
|
||||||
environmentSlug: environment,
|
environmentSlug: environment,
|
||||||
projectId,
|
projectId,
|
||||||
@@ -94,6 +102,26 @@ export const SecretReferenceTree = ({ secretPath, environment, secretKey }: Prop
|
|||||||
const tree = data?.tree;
|
const tree = data?.tree;
|
||||||
const secretValue = data?.value;
|
const secretValue = data?.value;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (error instanceof AxiosError) {
|
||||||
|
const err = error?.response?.data as TApiErrors;
|
||||||
|
|
||||||
|
if (err?.error === ApiErrorTypes.CustomForbiddenError) {
|
||||||
|
createNotification({
|
||||||
|
title: "You don't have permission to view reference tree",
|
||||||
|
text: "You don't have permission to view one or more of the referenced secrets.",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createNotification({
|
||||||
|
title: "Error fetching secret reference tree",
|
||||||
|
text: "Please try again later.",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [error]);
|
||||||
|
|
||||||
if (isPending) {
|
if (isPending) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center py-4">
|
<div className="flex items-center justify-center py-4">
|
||||||
@@ -114,11 +142,16 @@ export const SecretReferenceTree = ({ secretPath, environment, secretKey }: Prop
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<FormLabel className="mb-2" label="Reference Tree" />
|
<FormLabel className="mb-2" label="Reference Tree" />
|
||||||
<div className="thin-scrollbar relative max-h-96 overflow-auto rounded-md border border-mineshaft-600 bg-bunker-700 py-6 text-sm text-mineshaft-200">
|
<div className="thin-scrollbar relative max-h-96 overflow-auto rounded-md border border-mineshaft-600 bg-bunker-700 py-6 text-sm text-mineshaft-200">
|
||||||
{tree && (
|
{isError ? (
|
||||||
|
<div className="flex items-center justify-center py-4">
|
||||||
|
<FontAwesomeIcon icon={faExclamationTriangle} className="mr-2 text-red-500" />
|
||||||
|
<p className="text-red-500">Error fetching secret reference tree</p>
|
||||||
|
</div>
|
||||||
|
) : tree ? (
|
||||||
<ul className={style.tree}>
|
<ul className={style.tree}>
|
||||||
<SecretReferenceNode node={tree} isRoot secretKey={secretKey} />
|
<SecretReferenceNode node={tree} isRoot secretKey={secretKey} />
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 text-sm text-mineshaft-400">
|
<div className="mt-2 text-sm text-mineshaft-400">
|
||||||
Click a secret key to view its sub-references.
|
Click a secret key to view its sub-references.
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ export enum ApiErrorTypes {
|
|||||||
ValidationError = "ValidationFailure",
|
ValidationError = "ValidationFailure",
|
||||||
BadRequestError = "BadRequest",
|
BadRequestError = "BadRequest",
|
||||||
UnauthorizedError = "UnauthorizedError",
|
UnauthorizedError = "UnauthorizedError",
|
||||||
ForbiddenError = "PermissionDenied"
|
ForbiddenError = "PermissionDenied",
|
||||||
|
CustomForbiddenError = "ForbiddenError"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TApiErrors =
|
export type TApiErrors =
|
||||||
@@ -69,6 +70,12 @@ export type TApiErrors =
|
|||||||
details: PureAbility["rules"];
|
details: PureAbility["rules"];
|
||||||
statusCode: 403;
|
statusCode: 403;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
reqId: string;
|
||||||
|
error: ApiErrorTypes.CustomForbiddenError;
|
||||||
|
message: string;
|
||||||
|
statusCode: 403;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
reqId: string;
|
reqId: string;
|
||||||
statusCode: 400;
|
statusCode: 400;
|
||||||
|
|||||||
Reference in New Issue
Block a user