improvements: address feedback

This commit is contained in:
Scott Wilson
2025-01-22 10:50:24 -08:00
parent c92c160709
commit 8f2a504fd0
22 changed files with 144 additions and 143 deletions
@@ -76,7 +76,7 @@ export const SecretSyncRow = ({
name,
description,
syncStatus,
isEnabled,
isAutoSyncEnabled,
projectId
} = secretSync;
@@ -131,8 +131,7 @@ export const SecretSyncRow = ({
}
className={twMerge(
"group h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700",
syncStatus === SecretSyncStatus.Failed && "bg-red/5 hover:bg-red/10",
!isEnabled && "bg-mineshaft-400/15 opacity-50 hover:opacity-100"
syncStatus === SecretSyncStatus.Failed && "bg-red/5 hover:bg-red/10"
)}
key={`sync-${id}`}
>
@@ -180,58 +179,59 @@ export const SecretSyncRow = ({
<SecretSyncDestinationCol secretSync={secretSync} />
<Td>
<div className="flex items-center gap-1">
{isEnabled ? (
syncStatus && (
<Tooltip
position="left"
className="max-w-sm"
content={
[SecretSyncStatus.Succeeded, SecretSyncStatus.Failed].includes(syncStatus) ? (
<div className="flex flex-col gap-2 whitespace-normal py-1">
{lastSyncedAt && (
<div>
<div
className={`mb-2 flex self-start ${syncStatus === SecretSyncStatus.Failed ? "text-yellow" : "text-green"}`}
>
<FontAwesomeIcon
icon={faCalendarCheck}
className="ml-1 pr-1.5 pt-0.5 text-sm"
/>
<div className="text-xs">Last Synced</div>
</div>
<div className="rounded bg-mineshaft-600 p-2 text-xs">
{format(new Date(lastSyncedAt), "yyyy-MM-dd, hh:mm aaa")}
</div>
{syncStatus && (
<Tooltip
position="left"
className="max-w-sm"
content={
[SecretSyncStatus.Succeeded, SecretSyncStatus.Failed].includes(syncStatus) ? (
<div className="flex flex-col gap-2 whitespace-normal py-1">
{lastSyncedAt && (
<div>
<div
className={`mb-2 flex self-start ${syncStatus === SecretSyncStatus.Failed ? "text-yellow" : "text-green"}`}
>
<FontAwesomeIcon
icon={faCalendarCheck}
className="ml-1 pr-1.5 pt-0.5 text-sm"
/>
<div className="text-xs">Last Synced</div>
</div>
)}
{failureMessage && (
<div>
<div className="mb-2 flex self-start text-red">
<FontAwesomeIcon
icon={faXmark}
className="ml-1 pr-1.5 pt-0.5 text-sm"
/>
<div className="text-xs">Failure Reason</div>
</div>
<div className="rounded bg-mineshaft-600 p-2 text-xs">
{failureMessage}
</div>
<div className="rounded bg-mineshaft-600 p-2 text-xs">
{format(new Date(lastSyncedAt), "yyyy-MM-dd, hh:mm aaa")}
</div>
)}
</div>
) : undefined
}
>
<div>
<SecretSyncStatusBadge status={syncStatus} />
</div>
</Tooltip>
)
) : (
<Badge className="flex w-min items-center gap-1.5 bg-mineshaft-400/50 text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Disabled</span>
</Badge>
</div>
)}
{failureMessage && (
<div>
<div className="mb-2 flex self-start text-red">
<FontAwesomeIcon icon={faXmark} className="ml-1 pr-1.5 pt-0.5 text-sm" />
<div className="text-xs">Failure Reason</div>
</div>
<div className="rounded bg-mineshaft-600 p-2 text-xs">{failureMessage}</div>
</div>
)}
</div>
) : undefined
}
>
<div>
<SecretSyncStatusBadge status={syncStatus} />
</div>
</Tooltip>
)}
{!isAutoSyncEnabled && (
<Tooltip
className="text-xs"
content="Auto-Sync is disabled. Changes to the source location will not be automatically synced to the destination."
>
<div>
<Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap bg-mineshaft-400/50 text-bunker-300">
<FontAwesomeIcon icon={faBan} />
{!syncStatus && "Auto-Sync Disabled"}
</Badge>
</div>
</Tooltip>
)}
<SecretSyncImportStatusBadge mini secretSync={secretSync} />
<SecretSyncRemoveStatusBadge mini secretSync={secretSync} />
@@ -359,13 +359,13 @@ export const SecretSyncRow = ({
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed}
icon={<FontAwesomeIcon icon={isEnabled ? faToggleOff : faToggleOn} />}
icon={<FontAwesomeIcon icon={isAutoSyncEnabled ? faToggleOff : faToggleOn} />}
onClick={(e) => {
e.stopPropagation();
onToggleEnable(secretSync);
}}
>
{isEnabled ? "Disable" : "Enable"} Sync
{isAutoSyncEnabled ? "Disable" : "Enable"} Auto-Sync
</DropdownMenuItem>
)}
</ProjectPermissionCan>
@@ -2,7 +2,6 @@ import { useMemo, useState } from "react";
import {
faArrowDown,
faArrowUp,
faBan,
faCheck,
faCheckCircle,
faFilter,
@@ -61,17 +60,10 @@ enum SecretSyncsOrderBy {
type SecretSyncFilters = {
destinations: SecretSync[];
status: SecretSyncStatusCol[];
status: SecretSyncStatus[];
environmentIds: string[];
};
enum SecretSyncStatusCol {
Pending = "pending",
Success = "success",
Failed = "failed",
Disabled = "disabled"
}
const getSyncStatusOrderValue = (syncStatus: SecretSyncStatus | null) => {
switch (syncStatus) {
case SecretSyncStatus.Failed:
@@ -91,10 +83,10 @@ type Props = {
};
const STATUS_ICON_MAP = {
[SecretSyncStatusCol.Success]: { icon: faCheck, className: "text-green", name: "Synced" },
[SecretSyncStatusCol.Failed]: { icon: faWarning, className: "text-red", name: "Not Synced" },
[SecretSyncStatusCol.Pending]: { icon: faRotate, className: "text-yellow", name: "Syncing" },
[SecretSyncStatusCol.Disabled]: { icon: faBan, className: "text-mineshaft-400", name: "Disabled" }
[SecretSyncStatus.Succeeded]: { icon: faCheck, className: "text-green", name: "Synced" },
[SecretSyncStatus.Failed]: { icon: faWarning, className: "text-red", name: "Not Synced" },
[SecretSyncStatus.Pending]: { icon: faRotate, className: "text-yellow", name: "Syncing" },
[SecretSyncStatus.Running]: { icon: faRotate, className: "text-yellow", name: "Syncing" }
};
export const SecretSyncsTable = ({ secretSyncs }: Props) => {
@@ -133,8 +125,7 @@ export const SecretSyncsTable = ({ secretSyncs }: Props) => {
() =>
secretSyncs
.filter((secretSync) => {
const { destination, name, connection, folder, environment, syncStatus, isEnabled } =
secretSync;
const { destination, name, connection, folder, environment, syncStatus } = secretSync;
if (filters.destinations.length && !filters.destinations.includes(destination))
return false;
@@ -146,12 +137,7 @@ export const SecretSyncsTable = ({ secretSyncs }: Props) => {
)
return false;
const status = isEnabled ? syncStatus : SecretSyncStatusCol.Disabled;
if (
filters.status.length &&
(!status || !filters.status.includes(status as SecretSyncStatusCol))
) {
if (filters.status.length && (!syncStatus || !filters.status.includes(syncStatus))) {
return false;
}
@@ -184,9 +170,6 @@ export const SecretSyncsTable = ({ secretSyncs }: Props) => {
getSecretSyncDestinationColValues(syncTwo).primaryText.toLowerCase()
);
case SecretSyncsOrderBy.Status:
if (!syncOne.isEnabled && syncTwo.isEnabled) return 1;
if (syncOne.isEnabled && !syncTwo.isEnabled) return -1;
if (!syncOne.syncStatus && syncTwo.syncStatus) return 1;
if (syncOne.syncStatus && !syncTwo.syncStatus) return -1;
if (!syncOne.syncStatus && !syncTwo.syncStatus) return 0;
@@ -238,22 +221,22 @@ export const SecretSyncsTable = ({ secretSyncs }: Props) => {
const handleToggleEnableSync = async (secretSync: TSecretSync) => {
const destinationName = SECRET_SYNC_MAP[secretSync.destination].name;
const isEnabled = !secretSync.isEnabled;
const isAutoSyncEnabled = !secretSync.isAutoSyncEnabled;
try {
await updateSync.mutateAsync({
syncId: secretSync.id,
destination: secretSync.destination,
isEnabled
isAutoSyncEnabled
});
createNotification({
text: `Successfully ${isEnabled ? "enabled" : "disabled"} ${destinationName} Sync`,
text: `Successfully ${isAutoSyncEnabled ? "enabled" : "disabled"} auto-sync for ${destinationName} Sync`,
type: "success"
});
} catch {
createNotification({
text: `Failed to ${isEnabled ? "enable" : "disable"} ${destinationName} Sync`,
text: `Failed to ${isAutoSyncEnabled ? "enable" : "disable"} auto-sync for ${destinationName} Sync`,
type: "error"
});
}
@@ -306,7 +289,7 @@ export const SecretSyncsTable = ({ secretSyncs }: Props) => {
</DropdownMenuTrigger>
<DropdownMenuContent className="thin-scrollbar max-h-[70vh] overflow-y-auto" align="end">
<DropdownMenuLabel>Status</DropdownMenuLabel>
{Object.values(SecretSyncStatusCol).map((status) => (
{Object.values(SecretSyncStatus).map((status) => (
<DropdownMenuItem
onClick={(e) => {
e.preventDefault();
@@ -442,7 +425,7 @@ export const SecretSyncsTable = ({ secretSyncs }: Props) => {
</IconButton>
</div>
</Th>
<Th className="min-w-[10rem]">
<Th className="min-w-[10.5rem]">
<div className="flex items-center">
Status
<IconButton
@@ -1,5 +1,6 @@
import { useCallback } from "react";
import {
faBan,
faCheck,
faCopy,
faDownload,
@@ -24,6 +25,7 @@ import {
SecretSyncRemoveStatusBadge
} from "@app/components/secret-syncs";
import {
Badge,
Button,
DropdownMenu,
DropdownMenuContent,
@@ -84,22 +86,22 @@ export const SecretSyncActionTriggers = ({ secretSync }: Props) => {
}, [isIdCopied]);
const handleToggleEnableSync = async () => {
const isEnabled = !secretSync.isEnabled;
const isAutoSyncEnabled = !secretSync.isAutoSyncEnabled;
try {
await updateSync.mutateAsync({
syncId: secretSync.id,
destination: secretSync.destination,
isEnabled
isAutoSyncEnabled
});
createNotification({
text: `Successfully ${isEnabled ? "enabled" : "disabled"} ${destinationName} Sync`,
text: `Successfully ${isAutoSyncEnabled ? "enabled" : "disabled"} auto-sync for ${destinationName} Sync`,
type: "success"
});
} catch {
createNotification({
text: `Failed to ${isEnabled ? "enable" : "disable"} ${destinationName} Sync`,
text: `Failed to ${isAutoSyncEnabled ? "enable" : "disable"} auto-sync for ${destinationName} Sync`,
type: "error"
});
}
@@ -129,6 +131,27 @@ export const SecretSyncActionTriggers = ({ secretSync }: Props) => {
<div className="ml-auto mt-4 flex flex-wrap items-center justify-end gap-2">
<SecretSyncImportStatusBadge secretSync={secretSync} />
<SecretSyncRemoveStatusBadge secretSync={secretSync} />
{secretSync.isAutoSyncEnabled ? (
<Badge
variant="success"
className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
>
<FontAwesomeIcon icon={faRotate} />
<span>Auto-Sync Enabled</span>
</Badge>
) : (
<Tooltip
className="text-xs"
content="Auto-Sync is disabled. Changes to the source location will not be automatically synced to the destination."
>
<div>
<Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap bg-mineshaft-400/50 text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Auto-Sync Disabled</span>
</Badge>
</div>
</Tooltip>
)}
<div>
<ProjectPermissionCan
I={ProjectPermissionSecretSyncActions.SyncSecrets}
@@ -230,11 +253,13 @@ export const SecretSyncActionTriggers = ({ secretSync }: Props) => {
<DropdownMenuItem
isDisabled={!isAllowed}
icon={
<FontAwesomeIcon icon={secretSync.isEnabled ? faToggleOff : faToggleOn} />
<FontAwesomeIcon
icon={secretSync.isAutoSyncEnabled ? faToggleOff : faToggleOn}
/>
}
onClick={handleToggleEnableSync}
>
{secretSync.isEnabled ? "Disable" : "Enable"} Sync
{secretSync.isAutoSyncEnabled ? "Disable" : "Enable"} Auto-Sync
</DropdownMenuItem>
)}
</ProjectPermissionCan>
@@ -1,11 +1,11 @@
import { useMemo } from "react";
import { faBan, faEdit } from "@fortawesome/free-solid-svg-icons";
import { faEdit } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from "date-fns";
import { ProjectPermissionCan } from "@app/components/permissions";
import { SecretSyncLabel, SecretSyncStatusBadge } from "@app/components/secret-syncs";
import { Badge, IconButton } from "@app/components/v2";
import { SecretSyncLabel } from "@app/components/secret-syncs";
import { IconButton } from "@app/components/v2";
import { ProjectPermissionSub } from "@app/context";
import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types";
import { SecretSyncStatus, TSecretSync } from "@app/hooks/api/secretSyncs";
@@ -16,7 +16,7 @@ type Props = {
};
export const SecretSyncDetailsSection = ({ secretSync, onEditDetails }: Props) => {
const { syncStatus, lastSyncMessage, lastSyncedAt, name, description, isEnabled } = secretSync;
const { syncStatus, lastSyncMessage, lastSyncedAt, name, description } = secretSync;
const failureMessage = useMemo(() => {
if (syncStatus === SecretSyncStatus.Failed) {
@@ -57,16 +57,6 @@ export const SecretSyncDetailsSection = ({ secretSync, onEditDetails }: Props) =
<div className="space-y-3">
<SecretSyncLabel label="Name">{name}</SecretSyncLabel>
<SecretSyncLabel label="Description">{description}</SecretSyncLabel>
<SecretSyncLabel label="Status">
{isEnabled ? (
syncStatus && <SecretSyncStatusBadge status={syncStatus} />
) : (
<Badge className="flex w-min items-center gap-1.5 bg-mineshaft-400/50 text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Disabled</span>
</Badge>
)}
</SecretSyncLabel>
{lastSyncedAt && (
<SecretSyncLabel label="Last Synced">
{format(new Date(lastSyncedAt), "yyyy-MM-dd, hh:mm aaa")}