mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 16:28:19 +00:00
chore: fixed error with typings
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
import { Checkbox, PopoverContent } from "@app/components/v2";
|
||||||
|
|
||||||
|
import { WsTag } from "../../hooks/api/tags/types";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
wsTags: WsTag[] | undefined;
|
||||||
|
secKey: string;
|
||||||
|
selectedTagIds: Record<string, boolean>;
|
||||||
|
handleSelectTag: (wsTag: WsTag) => void;
|
||||||
|
handleTagOnMouseEnter: (wsTag: WsTag) => void;
|
||||||
|
handleTagOnMouseLeave: () => void;
|
||||||
|
checkIfTagIsVisible: (wsTag: WsTag) => boolean;
|
||||||
|
handleOnCreateTagOpen: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddTagPopoverContent = ({
|
||||||
|
wsTags,
|
||||||
|
secKey,
|
||||||
|
selectedTagIds,
|
||||||
|
handleSelectTag,
|
||||||
|
handleTagOnMouseEnter,
|
||||||
|
handleTagOnMouseLeave,
|
||||||
|
checkIfTagIsVisible,
|
||||||
|
handleOnCreateTagOpen
|
||||||
|
}: Props) => {
|
||||||
|
return (
|
||||||
|
<PopoverContent
|
||||||
|
side="left"
|
||||||
|
className="relative max-h-96 w-auto min-w-[200px] p-2 overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 text-bunker-200"
|
||||||
|
hideCloseBtn
|
||||||
|
>
|
||||||
|
<div className=" text-center text-sm font-medium text-bunker-200">
|
||||||
|
Add tags to {secKey || "this secret"}
|
||||||
|
</div>
|
||||||
|
<div className="absolute left-0 w-full border-mineshaft-600 border-t mt-2" />
|
||||||
|
<div className="flex flex-col space-y-1.5">
|
||||||
|
{wsTags?.map((wsTag: WsTag) => (
|
||||||
|
<div key={`tag-${wsTag._id}`} className="mt-4 h-[32px] relative flex items-center justify-start hover:border-mineshaft-600 hover:border hover:bg-mineshaft-700 p-2 rounded-md hover:text-bunker-200 bg-none"
|
||||||
|
onClick={() => handleSelectTag(wsTag)}
|
||||||
|
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
|
||||||
|
onMouseLeave={() => handleTagOnMouseLeave()}
|
||||||
|
tabIndex={0} role="button"
|
||||||
|
onKeyDown={() => { }}>
|
||||||
|
{
|
||||||
|
|
||||||
|
(checkIfTagIsVisible(wsTag) || selectedTagIds?.[wsTag.slug]) && <Checkbox
|
||||||
|
id="autoCapitalization"
|
||||||
|
isChecked={selectedTagIds?.[wsTag.slug]}
|
||||||
|
className="absolute top-[50%] translate-y-[-50%] left-[10px] "
|
||||||
|
checkIndicatorBg={`${!selectedTagIds?.[wsTag.slug] ? "text-transparent" : "text-mineshaft-800"}`}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
<div className="ml-7 flex items-center gap-3">
|
||||||
|
<div className="w-[10px] h-[10px] rounded-full" style={{ background: wsTag?.tagColor ? wsTag.tagColor : "#bec2c8" }}> </div>
|
||||||
|
<span >
|
||||||
|
{wsTag.slug}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div
|
||||||
|
className="h-[32px] relative flex items-center cursor-pointer justify-start border-mineshaft-600 border bg-mineshaft-700 p-2 rounded-md hover:text-bunker-200 bg-none"
|
||||||
|
onClick={() => handleOnCreateTagOpen()}
|
||||||
|
tabIndex={0} role="button"
|
||||||
|
onKeyDown={() => { }}>
|
||||||
|
<FontAwesomeIcon icon={faPlus} className="ml-1 mr-2" />
|
||||||
|
<span> Add new tag</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddTagPopoverContent
|
||||||
@@ -8,11 +8,12 @@ export type CheckboxProps = Omit<
|
|||||||
CheckboxPrimitive.CheckboxProps,
|
CheckboxPrimitive.CheckboxProps,
|
||||||
"checked" | "disabled" | "required"
|
"checked" | "disabled" | "required"
|
||||||
> & {
|
> & {
|
||||||
children: ReactNode;
|
children?: ReactNode;
|
||||||
id: string;
|
id: string;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
isChecked?: boolean;
|
isChecked?: boolean;
|
||||||
isRequired?: boolean;
|
isRequired?: boolean;
|
||||||
|
checkIndicatorBg?: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Checkbox = ({
|
export const Checkbox = ({
|
||||||
@@ -22,6 +23,7 @@ export const Checkbox = ({
|
|||||||
isChecked,
|
isChecked,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
isRequired,
|
isRequired,
|
||||||
|
checkIndicatorBg,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps): JSX.Element => {
|
}: CheckboxProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
@@ -39,7 +41,7 @@ export const Checkbox = ({
|
|||||||
{...props}
|
{...props}
|
||||||
id={id}
|
id={id}
|
||||||
>
|
>
|
||||||
<CheckboxPrimitive.Indicator className="text-bunker-800">
|
<CheckboxPrimitive.Indicator className={`${checkIndicatorBg || "text-bunker-800"}`}>
|
||||||
<FontAwesomeIcon icon={faCheck} size="sm" />
|
<FontAwesomeIcon icon={faCheck} size="sm" />
|
||||||
</CheckboxPrimitive.Indicator>
|
</CheckboxPrimitive.Indicator>
|
||||||
</CheckboxPrimitive.Root>
|
</CheckboxPrimitive.Root>
|
||||||
|
|||||||
@@ -1,17 +1,10 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { faClose } from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import { cva, VariantProps } from "cva";
|
import { cva, VariantProps } from "cva";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
onClose?: () => void;
|
|
||||||
color?: string;
|
|
||||||
styles?: Record<string, string>
|
|
||||||
isDisabled?: boolean;
|
|
||||||
tagColor: string;
|
|
||||||
} & VariantProps<typeof tagVariants>;
|
} & VariantProps<typeof tagVariants>;
|
||||||
|
|
||||||
const tagVariants = cva(
|
const tagVariants = cva(
|
||||||
@@ -34,12 +27,7 @@ export const Tag = ({
|
|||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
colorSchema = "gray",
|
colorSchema = "gray",
|
||||||
color,
|
size = "sm" }: Props) => (
|
||||||
isDisabled,
|
|
||||||
size = "sm",
|
|
||||||
onClose,
|
|
||||||
styles = {}
|
|
||||||
}: Props) => (
|
|
||||||
<div
|
<div
|
||||||
className={twMerge(tagVariants({ colorSchema, className, size }))}
|
className={twMerge(tagVariants({ colorSchema, className, size }))}
|
||||||
>
|
>
|
||||||
|
|||||||
+18
-18
@@ -55,65 +55,65 @@ export const leaveConfirmDefaultMessage = "Your changes will be lost if you leav
|
|||||||
export const secretTagsColors = [
|
export const secretTagsColors = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
hex: '#bec2c8',
|
hex: "#bec2c8",
|
||||||
rgba: "rgb(128,128,128, 0.8)",
|
rgba: "rgb(128,128,128, 0.8)",
|
||||||
name: 'Grey',
|
name: "Grey",
|
||||||
selected: true
|
selected: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
hex: '#95a2b3',
|
hex: "#95a2b3",
|
||||||
rgba: "rgb(0,0,255, 0.8)",
|
rgba: "rgb(0,0,255, 0.8)",
|
||||||
name: 'blue',
|
name: "blue",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
hex: '#5e6ad2',
|
hex: "#5e6ad2",
|
||||||
rgba: "rgb(128,0,128, 0.8)",
|
rgba: "rgb(128,0,128, 0.8)",
|
||||||
name: 'Purple',
|
name: "Purple",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
hex: '#26b5ce',
|
hex: "#26b5ce",
|
||||||
rgba: "rgb(0,128,128, 0.8)",
|
rgba: "rgb(0,128,128, 0.8)",
|
||||||
name: 'Teal',
|
name: "Teal",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
hex: '#4cb782',
|
hex: "#4cb782",
|
||||||
rgba: "rgb(0,128,0, 0.8)",
|
rgba: "rgb(0,128,0, 0.8)",
|
||||||
name: 'Green',
|
name: "Green",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
hex: '#f2c94c',
|
hex: "#f2c94c",
|
||||||
rgba: "rgb(255,255,0, 0.8)",
|
rgba: "rgb(255,255,0, 0.8)",
|
||||||
name: 'Yellow',
|
name: "Yellow",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 7,
|
id: 7,
|
||||||
hex: '#f2994a',
|
hex: "#f2994a",
|
||||||
rgba: "rgb(128,128,0, 0.8)",
|
rgba: "rgb(128,128,0, 0.8)",
|
||||||
name: 'Orange',
|
name: "Orange",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 8,
|
id: 8,
|
||||||
hex: '#f7c8c1',
|
hex: "#f7c8c1",
|
||||||
rgba: "rgb(128,0,0, 0.8)",
|
rgba: "rgb(128,0,0, 0.8)",
|
||||||
name: 'Pink',
|
name: "Pink",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 9,
|
id: 9,
|
||||||
hex: '#eb5757',
|
hex: "#eb5757",
|
||||||
rgba: "rgb(255,0,0, 0.8)",
|
rgba: "rgb(255,0,0, 0.8)",
|
||||||
name: 'Red',
|
name: "Red",
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -7,9 +7,7 @@ import {
|
|||||||
CreateTagRes,
|
CreateTagRes,
|
||||||
DeleteTagDTO,
|
DeleteTagDTO,
|
||||||
DeleteWsTagRes,
|
DeleteWsTagRes,
|
||||||
QueryTag,
|
|
||||||
UserWsTags,
|
UserWsTags,
|
||||||
WsTag
|
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const workspaceTags = {
|
const workspaceTags = {
|
||||||
@@ -32,33 +30,35 @@ export const useGetWsTags = (workspaceID: string) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const useCreateWsTag = () => {
|
export const useCreateWsTag = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation<CreateTagRes, {}, CreateTagDTO>({
|
return useMutation<CreateTagRes, {}, CreateTagDTO>({
|
||||||
mutationFn: async ({ workspaceID, tagName, tagColor, tagSlug }: QueryTag) => {
|
mutationFn: async ({ workspaceID, tagName, tagColor, tagSlug }) => {
|
||||||
const { data } = await apiRequest.post(`/api/v2/workspace/${workspaceID}/tags`, {
|
const { data } = await apiRequest.post(`/api/v2/workspace/${workspaceID}/tags`, {
|
||||||
name: tagName,
|
name: tagName,
|
||||||
tagColor: tagColor,
|
tagColor,
|
||||||
slug: tagSlug
|
slug: tagSlug
|
||||||
})
|
})
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
onSuccess: (tagData: WsTag) => {
|
onSuccess: (tagData) => {
|
||||||
queryClient.invalidateQueries(workspaceTags.getWsTags(tagData?.workspace));
|
queryClient.invalidateQueries(workspaceTags.getWsTags(tagData?.workspace));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const useDeleteWsTag = () => {
|
export const useDeleteWsTag = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation<DeleteWsTagRes, {}, DeleteTagDTO>({
|
return useMutation<DeleteWsTagRes, {}, DeleteTagDTO>({
|
||||||
mutationFn: async ({ tagID }: {tagID: string}) => {
|
mutationFn: async ({ tagID }) => {
|
||||||
const { data } = await apiRequest.delete(`/api/v2/workspace/tags/${tagID}`);
|
const { data } = await apiRequest.delete(`/api/v2/workspace/tags/${tagID}`);
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
onSuccess: (tagData: WsTag) => {
|
onSuccess: (tagData) => {
|
||||||
queryClient.invalidateQueries(workspaceTags.getWsTags(tagData?.workspace));
|
queryClient.invalidateQueries(workspaceTags.getWsTags(tagData?.workspace));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export type WsTag = {
|
|||||||
_id: string;
|
_id: string;
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
|
tagColor?: string;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
@@ -16,6 +17,7 @@ export type CreateTagDTO = {
|
|||||||
workspaceID: string;
|
workspaceID: string;
|
||||||
tagSlug: string;
|
tagSlug: string;
|
||||||
tagName: string;
|
tagName: string;
|
||||||
|
tagColor: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateTagRes = {
|
export type CreateTagRes = {
|
||||||
@@ -23,6 +25,7 @@ export type CreateTagRes = {
|
|||||||
slug: string;
|
slug: string;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
tagColor?: string;
|
||||||
user: string;
|
user: string;
|
||||||
_id: string;
|
_id: string;
|
||||||
};
|
};
|
||||||
@@ -51,11 +54,4 @@ export type TagColor = {
|
|||||||
rgba: string
|
rgba: string
|
||||||
name: string
|
name: string
|
||||||
selected: boolean
|
selected: boolean
|
||||||
}
|
|
||||||
|
|
||||||
export type QueryTag = {
|
|
||||||
workspaceID: string;
|
|
||||||
tagName: string;
|
|
||||||
tagColor: string;
|
|
||||||
tagSlug: string
|
|
||||||
}
|
}
|
||||||
@@ -297,6 +297,8 @@ export const DashboardPage = () => {
|
|||||||
resolver: yupResolver(schema)
|
resolver: yupResolver(schema)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("300 => secrets", secrets)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
control,
|
control,
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ const secretSchema = yup.object({
|
|||||||
yup.object({
|
yup.object({
|
||||||
_id: yup.string().required(),
|
_id: yup.string().required(),
|
||||||
name: yup.string().required(),
|
name: yup.string().required(),
|
||||||
slug: yup.string().required()
|
slug: yup.string().required(),
|
||||||
|
tagColor: yup.string().nullable(),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
overrideAction: yup.string().notRequired().oneOf(Object.values(SecretActionType)),
|
overrideAction: yup.string().notRequired().oneOf(Object.values(SecretActionType)),
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
|
||||||
import * as yup from "yup";
|
|
||||||
import { secretTagsColors } from "~/const"
|
|
||||||
import {
|
import {
|
||||||
faCheck
|
faCheck
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import * as yup from "yup";
|
||||||
|
|
||||||
import { Button, FormControl, Input, ModalClose, Tooltip } from "@app/components/v2";
|
import { Button, FormControl, Input, ModalClose, Tooltip } from "@app/components/v2";
|
||||||
import { isValidHexColor } from "~/components/utilities/isValidHexColor";
|
|
||||||
import { TagColor } from '~/hooks/api/tags/types';
|
import { isValidHexColor } from "../../../../components/utilities/isValidHexColor";
|
||||||
|
import { secretTagsColors } from "../../../../const"
|
||||||
|
import { TagColor } from "../../../../hooks/api/tags/types";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -33,8 +33,8 @@ export const CreateTagModal = ({ onCreateTag }: Props): JSX.Element => {
|
|||||||
resolver: yupResolver(createTagSchema)
|
resolver: yupResolver(createTagSchema)
|
||||||
});
|
});
|
||||||
|
|
||||||
const [tagsColors, setTagsColors] = useState<TagColor>(secretTagsColors)
|
const [tagsColors] = useState<TagColor[]>(secretTagsColors)
|
||||||
const [selectedTagColor, setSelectedTagColor] = useState<TagColor>({})
|
const [selectedTagColor, setSelectedTagColor] = useState<TagColor>(tagsColors[0])
|
||||||
const [showHexInput, setShowHexInput] = useState<boolean>(false)
|
const [showHexInput, setShowHexInput] = useState<boolean>(false)
|
||||||
const [tagColor, setTagColor] = useState<string>("")
|
const [tagColor, setTagColor] = useState<string>("")
|
||||||
|
|
||||||
@@ -46,12 +46,11 @@ export const CreateTagModal = ({ onCreateTag }: Props): JSX.Element => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const clonedTagColors = [...tagsColors]
|
const clonedTagColors = [...tagsColors]
|
||||||
for (const tagColor of clonedTagColors) {
|
const selectedTagBgColor = clonedTagColors.find($tagColor => $tagColor.selected);
|
||||||
if (tagColor.selected) {
|
|
||||||
setSelectedTagColor(tagColor)
|
if (selectedTagBgColor) {
|
||||||
setTagColor(tagColor.hex)
|
setSelectedTagColor(selectedTagBgColor);
|
||||||
break
|
setTagColor(selectedTagBgColor.hex);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -60,124 +59,133 @@ export const CreateTagModal = ({ onCreateTag }: Props): JSX.Element => {
|
|||||||
const tagsHexWrapper = document.querySelector(".tags-hex-wrapper")
|
const tagsHexWrapper = document.querySelector(".tags-hex-wrapper")
|
||||||
|
|
||||||
if (showHexInput) {
|
if (showHexInput) {
|
||||||
tagsList?.classList.add('hide-tags')
|
tagsList?.classList.add("hide-tags")
|
||||||
tagsList?.classList.remove('show-tags')
|
tagsList?.classList.remove("show-tags")
|
||||||
tagsHexWrapper?.classList.add('show-hex-input')
|
tagsHexWrapper?.classList.add("show-hex-input")
|
||||||
tagsHexWrapper?.classList.remove('hide-hex-input')
|
tagsHexWrapper?.classList.remove("hide-hex-input")
|
||||||
} else {
|
} else {
|
||||||
tagsList?.classList.remove('hide-tags')
|
tagsList?.classList.remove("hide-tags")
|
||||||
tagsList?.classList.add('show-tags')
|
tagsList?.classList.add("show-tags")
|
||||||
tagsHexWrapper?.classList.remove('show-hex-input')
|
tagsHexWrapper?.classList.remove("show-hex-input")
|
||||||
tagsHexWrapper?.classList.add('hide-hex-input')
|
tagsHexWrapper?.classList.add("hide-hex-input")
|
||||||
}
|
}
|
||||||
}, [showHexInput])
|
}, [showHexInput])
|
||||||
|
|
||||||
const handleColorChange = (tagColor: TagColor) => {
|
|
||||||
const clonedTagColors = [...tagsColors]
|
const handleColorChange = (clickedTagColor: TagColor) => {
|
||||||
const tagColorIndex = clonedTagColors.findIndex(_tagColor => _tagColor.id === tagColor.id)
|
const updatedTagColors = [...tagsColors];
|
||||||
const _selectedTagColor = clonedTagColors[tagColorIndex]
|
const clickedTagColorIndex = updatedTagColors.findIndex(($tagColor) => $tagColor.id === clickedTagColor.id);
|
||||||
clonedTagColors.forEach(tagColor => {
|
const updatedClickedTagColor = updatedTagColors[clickedTagColorIndex];
|
||||||
tagColor.selected = false
|
|
||||||
})
|
updatedTagColors.forEach((tgColor) => {
|
||||||
if (selectedTagColor.id !== tagColor.id) {
|
// eslint-disable-next-line no-param-reassign
|
||||||
_selectedTagColor.selected = !_selectedTagColor.selected
|
tgColor.selected = false;
|
||||||
setSelectedTagColor(_selectedTagColor)
|
});
|
||||||
setTagColor(_selectedTagColor.hex)
|
|
||||||
|
if (selectedTagColor.id !== clickedTagColor.id) {
|
||||||
|
updatedClickedTagColor.selected = !updatedClickedTagColor.selected;
|
||||||
|
setSelectedTagColor(updatedClickedTagColor);
|
||||||
|
setTagColor(updatedClickedTagColor.hex);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<form onSubmit={handleSubmit(onFormSubmit)}>
|
||||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
<Controller
|
||||||
<Controller
|
control={control}
|
||||||
control={control}
|
name="name"
|
||||||
name="name"
|
defaultValue=""
|
||||||
defaultValue=""
|
render={({ field, fieldState: { error } }) => (
|
||||||
render={({ field, fieldState: { error } }) => (
|
<FormControl label="Tag Name" isError={Boolean(error)} errorText={error?.message}>
|
||||||
<FormControl label="Tag Name" isError={Boolean(error)} errorText={error?.message}>
|
<Input {...field} placeholder="Type your tag name" />
|
||||||
<Input {...field} placeholder="Type your tag name" />
|
</FormControl>
|
||||||
</FormControl>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<label className="text-mineshaft-400">Tag color</label>
|
<h6 className="text-mineshaft-400">Tag color</h6>
|
||||||
<div className="flex gap-2 h-[50px]">
|
<div className="flex gap-2 h-[50px]">
|
||||||
<div className="w-[12%] h-[2.813rem] inline-flex font-inter items-center justify-center border relative rounded-md border-mineshaft-500 bg-mineshaft-900 hover:bg-mineshaft-800">
|
<div className="w-[12%] h-[2.813rem] inline-flex font-inter items-center justify-center border relative rounded-md border-mineshaft-500 bg-mineshaft-900 hover:bg-mineshaft-800">
|
||||||
<div className={`w-[26px] h-[26px] rounded-full`} style={{ background: `${tagColor}` }}></div>
|
<div className="w-[26px] h-[26px] rounded-full" style={{ background: `${tagColor}` }} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-[88%] h-[2.813rem] flex-wrap inline-flex gap-3 items-center border rounded-md border-mineshaft-500 bg-mineshaft-900 hover:bg-mineshaft-800 relative">
|
||||||
|
<div className="flex-wrap inline-flex gap-3 items-center secret-tags-wrapper pl-3">
|
||||||
|
{
|
||||||
|
tagsColors.map(($tagColor: TagColor) => {
|
||||||
|
return (
|
||||||
|
<div key={`tag-color-${$tagColor.id}`}>
|
||||||
|
<Tooltip content={`${$tagColor.name}`}>
|
||||||
|
<div className=" flex items-center justify-center w-[26px] h-[26px] hover:ring-offset-2 hover:ring-2 bg-[#bec2c8] border-2 p-2 hover:shadow-lg border-transparent hover:border-black rounded-full"
|
||||||
|
key={`tag-${$tagColor.id}`}
|
||||||
|
style={{ backgroundColor: `${$tagColor.hex}` }}
|
||||||
|
|
||||||
|
onClick={() => handleColorChange($tagColor)}
|
||||||
|
tabIndex={0} role="button"
|
||||||
|
onKeyDown={() => { }}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
$tagColor.selected && <FontAwesomeIcon icon={faCheck} style={{ color: "#00000070" }} />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-[88%] h-[2.813rem] flex-wrap inline-flex gap-3 items-center border relative rounded-md border-mineshaft-500 bg-mineshaft-900 hover:bg-mineshaft-800 relative">
|
<div className="flex items-center gap-2 px-2 tags-hex-wrapper" >
|
||||||
{
|
<div className="w-1/6 flex items-center relative rounded-md hover:bg-mineshaft-800">
|
||||||
(
|
{
|
||||||
<div className="flex-wrap inline-flex gap-3 items-center secret-tags-wrapper pl-3">
|
isValidHexColor(tagColor) && (
|
||||||
{
|
<div className="w-[26px] h-[26px] rounded-full flex items-center justify-center" style={{ background: `${tagColor}` }}>
|
||||||
tagsColors.map((tagColor: TagColor) => {
|
<FontAwesomeIcon icon={faCheck} style={{ color: "#00000070" }} />
|
||||||
return (
|
</div>
|
||||||
<Tooltip content={`${tagColor.name}`}>
|
)
|
||||||
<div className={`flex items-center justify-center w-[26px] h-[26px] hover:ring-offset-2 hover:ring-2 bg-[#bec2c8] border-2 p-2 hover:shadow-lg border-transparent hover:border-black rounded-full`} key={`tag-${tagColor.id}`} style={{ backgroundColor: `${tagColor.hex}` }} onClick={() => handleColorChange(tagColor)}>
|
}
|
||||||
{
|
|
||||||
tagColor.selected && <FontAwesomeIcon icon={faCheck} style={{ color: `#00000070` }} />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className="flex items-center gap-2 px-2 tags-hex-wrapper" >
|
{
|
||||||
<div className="w-1/6 flex items-center relative rounded-md hover:bg-mineshaft-800">
|
!isValidHexColor(tagColor) && (
|
||||||
{
|
<div className="border-dashed border bg-blue rounded-full w-[26px] h-[26px] border-mineshaft-500" />
|
||||||
isValidHexColor(tagColor) && (
|
)
|
||||||
<div className={`w-[26px] h-[26px] rounded-full flex items-center justify-center`} style={{ background: `${tagColor}` }}>
|
}
|
||||||
<FontAwesomeIcon icon={faCheck} style={{ color: `#00000070` }} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!isValidHexColor(tagColor) && (
|
|
||||||
<div class="border-dashed border bg-blue rounded-full w-[26px] h-[26px] border-mineshaft-500"></div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="w-10/12">
|
|
||||||
<Input
|
|
||||||
variant="plain"
|
|
||||||
className="w-full focus:text-bunker-100 focus:ring-transparent bg-transparent"
|
|
||||||
autoCapitalization={false}
|
|
||||||
value={tagColor}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setTagColor(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-10/12">
|
||||||
|
<Input
|
||||||
|
variant="plain"
|
||||||
|
className="w-full focus:text-bunker-100 focus:ring-transparent bg-transparent"
|
||||||
|
autoCapitalization={false}
|
||||||
|
value={tagColor}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setTagColor(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="w-[26px] h-[26px] flex items-center justify-center absolute top-[10px] right-[-4px] translate-x-[-50%]">
|
<div className="w-[26px] h-[26px] flex items-center justify-center absolute top-[10px] right-[-4px] translate-x-[-50%]">
|
||||||
<div className="border-mineshaft-500 border h-[2.1rem] mr-4 absolute right-5"></div>
|
<div className="border-mineshaft-500 border h-[2.1rem] mr-4 absolute right-5" />
|
||||||
<div className={`flex items-center justify-center w-[26px] h-[26px] bg-transparent cursor-pointer hover:ring-offset-1 hover:ring-2 border-mineshaft-500 border bg-mineshaft-900 rounded-[3px] p-2 ${showHexInput ? 'tags-conic-bg rounded-full' : ''}`} onClick={() => setShowHexInput((prev) => !prev)} style={{ border: '1px solid rgba(220, 216, 254, 0.376)' }}>
|
<div className={`flex items-center justify-center w-[26px] h-[26px] bg-transparent cursor-pointer hover:ring-offset-1 hover:ring-2 border-mineshaft-500 border bg-mineshaft-900 rounded-[3px] p-2 ${showHexInput ? "tags-conic-bg rounded-full" : ""}`} onClick={() => setShowHexInput((prev) => !prev)} style={{ border: "1px solid rgba(220, 216, 254, 0.376)" }}
|
||||||
{
|
tabIndex={0} role="button"
|
||||||
!showHexInput && <span>#</span>
|
onKeyDown={() => { }}>
|
||||||
}
|
{
|
||||||
</div>
|
!showHexInput && <span>#</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mt-8 flex items-center">
|
<div className="mt-8 flex items-center">
|
||||||
<Button className="mr-4" type="submit" isDisabled={isSubmitting} isLoading={isSubmitting}>
|
<Button className="mr-4" type="submit" isDisabled={isSubmitting} isLoading={isSubmitting}>
|
||||||
Create
|
Create
|
||||||
|
</Button>
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button variant="plain" colorSchema="secondary">
|
||||||
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<ModalClose asChild>
|
</ModalClose>
|
||||||
<Button variant="plain" colorSchema="secondary">
|
</div>
|
||||||
Cancel
|
</form>
|
||||||
</Button>
|
|
||||||
</ModalClose>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
|
||||||
import * as yup from "yup";
|
|
||||||
|
|
||||||
import { Button, FormControl, Input, ModalClose, Tooltip, IconButton, Tag } from "@app/components/v2";
|
|
||||||
import { useToggle } from "@app/hooks";
|
|
||||||
import { TagDesign } from "~/hooks/api/tags/types";
|
|
||||||
|
|
||||||
import {
|
|
||||||
faEye,
|
|
||||||
faEyeSlash
|
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { WsTag } from '../../../../hooks/api/tags/types';
|
|
||||||
|
|
||||||
type TagData = {
|
|
||||||
tagBackground: string;
|
|
||||||
tagLabel: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
onDesignTag: (tagData: TagData) => void;
|
|
||||||
selectedTag: WsTag
|
|
||||||
};
|
|
||||||
|
|
||||||
const designTagSchema = yup.object({
|
|
||||||
tagBackground: yup.string().required().trim().label("Tag Background"),
|
|
||||||
tagLabel: yup.string().required().trim().label("Tag Label"),
|
|
||||||
});
|
|
||||||
type FormData = yup.InferType<typeof designTagSchema>;
|
|
||||||
|
|
||||||
|
|
||||||
export const DesignTagModal = ({ onDesignTag, selectedTag }: Props): JSX.Element => {
|
|
||||||
const [tagDesignObj, setTagDesignObj] = useState({
|
|
||||||
tagColor: {
|
|
||||||
bg: "",
|
|
||||||
text: ""
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const {
|
|
||||||
control,
|
|
||||||
reset,
|
|
||||||
formState,
|
|
||||||
handleSubmit,
|
|
||||||
setValue
|
|
||||||
} = useForm<FormData>({
|
|
||||||
resolver: yupResolver(designTagSchema)
|
|
||||||
});
|
|
||||||
|
|
||||||
const onFormSubmit = ({ tagBackground, tagLabel }: FormData) => {
|
|
||||||
onDesignTag({ tagBackground, tagLabel });
|
|
||||||
reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
const [previewTag, setPreviewTag] = useToggle(false);
|
|
||||||
|
|
||||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>, type: string) => {
|
|
||||||
setTagDesignObj((prev: { tagColor: { bg: string, text: string }; }) => ({
|
|
||||||
tagColor: {
|
|
||||||
...prev.tagColor,
|
|
||||||
[type]: e.target.value
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
if (type === 'bg') {
|
|
||||||
setValue('tagBackground', e.target.value)
|
|
||||||
} else {
|
|
||||||
setValue('tagLabel', e.target.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
|
||||||
<div className="relative">
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="tagBackground"
|
|
||||||
defaultValue=""
|
|
||||||
render={({ field, fieldState: { error } }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FormControl label="Tag Background" isError={Boolean(error)} errorText={error?.message}>
|
|
||||||
<Input {...field} type="color" onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleInputChange(e, 'bg')} />
|
|
||||||
</FormControl>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* <Tooltip content={previewTag ? "Hide Preview" : "Show Preview"}> */}
|
|
||||||
<div >
|
|
||||||
<FontAwesomeIcon icon={previewTag ? faEye : faEyeSlash} onClick={() => setPreviewTag.toggle()} className="absolute top-[2px] left-[127px] cursor-pointer" />
|
|
||||||
{previewTag && (
|
|
||||||
<Tag
|
|
||||||
styles={{
|
|
||||||
backgroundColor: tagDesignObj.tagColor.bg,
|
|
||||||
color: tagDesignObj.tagColor.text
|
|
||||||
}}
|
|
||||||
isDisabled={true}
|
|
||||||
onClose={() => void (0)}
|
|
||||||
key={selectedTag._id}
|
|
||||||
className="absolute top-[-5px] right-[-5px] cursor-pointer"
|
|
||||||
>
|
|
||||||
{selectedTag.slug}
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{/* </Tooltip> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="tagLabel"
|
|
||||||
defaultValue="#000000"
|
|
||||||
render={({ field, fieldState: { error } }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FormControl label="Tag Label" isError={Boolean(error)} errorText={error?.message}>
|
|
||||||
<Input {...field} type="color" onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleInputChange(e, 'text')} value={tagDesignObj.tagColor.text} />
|
|
||||||
</FormControl>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="mt-8 flex items-center">
|
|
||||||
<Button className="mr-4" type="submit" isDisabled={formState.isSubmitting} isLoading={formState.isSubmitting}>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
<ModalClose asChild>
|
|
||||||
<Button variant="plain" colorSchema="secondary">
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</ModalClose>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export {DesignTagModal} from "./DesignTagModal"
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable react/jsx-no-useless-fragment */
|
/* eslint-disable react/jsx-no-useless-fragment */
|
||||||
import { memo, useEffect, useRef, useState } from "react";
|
import { memo, useEffect,useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Control,
|
Control,
|
||||||
Controller,
|
Controller,
|
||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
faCopy,
|
faCopy,
|
||||||
faEllipsis,
|
faEllipsis,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faPlus,
|
|
||||||
faTags,
|
faTags,
|
||||||
faXmark
|
faXmark
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
@@ -24,41 +23,21 @@ import { cx } from "cva";
|
|||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Checkbox,
|
|
||||||
FormControl,
|
|
||||||
HoverCard,
|
HoverCard,
|
||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger,
|
HoverCardTrigger,
|
||||||
IconButton,
|
IconButton,
|
||||||
Input,
|
Input,
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
SecretInput,
|
SecretInput,
|
||||||
Tag,
|
Tag,
|
||||||
TextArea,
|
Tooltip} from "@app/components/v2";
|
||||||
Tooltip,
|
import { useToggle } from "@app/hooks";
|
||||||
Modal,
|
|
||||||
ModalContent,
|
|
||||||
} from "@app/components/v2";
|
|
||||||
|
|
||||||
import { WsTag } from "@app/hooks/api/types";
|
import { WsTag } from "@app/hooks/api/types";
|
||||||
|
|
||||||
|
import AddTagPopoverContent from "../../../../components/AddTagPopoverContent/AddTagPopoverContent";
|
||||||
import { FormData, SecretActionType } from "../../DashboardPage.utils";
|
import { FormData, SecretActionType } from "../../DashboardPage.utils";
|
||||||
import { SecretTags } from "~/hooks/api/tags/types";
|
|
||||||
import { useToggle } from "@app/hooks";
|
|
||||||
|
|
||||||
const tagColors = [
|
|
||||||
{ bg: "bg-[#f1c40f]/40", text: "text-[#fcf0c3]/70" },
|
|
||||||
{ bg: "bg-[#cb1c8d]/40", text: "text-[#f2c6e3]/70" },
|
|
||||||
{ bg: "bg-[#badc58]/40", text: "text-[#eef6d5]/70" },
|
|
||||||
{ bg: "bg-[#ff5400]/40", text: "text-[#ffddcc]/70" },
|
|
||||||
{ bg: "bg-[#3AB0FF]/40", text: "text-[#f0fffd]/70" },
|
|
||||||
{ bg: "bg-[#6F1AB6]/40", text: "text-[#FFE5F1]/70" },
|
|
||||||
{ bg: "bg-[#C40B13]/40", text: "text-[#FFDEDE]/70" },
|
|
||||||
{ bg: "bg-[#332FD0]/40", text: "text-[#DFF6FF]/70" }
|
|
||||||
];
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
index: number;
|
index: number;
|
||||||
@@ -77,7 +56,6 @@ type Props = {
|
|||||||
// tag props
|
// tag props
|
||||||
wsTags?: WsTag[];
|
wsTags?: WsTag[];
|
||||||
onCreateTagOpen: () => void;
|
onCreateTagOpen: () => void;
|
||||||
onDesignTagOpen: (selectedTag: WsTag, selectedFieldIndex: number) => void;
|
|
||||||
// rhf specific functions, dont put this using useFormContext. This is passed as props to avoid re-rendering
|
// rhf specific functions, dont put this using useFormContext. This is passed as props to avoid re-rendering
|
||||||
control: Control<FormData>;
|
control: Control<FormData>;
|
||||||
register: UseFormRegister<FormData>;
|
register: UseFormRegister<FormData>;
|
||||||
@@ -97,11 +75,10 @@ export const SecretInputRow = memo(
|
|||||||
isAddOnly,
|
isAddOnly,
|
||||||
wsTags,
|
wsTags,
|
||||||
onCreateTagOpen,
|
onCreateTagOpen,
|
||||||
onDesignTagOpen,
|
|
||||||
onSecretDelete,
|
onSecretDelete,
|
||||||
searchTerm,
|
searchTerm,
|
||||||
control,
|
control,
|
||||||
register,
|
// register,
|
||||||
setValue,
|
setValue,
|
||||||
isKeyError,
|
isKeyError,
|
||||||
keyError,
|
keyError,
|
||||||
@@ -116,8 +93,6 @@ export const SecretInputRow = memo(
|
|||||||
append
|
append
|
||||||
} = useFieldArray({ control, name: `secrets.${index}.tags` });
|
} = useFieldArray({ control, name: `secrets.${index}.tags` });
|
||||||
|
|
||||||
const tagColorByTagId = new Map((wsTags || []).map((wsTag, i) => [wsTag._id, tagColors[i % tagColors.length]]))
|
|
||||||
|
|
||||||
// display the tags in alphabetical order
|
// display the tags in alphabetical order
|
||||||
secretTags.sort((a, b) => a?.name?.localeCompare(b?.name))
|
secretTags.sort((a, b) => a?.name?.localeCompare(b?.name))
|
||||||
|
|
||||||
@@ -152,7 +127,19 @@ export const SecretInputRow = memo(
|
|||||||
const isOverridden =
|
const isOverridden =
|
||||||
overrideAction === SecretActionType.Created || overrideAction === SecretActionType.Modified;
|
overrideAction === SecretActionType.Created || overrideAction === SecretActionType.Modified;
|
||||||
|
|
||||||
|
|
||||||
const [editorRef, setEditorRef] = useState(isOverridden ? secValueOverride : secValue);
|
const [editorRef, setEditorRef] = useState(isOverridden ? secValueOverride : secValue);
|
||||||
|
const [hoveredTag, setHoveredTag] = useState<WsTag | null>(null);
|
||||||
|
|
||||||
|
const handleTagOnMouseEnter = (wsTag: WsTag) => {
|
||||||
|
setHoveredTag(wsTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleTagOnMouseLeave = () => {
|
||||||
|
setHoveredTag(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkIfTagIsVisible = (wsTag: WsTag) => wsTag._id === hoveredTag?._id;
|
||||||
|
|
||||||
const secId = useWatch({ control, name: `secrets.${index}._id`, exact: true });
|
const secId = useWatch({ control, name: `secrets.${index}._id`, exact: true });
|
||||||
const tags = useWatch({ control, name: `secrets.${index}.tags`, exact: true, defaultValue: [] }) || [];
|
const tags = useWatch({ control, name: `secrets.${index}.tags`, exact: true, defaultValue: [] }) || [];
|
||||||
@@ -164,6 +151,7 @@ export const SecretInputRow = memo(
|
|||||||
|
|
||||||
const [isInviteLinkCopied, setInviteLinkCopied] = useToggle(false);
|
const [isInviteLinkCopied, setInviteLinkCopied] = useToggle(false);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let timer: NodeJS.Timeout;
|
let timer: NodeJS.Timeout;
|
||||||
if (isInviteLinkCopied) {
|
if (isInviteLinkCopied) {
|
||||||
@@ -172,6 +160,7 @@ export const SecretInputRow = memo(
|
|||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, [isInviteLinkCopied]);
|
}, [isInviteLinkCopied]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setEditorRef(isOverridden ? secValueOverride : secValue);
|
setEditorRef(isOverridden ? secValueOverride : secValue);
|
||||||
}, [isOverridden]);
|
}, [isOverridden]);
|
||||||
@@ -202,7 +191,8 @@ export const SecretInputRow = memo(
|
|||||||
const onSelectTag = (selectedTag: WsTag) => {
|
const onSelectTag = (selectedTag: WsTag) => {
|
||||||
const shouldAppend = !selectedTagIds[selectedTag.slug];
|
const shouldAppend = !selectedTagIds[selectedTag.slug];
|
||||||
if (shouldAppend) {
|
if (shouldAppend) {
|
||||||
append(selectedTag);
|
const {_id: id, name, slug, tagColor} = selectedTag
|
||||||
|
append({_id: id, name, slug, tagColor});
|
||||||
} else {
|
} else {
|
||||||
const pos = tags.findIndex(({ slug }: { slug: string }) => selectedTag.slug === slug);
|
const pos = tags.findIndex(({ slug }: { slug: string }) => selectedTag.slug === slug);
|
||||||
remove(pos);
|
remove(pos);
|
||||||
@@ -229,8 +219,6 @@ export const SecretInputRow = memo(
|
|||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="group flex flex-row hover:bg-mineshaft-700" key={index}>
|
<tr className="group flex flex-row hover:bg-mineshaft-700" key={index}>
|
||||||
<td className="flex h-10 w-10 items-center justify-center border-none px-4">
|
<td className="flex h-10 w-10 items-center justify-center border-none px-4">
|
||||||
@@ -335,67 +323,37 @@ export const SecretInputRow = memo(
|
|||||||
</td>
|
</td>
|
||||||
<td className="min-w-sm flex">
|
<td className="min-w-sm flex">
|
||||||
<div className="flex h-8 items-center pl-2">
|
<div className="flex h-8 items-center pl-2">
|
||||||
{secretTags.map(({ id, _id, slug, tagColor }: SecretTags, i: number) => {
|
{secretTags.map(({ id, slug, tagColor}) => {
|
||||||
return (
|
return (
|
||||||
<Popover>
|
<>
|
||||||
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<div>
|
<div>
|
||||||
<Tag
|
<Tag
|
||||||
isDisabled={isReadOnly || isAddOnly || isRollbackMode}
|
// isDisabled={isReadOnly || isAddOnly || isRollbackMode}
|
||||||
onClose={() => remove(i)}
|
// onClose={() => remove(i)}
|
||||||
key={id}
|
key={id}
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
>
|
>
|
||||||
<div className="rounded-md rounded-full border-mineshaft-500 bg-transparent flex items-center gap-1.5 justify-around">
|
<div className="rounded-full border-mineshaft-500 bg-transparent flex items-center gap-1.5 justify-around">
|
||||||
<div className="w-[10px] h-[10px] rounded-full" style={{ background: tagColor ? tagColor : "#bec2c8" }}></div>
|
<div className="w-[10px] h-[10px] rounded-full" style={{ background: tagColor || "#bec2c8" }} />
|
||||||
{slug}
|
{slug}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<AddTagPopoverContent
|
||||||
side="left"
|
wsTags={wsTags}
|
||||||
className="max-h-96 w-auto min-w-[200px] p-2 overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 text-bunker-200"
|
secKey={secKey || "this secret"}
|
||||||
hideCloseBtn
|
selectedTagIds={selectedTagIds}
|
||||||
>
|
handleSelectTag={(wsTag: WsTag) => onSelectTag(wsTag)}
|
||||||
<div className=" text-center text-sm font-medium text-bunker-200">
|
handleTagOnMouseEnter={(wsTag: WsTag) => handleTagOnMouseEnter(wsTag)}
|
||||||
Add tags to {secKey || "this secret"}
|
handleTagOnMouseLeave={() => handleTagOnMouseLeave()}
|
||||||
</div>
|
checkIfTagIsVisible={(wsTag: WsTag) => checkIfTagIsVisible(wsTag)}
|
||||||
<div className="flex flex-col space-y-2.5">
|
handleOnCreateTagOpen={() => onCreateTagOpen()}
|
||||||
{wsTags?.map((wsTag) => (
|
/>
|
||||||
<Button
|
|
||||||
variant="star"
|
|
||||||
size="md"
|
|
||||||
className={`mt-4 justify-start px-1 hover:bg-mineshaft-600 hover:border-mineshaft-500 hover:text-bunker-200 ${selectedTagIds?.[wsTag.slug] && "text-primary hover:text-primary"}`}
|
|
||||||
onClick={() => onSelectTag(wsTag)}
|
|
||||||
leftIcon={
|
|
||||||
<Checkbox
|
|
||||||
className="mr-0 data-[state=checked]:bg-primary border-mineshaft-500 border"
|
|
||||||
id="autoCapitalization"
|
|
||||||
isChecked={selectedTagIds?.[wsTag.slug]}
|
|
||||||
>
|
|
||||||
{ }
|
|
||||||
</Checkbox>
|
|
||||||
}
|
|
||||||
key={wsTag._id}
|
|
||||||
>
|
|
||||||
{wsTag.slug}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
<Button
|
|
||||||
variant="star"
|
|
||||||
size="md"
|
|
||||||
className="mt-4 justify-start px-1 hover:bg-mineshaft-600 hover:border-mineshaft-500 hover:text-bunker-200"
|
|
||||||
onClick={onCreateTagOpen}
|
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
|
||||||
>
|
|
||||||
Add new tag
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<div className="w-0 overflow-hidden group-hover:w-6">
|
<div className="w-0 overflow-hidden group-hover:w-6">
|
||||||
@@ -428,46 +386,16 @@ export const SecretInputRow = memo(
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<AddTagPopoverContent
|
||||||
side="left"
|
wsTags={wsTags}
|
||||||
className="max-h-96 w-auto min-w-[200px] p-2 overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 text-bunker-200"
|
secKey={secKey || "this secret"}
|
||||||
hideCloseBtn
|
selectedTagIds={selectedTagIds}
|
||||||
>
|
handleSelectTag={(wsTag: WsTag) => onSelectTag(wsTag)}
|
||||||
<div className=" text-center text-sm font-medium text-bunker-200">
|
handleTagOnMouseEnter={(wsTag: WsTag) => handleTagOnMouseEnter(wsTag)}
|
||||||
Add tags to {secKey || "this secret"}
|
handleTagOnMouseLeave={() => handleTagOnMouseLeave()}
|
||||||
</div>
|
checkIfTagIsVisible={(wsTag: WsTag) => checkIfTagIsVisible(wsTag)}
|
||||||
<div className="flex flex-col space-y-2.5">
|
handleOnCreateTagOpen={() => onCreateTagOpen()}
|
||||||
{wsTags?.map((wsTag) => (
|
/>
|
||||||
<Button
|
|
||||||
variant="star"
|
|
||||||
size="md"
|
|
||||||
className={`mt-4 justify-start px-1 hover:bg-mineshaft-600 hover:border-mineshaft-500 hover:text-bunker-200 ${selectedTagIds?.[wsTag.slug] && "text-primary hover:text-primary"}`}
|
|
||||||
onClick={() => onSelectTag(wsTag)}
|
|
||||||
leftIcon={
|
|
||||||
<Checkbox
|
|
||||||
className="mr-0 data-[state=checked]:bg-primary border-mineshaft-500"
|
|
||||||
id="autoCapitalization"
|
|
||||||
isChecked={selectedTagIds?.[wsTag.slug]}
|
|
||||||
>
|
|
||||||
{ }
|
|
||||||
</Checkbox>
|
|
||||||
}
|
|
||||||
key={wsTag._id}
|
|
||||||
>
|
|
||||||
{wsTag.slug}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
<Button
|
|
||||||
variant="star"
|
|
||||||
size="md"
|
|
||||||
className="mt-4 justify-start px-1 hover:bg-mineshaft-600 hover:border-mineshaft-500 hover:text-bunker-200"
|
|
||||||
onClick={onCreateTagOpen}
|
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
|
||||||
>
|
|
||||||
Add new tag
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -511,20 +439,16 @@ export const SecretInputRow = memo(
|
|||||||
<FontAwesomeIcon icon={faComment} />
|
<FontAwesomeIcon icon={faComment} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<AddTagPopoverContent
|
||||||
className="w-auto border border-mineshaft-600 bg-mineshaft-800 p-2 drop-shadow-2xl"
|
wsTags={wsTags}
|
||||||
sticky="always"
|
secKey={secKey || "this secret"}
|
||||||
>
|
selectedTagIds={selectedTagIds}
|
||||||
<FormControl label="Comment" className="mb-0">
|
handleSelectTag={(wsTag: WsTag) => onSelectTag(wsTag)}
|
||||||
<TextArea
|
handleTagOnMouseEnter={(wsTag: WsTag) => handleTagOnMouseEnter(wsTag)}
|
||||||
isDisabled={isReadOnly || isRollbackMode || shouldBeBlockedInAddOnly}
|
handleTagOnMouseLeave={() => handleTagOnMouseLeave()}
|
||||||
className="border border-mineshaft-600 text-sm"
|
checkIfTagIsVisible={(wsTag: WsTag) => checkIfTagIsVisible(wsTag)}
|
||||||
{...register(`secrets.${index}.comment`)}
|
handleOnCreateTagOpen={() => onCreateTagOpen()}
|
||||||
rows={8}
|
/>
|
||||||
cols={30}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
Reference in New Issue
Block a user