feat(dashboard-v2): add node about public key needing configuration
This commit is contained in:
parent
9dd4b8eb17
commit
08bab146ec
|
@ -1,12 +1,16 @@
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import cn from "classnames";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
import { Alert } from "../Alert";
|
import { Alert } from "../Alert";
|
||||||
import { Button } from "../Button";
|
import { Button } from "../Button";
|
||||||
import { AddSkylinkToAPIKeyForm } from "../forms/AddSkylinkToAPIKeyForm";
|
import { AddSkylinkToAPIKeyForm } from "../forms/AddSkylinkToAPIKeyForm";
|
||||||
import { CogIcon, TrashIcon } from "../Icons";
|
import { CogIcon, ImportantNoteIcon, TrashIcon } from "../Icons";
|
||||||
import { Modal } from "../Modal";
|
import { Modal } from "../Modal";
|
||||||
|
|
||||||
import { useAPIKeyEdit } from "./useAPIKeyEdit";
|
import { useAPIKeyEdit } from "./useAPIKeyEdit";
|
||||||
import { useAPIKeyRemoval } from "./useAPIKeyRemoval";
|
import { useAPIKeyRemoval } from "./useAPIKeyRemoval";
|
||||||
|
import { Tooltip } from "../Tooltip/Tooltip";
|
||||||
|
|
||||||
export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
||||||
const { id, name, createdAt, skylinks } = apiKey;
|
const { id, name, createdAt, skylinks } = apiKey;
|
||||||
|
@ -49,9 +53,23 @@ export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
||||||
abortEdit();
|
abortEdit();
|
||||||
}, [abortEdit]);
|
}, [abortEdit]);
|
||||||
|
|
||||||
|
const needsAttention = isPublic && skylinks?.length === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="grid grid-cols-2 sm:grid-cols-[1fr_repeat(2,_max-content)] py-6 sm:py-4 px-4 gap-x-8 bg-white odd:bg-palette-100/50">
|
<li
|
||||||
<span className="truncate col-span-2 sm:col-span-1">{name || id}</span>
|
className={cn("grid grid-cols-2 sm:grid-cols-[1fr_repeat(2,_max-content)] py-6 sm:py-4 px-4 gap-x-8", {
|
||||||
|
"bg-red-100": needsAttention,
|
||||||
|
"bg-white odd:bg-palette-100/50": !needsAttention,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<span className="col-span-2 sm:col-span-1 flex items-center">
|
||||||
|
<span className={cn("truncate", { "text-palette-300": !name })}>{name || "unnamed key"}</span>
|
||||||
|
{needsAttention && (
|
||||||
|
<Tooltip message="This key has no Skylinks configured.">
|
||||||
|
<ImportantNoteIcon className="text-error -mt-2" size={24} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
<span className="col-span-2 my-4 border-t border-t-palette-200/50 sm:hidden" />
|
<span className="col-span-2 my-4 border-t border-t-palette-200/50 sm:hidden" />
|
||||||
<span className="text-palette-400">{dayjs(createdAt).format("MMM DD, YYYY")}</span>
|
<span className="text-palette-400">{dayjs(createdAt).format("MMM DD, YYYY")}</span>
|
||||||
<span className="flex items-center justify-end">
|
<span className="flex items-center justify-end">
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { withIconProps } from "../withIconProps";
|
||||||
|
|
||||||
|
export const ImportantNoteIcon = withIconProps(({ size, ...props }) => (
|
||||||
|
<svg width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||||
|
<g fill="none" fillRule="evenodd">
|
||||||
|
<g fill="currentColor" fillRule="nonzero">
|
||||||
|
<path d="M16.028 6c5.523 0 10 4.477 10 10s-4.477 10-10 10h-9c-.405.017-.78-.212-.95-.58-.156-.372-.074-.802.21-1.09l2-2C6.82 20.549 6.02 18.31 6.028 16c0-5.523 4.477-10 10-10zm3.05 2.607c-3.526-1.458-7.592-.222-9.71 2.953-2.119 3.174-1.7 7.403 1 10.1.189.185.296.436.3.7 0 .267-.109.523-.3.71l-.93.93h6.59c3.817-.003 7.1-2.701 7.841-6.445.742-3.744-1.264-7.49-4.79-8.948zM16.028 18c.552 0 1 .448 1 1s-.448 1-1 1-1-.448-1-1 .448-1 1-1zM17 12v5h-2v-5h2z" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
));
|
|
@ -14,3 +14,4 @@ export * from "./icons/CopyIcon";
|
||||||
export * from "./icons/ShareIcon";
|
export * from "./icons/ShareIcon";
|
||||||
export * from "./icons/SimpleUploadIcon";
|
export * from "./icons/SimpleUploadIcon";
|
||||||
export * from "./icons/TrashIcon";
|
export * from "./icons/TrashIcon";
|
||||||
|
export * from "./icons/ImportantNoteIcon";
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import React, { Children, cloneElement, useState } from "react";
|
||||||
|
import styled, { keyframes } from "styled-components";
|
||||||
|
|
||||||
|
const fadeIn = keyframes`
|
||||||
|
0% { opacity: 0; }
|
||||||
|
100% { opacity: 1; }
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Popper = styled.div.attrs({
|
||||||
|
className: `absolute left-full top-1/2 z-10 px-2 py-1 text-xs
|
||||||
|
bg-black/90 text-white rounded`,
|
||||||
|
})`
|
||||||
|
transform: translateY(-50%);
|
||||||
|
animation: ${fadeIn} 0.2s ease-in-out;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Tooltip = ({ message, children, className }) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
|
const show = () => setVisible(true);
|
||||||
|
const hide = () => setVisible(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="relative" onMouseEnter={show} onMouseLeave={hide}>
|
||||||
|
{children}
|
||||||
|
{visible && <Popper className={className}>{message}</Popper>}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
|
@ -39,6 +39,7 @@ export const AddSkylinkToAPIKeyForm = ({ addSkylink }) => (
|
||||||
id="skylink"
|
id="skylink"
|
||||||
name="skylink"
|
name="skylink"
|
||||||
label="New Skylink"
|
label="New Skylink"
|
||||||
|
placeholder="Paste a new Skylink here"
|
||||||
error={errors.skylink}
|
error={errors.skylink}
|
||||||
touched={touched.skylink}
|
touched={touched.skylink}
|
||||||
/>
|
/>
|
||||||
|
|
Reference in New Issue