mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 07:28:21 +00:00
wip
This commit is contained in:
@@ -20,7 +20,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
identitiesUsed: 0,
|
identitiesUsed: 0,
|
||||||
dynamicSecret: false,
|
dynamicSecret: false,
|
||||||
secretVersioning: true,
|
secretVersioning: true,
|
||||||
pitRecovery: false,
|
pitRecovery: true,
|
||||||
ipAllowlisting: false,
|
ipAllowlisting: false,
|
||||||
rbac: false,
|
rbac: false,
|
||||||
githubOrgSync: false,
|
githubOrgSync: false,
|
||||||
@@ -40,7 +40,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
status: null,
|
status: null,
|
||||||
trial_end: null,
|
trial_end: null,
|
||||||
has_used_trial: true,
|
has_used_trial: true,
|
||||||
secretApproval: false,
|
secretApproval: true,
|
||||||
secretRotation: false,
|
secretRotation: false,
|
||||||
caCrl: false,
|
caCrl: false,
|
||||||
instanceUserManagement: false,
|
instanceUserManagement: false,
|
||||||
|
|||||||
+2
-2
@@ -156,11 +156,11 @@ export const SecretApprovalRequestChangeItem = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<div className="text-sm font-medium text-mineshaft-300">Tags</div>
|
<div className="text-sm font-medium text-mineshaft-300">Tags</div>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-y-2">
|
||||||
{(secretVersion?.tags?.length ?? 0) ? (
|
{(secretVersion?.tags?.length ?? 0) ? (
|
||||||
secretVersion?.tags?.map(({ slug, id: tagId, color }) => (
|
secretVersion?.tags?.map(({ slug, id: tagId, color }) => (
|
||||||
<Tag
|
<Tag
|
||||||
className="flex w-min items-center space-x-2"
|
className="flex w-min items-center space-x-1.5 border border-mineshaft-500 bg-mineshaft-800"
|
||||||
key={`${secretVersion.id}-${tagId}`}
|
key={`${secretVersion.id}-${tagId}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ const createBatchModeStore: StateCreator<CombinedState, [], [], BatchModeState>
|
|||||||
|
|
||||||
if (change.type === PendingAction.Create && existingFolder) {
|
if (change.type === PendingAction.Create && existingFolder) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Another folder with same name already exists",
|
text: "A folder with this name already exists",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
return { pendingChanges: newChanges };
|
return { pendingChanges: newChanges };
|
||||||
@@ -302,7 +302,7 @@ const createBatchModeStore: StateCreator<CombinedState, [], [], BatchModeState>
|
|||||||
existingFolder
|
existingFolder
|
||||||
) {
|
) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Another folder with same name already exists",
|
text: "A folder with this name already exists",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
return { pendingChanges: newChanges };
|
return { pendingChanges: newChanges };
|
||||||
@@ -322,7 +322,7 @@ const createBatchModeStore: StateCreator<CombinedState, [], [], BatchModeState>
|
|||||||
|
|
||||||
if (change.type === PendingAction.Create && existingSecret) {
|
if (change.type === PendingAction.Create && existingSecret) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Another secret with same name already exists",
|
text: "A secret with this name already exists",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
return { pendingChanges: newChanges };
|
return { pendingChanges: newChanges };
|
||||||
@@ -343,7 +343,7 @@ const createBatchModeStore: StateCreator<CombinedState, [], [], BatchModeState>
|
|||||||
|
|
||||||
if (existingNewSecretName) {
|
if (existingNewSecretName) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Another secret with same name already exists",
|
text: "A secret with this name already exists",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
return { pendingChanges: newChanges };
|
return { pendingChanges: newChanges };
|
||||||
|
|||||||
+206
-151
@@ -1,9 +1,19 @@
|
|||||||
/* eslint-disable jsx-a11y/label-has-associated-control */
|
/* eslint-disable jsx-a11y/label-has-associated-control */
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { faCodeCommit, faEye, faFolder, faKey, faTrash } from "@fortawesome/free-solid-svg-icons";
|
import {
|
||||||
|
faChevronDown,
|
||||||
|
faChevronRight,
|
||||||
|
faCodeCommit,
|
||||||
|
faEye,
|
||||||
|
faFolder,
|
||||||
|
faKey,
|
||||||
|
faTrash
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import { Badge, Button, IconButton, Input, Modal, ModalContent, Tooltip } from "@app/components/v2";
|
import { Badge, Button, IconButton, Input, Modal, ModalContent, Tooltip } from "@app/components/v2";
|
||||||
|
import { useToggle } from "@app/hooks";
|
||||||
import { PendingAction } from "@app/hooks/api/secretFolders/types";
|
import { PendingAction } from "@app/hooks/api/secretFolders/types";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -39,7 +49,7 @@ const TagsList: React.FC<{ tags?: { id: string; slug: string }[]; className?: st
|
|||||||
return (
|
return (
|
||||||
<div className={`flex flex-wrap gap-1 ${className}`}>
|
<div className={`flex flex-wrap gap-1 ${className}`}>
|
||||||
{tags.map((tag) => (
|
{tags.map((tag) => (
|
||||||
<Badge key={tag.id} variant="primary" className="text-xs">
|
<Badge key={tag.id} variant="success" className="text-xs">
|
||||||
{tag.slug}
|
{tag.slug}
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
@@ -79,12 +89,14 @@ const ComparisonTableRow: React.FC<{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="border-b border-mineshaft-700 last:border-b-0">
|
<tr className="border-b border-mineshaft-700 last:border-b-0">
|
||||||
<td className="w-24 py-3 pl-4 align-top font-medium text-mineshaft-300">{label}:</td>
|
<td className="w-[12%] border-r border-mineshaft-600 px-4 py-3 align-top font-medium text-mineshaft-300">
|
||||||
<td className="w-1/2 px-3 py-3 align-top">
|
{label}
|
||||||
|
</td>
|
||||||
|
<td className="w-1/2 border-r border-mineshaft-600 px-4 py-3 align-top">
|
||||||
<div className="text-red-400 opacity-80">{previousValue}</div>
|
<div className="text-red-400 opacity-80">{previousValue}</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="w-1/2 py-3 pr-4 align-top">
|
<td className="w-1/2 py-3 pr-4 align-top">
|
||||||
<div className="text-green-400">{newValue}</div>
|
<div className="px-4 text-green-400">{newValue}</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
@@ -96,6 +108,8 @@ const ChangeTable: React.FC<ChangeTableProps> = ({
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
secretPath
|
secretPath
|
||||||
}) => {
|
}) => {
|
||||||
|
const [isOpen, setIsOpen] = useToggle(true);
|
||||||
|
|
||||||
const getChangeBadge = (type: PendingChange["type"]) => {
|
const getChangeBadge = (type: PendingChange["type"]) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PendingAction.Create:
|
case PendingAction.Create:
|
||||||
@@ -114,7 +128,7 @@ const ChangeTable: React.FC<ChangeTableProps> = ({
|
|||||||
|
|
||||||
if (change.type === PendingAction.Create) {
|
if (change.type === PendingAction.Create) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 overflow-hidden rounded-md border border-mineshaft-700 bg-mineshaft-900">
|
<div className="overflow-hidden rounded-md bg-mineshaft-900/80">
|
||||||
<table className="w-full text-sm">
|
<table className="w-full text-sm">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr className="border-b border-mineshaft-700">
|
<tr className="border-b border-mineshaft-700">
|
||||||
@@ -185,83 +199,85 @@ const ChangeTable: React.FC<ChangeTableProps> = ({
|
|||||||
if (!hasChanges) return null;
|
if (!hasChanges) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 overflow-hidden rounded-md border border-mineshaft-700 bg-mineshaft-900">
|
<table className="w-full text-sm">
|
||||||
<table className="w-full text-sm">
|
<tbody>
|
||||||
<tbody>
|
{hasKeyChange && (
|
||||||
{hasKeyChange && (
|
<ComparisonTableRow
|
||||||
<ComparisonTableRow
|
label="Key"
|
||||||
label="Key"
|
previousValue={<span className="font-mono">{change.existingSecret.key}</span>}
|
||||||
previousValue={<span className="font-mono">{change.existingSecret.key}</span>}
|
newValue={<span className="font-mono">{change.newSecretName}</span>}
|
||||||
newValue={<span className="font-mono">{change.newSecretName}</span>}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
{hasValueChange && (
|
||||||
{hasValueChange && (
|
<ComparisonTableRow
|
||||||
<ComparisonTableRow
|
label="Value"
|
||||||
label="Value"
|
previousValue={
|
||||||
previousValue={
|
<div className="max-w-md break-all rounded">
|
||||||
<div className="max-w-md break-all rounded">
|
{change.existingSecret.value || (
|
||||||
{change.existingSecret.value || <span className="italic">(empty)</span>}
|
<span className="italic text-mineshaft-400">(empty)</span>
|
||||||
</div>
|
)}
|
||||||
}
|
</div>
|
||||||
newValue={
|
}
|
||||||
<div className="max-w-md break-all rounded">
|
newValue={
|
||||||
{change.secretValue || <span className="italic">(empty)</span>}
|
<div className="max-w-md break-all rounded">
|
||||||
</div>
|
{change.secretValue || (
|
||||||
}
|
<span className="italic text-mineshaft-400">(empty)</span>
|
||||||
/>
|
)}
|
||||||
)}
|
</div>
|
||||||
{hasCommentChange && (
|
}
|
||||||
<ComparisonTableRow
|
/>
|
||||||
label="Comment"
|
)}
|
||||||
previousValue={
|
{hasCommentChange && (
|
||||||
change.existingSecret.comment || <span className="italic">(empty)</span>
|
<ComparisonTableRow
|
||||||
}
|
label="Comment"
|
||||||
newValue={change.secretComment || <span className="italic">(empty)</span>}
|
previousValue={
|
||||||
/>
|
change.existingSecret.comment || (
|
||||||
)}
|
<span className="italic text-mineshaft-400">(empty)</span>
|
||||||
{hasMultilineChange && (
|
)
|
||||||
<ComparisonTableRow
|
}
|
||||||
label="Multi-line Encoding"
|
newValue={
|
||||||
previousValue={
|
change.secretComment || <span className="italic text-mineshaft-400">(empty)</span>
|
||||||
change.existingSecret.skipMultilineEncoding ? "Enabled" : "Disabled"
|
}
|
||||||
}
|
/>
|
||||||
newValue={change.skipMultilineEncoding ? "Enabled" : "Disabled"}
|
)}
|
||||||
/>
|
{hasMultilineChange && (
|
||||||
)}
|
<ComparisonTableRow
|
||||||
{hasTagsChange && (
|
label="Multi-line Encoding"
|
||||||
<ComparisonTableRow
|
previousValue={change.existingSecret.skipMultilineEncoding ? "Enabled" : "Disabled"}
|
||||||
label="Tags"
|
newValue={change.skipMultilineEncoding ? "Enabled" : "Disabled"}
|
||||||
previousValue={<TagsList tags={change.existingSecret.tags} />}
|
/>
|
||||||
newValue={<TagsList tags={change.tags} />}
|
)}
|
||||||
/>
|
{hasTagsChange && (
|
||||||
)}
|
<ComparisonTableRow
|
||||||
{hasMetadataChange && (
|
label="Tags"
|
||||||
<ComparisonTableRow
|
previousValue={<TagsList tags={change.existingSecret.tags} />}
|
||||||
label="Metadata"
|
newValue={<TagsList tags={change.tags} />}
|
||||||
previousValue={<MetadataList metadata={change.existingSecret.secretMetadata} />}
|
/>
|
||||||
newValue={<MetadataList metadata={change.secretMetadata} />}
|
)}
|
||||||
/>
|
{hasMetadataChange && (
|
||||||
)}
|
<ComparisonTableRow
|
||||||
</tbody>
|
label="Metadata"
|
||||||
</table>
|
previousValue={<MetadataList metadata={change.existingSecret.secretMetadata} />}
|
||||||
</div>
|
newValue={<MetadataList metadata={change.secretMetadata} />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.type === PendingAction.Delete) {
|
if (change.type === PendingAction.Delete) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 overflow-hidden rounded-md border border-mineshaft-700 bg-mineshaft-900">
|
<table className="w-full text-sm">
|
||||||
<table className="w-full text-sm">
|
<tbody>
|
||||||
<tbody>
|
<tr className="border-b border-mineshaft-700">
|
||||||
<tr className="border-b border-mineshaft-700">
|
<td className="w-24 py-3 pl-4 font-medium text-red-400">Key:</td>
|
||||||
<td className="w-24 py-3 pl-4 font-medium text-red-400">Key:</td>
|
<td className="px-3 py-3 font-mono text-red-400 line-through" colSpan={2}>
|
||||||
<td className="px-3 py-3 font-mono text-red-400 line-through" colSpan={2}>
|
{change.secretKey}
|
||||||
{change.secretKey}
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,26 +289,24 @@ const ChangeTable: React.FC<ChangeTableProps> = ({
|
|||||||
|
|
||||||
if (change.type === PendingAction.Create) {
|
if (change.type === PendingAction.Create) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 overflow-hidden rounded-md border border-mineshaft-700 bg-mineshaft-900">
|
<table className="w-full text-sm">
|
||||||
<table className="w-full text-sm">
|
<tbody>
|
||||||
<tbody>
|
<tr className="border-b border-mineshaft-700">
|
||||||
<tr className="border-b border-mineshaft-700">
|
<td className="w-24 py-3 pl-4 font-medium text-mineshaft-300">Name:</td>
|
||||||
<td className="w-24 py-3 pl-4 font-medium text-mineshaft-300">Name:</td>
|
<td className="px-3 py-3 font-mono text-mineshaft-100" colSpan={2}>
|
||||||
<td className="px-3 py-3 font-mono text-mineshaft-100" colSpan={2}>
|
{change.folderName}
|
||||||
{change.folderName}
|
</td>
|
||||||
|
</tr>
|
||||||
|
{change.description !== undefined && change.description !== "" && (
|
||||||
|
<tr className="border-b border-mineshaft-700 last:border-b-0">
|
||||||
|
<td className="w-24 py-3 pl-4 font-medium text-mineshaft-300">Description:</td>
|
||||||
|
<td className="px-3 py-3 text-mineshaft-100" colSpan={2}>
|
||||||
|
{change.description}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{change.description !== undefined && change.description !== "" && (
|
)}
|
||||||
<tr className="border-b border-mineshaft-700 last:border-b-0">
|
</tbody>
|
||||||
<td className="w-24 py-3 pl-4 font-medium text-mineshaft-300">Description:</td>
|
</table>
|
||||||
<td className="px-3 py-3 text-mineshaft-100" colSpan={2}>
|
|
||||||
{change.description}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,45 +319,41 @@ const ChangeTable: React.FC<ChangeTableProps> = ({
|
|||||||
if (!hasChanges) return null;
|
if (!hasChanges) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 overflow-hidden rounded-md border border-mineshaft-700 bg-mineshaft-900">
|
<table className="w-full text-sm">
|
||||||
<table className="w-full text-sm">
|
<tbody>
|
||||||
<tbody>
|
{hasNameChange && (
|
||||||
{hasNameChange && (
|
<ComparisonTableRow
|
||||||
<ComparisonTableRow
|
label="Name"
|
||||||
label="Name"
|
previousValue={<span className="font-mono">{change.originalFolderName}</span>}
|
||||||
previousValue={<span className="font-mono">{change.originalFolderName}</span>}
|
newValue={<span className="font-mono">{change.folderName}</span>}
|
||||||
newValue={<span className="font-mono">{change.folderName}</span>}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
{hasDescriptionChange && (
|
||||||
{hasDescriptionChange && (
|
<ComparisonTableRow
|
||||||
<ComparisonTableRow
|
label="Description"
|
||||||
label="Description"
|
previousValue={
|
||||||
previousValue={
|
change.originalDescription || <span className="italic">(empty)</span>
|
||||||
change.originalDescription || <span className="italic">(empty)</span>
|
}
|
||||||
}
|
newValue={change.description || <span className="italic">(empty)</span>}
|
||||||
newValue={change.description || <span className="italic">(empty)</span>}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.type === PendingAction.Delete) {
|
if (change.type === PendingAction.Delete) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 overflow-hidden rounded-md border border-mineshaft-700 bg-mineshaft-900">
|
<table className="w-full text-sm">
|
||||||
<table className="w-full text-sm">
|
<tbody>
|
||||||
<tbody>
|
<tr className="border-b border-mineshaft-700">
|
||||||
<tr className="border-b border-mineshaft-700">
|
<td className="w-24 py-3 pl-4 font-medium text-red-400">Name:</td>
|
||||||
<td className="w-24 py-3 pl-4 font-medium text-red-400">Name:</td>
|
<td className="px-3 py-3 font-mono text-red-400 line-through" colSpan={2}>
|
||||||
<td className="px-3 py-3 font-mono text-red-400 line-through" colSpan={2}>
|
{change.folderName}
|
||||||
{change.folderName}
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +382,49 @@ const ChangeTable: React.FC<ChangeTableProps> = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="overflow-clip rounded-t-none border border-t-0 border-mineshaft-600 bg-mineshaft-800 first:rounded-t-md first:border-t last:rounded-b-md last:border-b">
|
||||||
|
<div
|
||||||
|
className={twMerge(
|
||||||
|
"flex h-12 cursor-pointer items-center border-mineshaft-600 px-3.5 py-2 text-sm text-gray-300",
|
||||||
|
isOpen && "border-b"
|
||||||
|
)}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => setIsOpen.toggle()}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
setIsOpen.toggle();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon className="mr-3 w-4" icon={isOpen ? faChevronDown : faChevronRight} />
|
||||||
|
|
||||||
|
<div className="flex flex-1 items-center gap-1.5 text-sm">
|
||||||
|
{getChangeName()}
|
||||||
|
{getChangeBadge(change.type)}
|
||||||
|
</div>
|
||||||
|
<Tooltip content="Discard change">
|
||||||
|
<IconButton
|
||||||
|
ariaLabel="delete-change"
|
||||||
|
variant="plain"
|
||||||
|
colorSchema="danger"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleDeletePending(change.resourceType, change.id)}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faTrash} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isOpen ? (
|
||||||
|
<div className="overflow-hidden bg-mineshaft-900">
|
||||||
|
{change.resourceType === "secret" ? renderSecretChanges() : renderFolderChanges()}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="py-2 shadow-sm">
|
<div className="py-2 shadow-sm">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@@ -432,32 +485,35 @@ export const CommitForm: React.FC<CommitFormProps> = ({
|
|||||||
{/* Floating Panel */}
|
{/* Floating Panel */}
|
||||||
{!isModalOpen && (
|
{!isModalOpen && (
|
||||||
<div className="fixed bottom-4 z-40 w-64 self-center rounded-lg border border-mineshaft-600 bg-mineshaft-800 shadow-2xl">
|
<div className="fixed bottom-4 z-40 w-64 self-center rounded-lg border border-mineshaft-600 bg-mineshaft-800 shadow-2xl">
|
||||||
<div className="flex w-full justify-center border-b border-mineshaft-600 px-4 py-3">
|
<div className="flex w-full justify-center border-b border-mineshaft-600 p-2">
|
||||||
<div className="flex w-full items-center justify-between">
|
<div className="flex w-full items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<FontAwesomeIcon icon={faCodeCommit} className="text-primary" />
|
<FontAwesomeIcon icon={faCodeCommit} className="text-mineshaft-400" />
|
||||||
<span className="font-medium text-mineshaft-100">Ready to Commit</span>
|
<span className="font-medium text-mineshaft-100">Pending Changes</span>
|
||||||
</div>
|
</div>
|
||||||
<Badge variant="primary" className="text-xs">
|
<Badge variant="primary" className="text-xs">
|
||||||
{totalChangesCount} change{totalChangesCount !== 1 ? "s" : ""}
|
{totalChangesCount} Change{totalChangesCount !== 1 ? "s" : ""}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center gap-4 p-3">
|
<div className="flex justify-center gap-2 p-2">
|
||||||
<Button
|
<Button
|
||||||
|
size="sm"
|
||||||
leftIcon={<FontAwesomeIcon icon={faTrash} />}
|
leftIcon={<FontAwesomeIcon icon={faTrash} />}
|
||||||
onClick={() => clearAllPendingChanges({ workspaceId, environment, secretPath })}
|
onClick={() => clearAllPendingChanges({ workspaceId, environment, secretPath })}
|
||||||
isDisabled={totalChangesCount === 0}
|
isDisabled={totalChangesCount === 0}
|
||||||
colorSchema="secondary"
|
variant="outline_bg"
|
||||||
|
className="h-8 flex-1 hover:border-red/40 hover:bg-red/[0.1]"
|
||||||
>
|
>
|
||||||
Discard
|
Discard
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
variant="outline_bg"
|
||||||
leftIcon={<FontAwesomeIcon icon={faEye} />}
|
leftIcon={<FontAwesomeIcon icon={faEye} />}
|
||||||
onClick={() => setIsModalOpen(true)}
|
onClick={() => setIsModalOpen(true)}
|
||||||
isDisabled={totalChangesCount === 0}
|
isDisabled={totalChangesCount === 0}
|
||||||
colorSchema="secondary"
|
className="h-8 flex-1"
|
||||||
>
|
>
|
||||||
Review
|
Review
|
||||||
</Button>
|
</Button>
|
||||||
@@ -470,23 +526,20 @@ export const CommitForm: React.FC<CommitFormProps> = ({
|
|||||||
<ModalContent
|
<ModalContent
|
||||||
title={
|
title={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<FontAwesomeIcon icon={faCodeCommit} className="text-primary" />
|
<FontAwesomeIcon icon={faCodeCommit} className="text-mineshaft-400" />
|
||||||
Commit Changes
|
Commit Changes
|
||||||
<Badge variant="primary" className="ml-2">
|
<Badge variant="primary" className="mt-[0.05rem]">
|
||||||
{totalChangesCount} change{totalChangesCount !== 1 ? "s" : ""}
|
{totalChangesCount} Change{totalChangesCount !== 1 ? "s" : ""}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
subTitle={"Write a commit message and review the changes you're about to commit."}
|
||||||
className="max-h-[90vh] max-w-5xl"
|
className="max-h-[90vh] max-w-5xl"
|
||||||
>
|
>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<p className="text-mineshaft-300">
|
|
||||||
Write a commit message and review the changes you're about to commit.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Changes List */}
|
{/* Changes List */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="max-h-96 space-y-4 overflow-y-auto pr-2">
|
<div className="max-h-[50vh] space-y-4 overflow-y-auto rounded-md border border-mineshaft-600 bg-bunker-800 p-4 shadow-inner">
|
||||||
{/* Folder Changes */}
|
{/* Folder Changes */}
|
||||||
{pendingChanges.folders.length > 0 && (
|
{pendingChanges.folders.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
@@ -494,7 +547,7 @@ export const CommitForm: React.FC<CommitFormProps> = ({
|
|||||||
<FontAwesomeIcon icon={faFolder} className="text-mineshaft-300" />
|
<FontAwesomeIcon icon={faFolder} className="text-mineshaft-300" />
|
||||||
Folders ({pendingChanges.folders.length})
|
Folders ({pendingChanges.folders.length})
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-3">
|
<div>
|
||||||
{pendingChanges.folders.map((change) => (
|
{pendingChanges.folders.map((change) => (
|
||||||
<ChangeTable
|
<ChangeTable
|
||||||
key={change.id}
|
key={change.id}
|
||||||
@@ -511,11 +564,11 @@ export const CommitForm: React.FC<CommitFormProps> = ({
|
|||||||
{/* Secret Changes */}
|
{/* Secret Changes */}
|
||||||
{pendingChanges.secrets.length > 0 && (
|
{pendingChanges.secrets.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<h4 className="mb-4 flex items-center gap-2 border-b border-mineshaft-700 pb-2 text-sm font-semibold text-mineshaft-200">
|
<h4 className="mb-2 flex items-center gap-2 px-2 text-sm text-mineshaft-300">
|
||||||
<FontAwesomeIcon icon={faKey} className="text-mineshaft-300" />
|
<FontAwesomeIcon icon={faKey} className="mr-1 text-mineshaft-300" />
|
||||||
Secrets ({pendingChanges.secrets.length})
|
Secrets ({pendingChanges.secrets.length})
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-3">
|
<div>
|
||||||
{pendingChanges.secrets.map((change) => (
|
{pendingChanges.secrets.map((change) => (
|
||||||
<ChangeTable
|
<ChangeTable
|
||||||
key={change.id}
|
key={change.id}
|
||||||
@@ -546,9 +599,10 @@ export const CommitForm: React.FC<CommitFormProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action Buttons */}
|
{/* Action Buttons */}
|
||||||
<div className="flex justify-end gap-3 border-t border-mineshaft-600 pt-4">
|
<div className="flex justify-end gap-3">
|
||||||
<Button
|
<Button
|
||||||
variant="outline_bg"
|
variant="plain"
|
||||||
|
colorSchema="secondary"
|
||||||
onClick={() => setIsModalOpen(false)}
|
onClick={() => setIsModalOpen(false)}
|
||||||
isDisabled={isCommitting}
|
isDisabled={isCommitting}
|
||||||
>
|
>
|
||||||
@@ -560,6 +614,7 @@ export const CommitForm: React.FC<CommitFormProps> = ({
|
|||||||
isDisabled={isCommitting || !commitMessage.trim()}
|
isDisabled={isCommitting || !commitMessage.trim()}
|
||||||
leftIcon={<FontAwesomeIcon icon={faCodeCommit} />}
|
leftIcon={<FontAwesomeIcon icon={faCodeCommit} />}
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
|
variant="outline_bg"
|
||||||
>
|
>
|
||||||
{isCommitting ? "Committing..." : "Commit Changes"}
|
{isCommitting ? "Committing..." : "Commit Changes"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+1
-1
@@ -1088,7 +1088,7 @@ export const SecretDetailSidebar = ({
|
|||||||
isDisabled={isSubmitting || !isDirty || !isAllowed}
|
isDisabled={isSubmitting || !isDirty || !isAllowed}
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
>
|
>
|
||||||
Save Changes
|
Apply Changes
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</ProjectPermissionCan>
|
</ProjectPermissionCan>
|
||||||
|
|||||||
+4
-4
@@ -38,7 +38,7 @@ import { WsTag } from "@app/hooks/api/types";
|
|||||||
import { subject } from "@casl/ability";
|
import { subject } from "@casl/ability";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { memo, useEffect, useRef, useCallback } from "react";
|
import { memo, useCallback, useEffect, useRef } from "react";
|
||||||
import { Controller, useFieldArray, useForm } from "react-hook-form";
|
import { Controller, useFieldArray, useForm } from "react-hook-form";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import {
|
import {
|
||||||
@@ -799,7 +799,7 @@ export const SecretItem = memo(
|
|||||||
isPending ? (
|
isPending ? (
|
||||||
<motion.div
|
<motion.div
|
||||||
key="options"
|
key="options"
|
||||||
className="flex h-10 flex-shrink-0 items-center space-x-4 px-[0.64rem]"
|
className="mt-0.5 flex h-10 flex-shrink-0 items-center space-x-3 px-[0.84rem]"
|
||||||
initial={{ x: 0, opacity: 0 }}
|
initial={{ x: 0, opacity: 0 }}
|
||||||
animate={{ x: 0, opacity: 1 }}
|
animate={{ x: 0, opacity: 1 }}
|
||||||
exit={{ x: 10, opacity: 0 }}
|
exit={{ x: 10, opacity: 0 }}
|
||||||
@@ -839,7 +839,7 @@ export const SecretItem = memo(
|
|||||||
) : (
|
) : (
|
||||||
<motion.div
|
<motion.div
|
||||||
key="options"
|
key="options"
|
||||||
className="flex h-10 flex-shrink-0 items-center space-x-4 px-[0.64rem]"
|
className="mt-0.5 flex h-10 flex-shrink-0 items-center space-x-3 px-[0.84rem]"
|
||||||
initial={{ x: 0, opacity: 0 }}
|
initial={{ x: 0, opacity: 0 }}
|
||||||
animate={{ x: 0, opacity: 1 }}
|
animate={{ x: 0, opacity: 1 }}
|
||||||
exit={{ x: 10, opacity: 0 }}
|
exit={{ x: 10, opacity: 0 }}
|
||||||
@@ -881,7 +881,7 @@ export const SecretItem = memo(
|
|||||||
>
|
>
|
||||||
<FontAwesomeSymbol
|
<FontAwesomeSymbol
|
||||||
symbolName={FontAwesomeSpriteName.Trash}
|
symbolName={FontAwesomeSpriteName.Trash}
|
||||||
className="h-5 w-4"
|
className="h-3.5 w-4"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user