feat: rename san to subjectAltNames, workflow to workflowId, nodeId to workflowNodeId, output to workflowOutputId, log to logs, succeed to succeeded
This commit is contained in:
@@ -19,14 +19,14 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
|
||||
const [messageApi, MessageContextHolder] = message.useMessage();
|
||||
|
||||
const handleDownloadPEMClick = async () => {
|
||||
const zipName = `${data.id}-${data.san}.zip`;
|
||||
const zipName = `${data.id}-${data.subjectAltNames}.zip`;
|
||||
const files = [
|
||||
{
|
||||
name: `${data.san}.pem`,
|
||||
name: `${data.subjectAltNames}.pem`,
|
||||
content: data.certificate ?? "",
|
||||
},
|
||||
{
|
||||
name: `${data.san}.key`,
|
||||
name: `${data.subjectAltNames}.key`,
|
||||
content: data.privateKey ?? "",
|
||||
},
|
||||
];
|
||||
@@ -39,17 +39,17 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
|
||||
{MessageContextHolder}
|
||||
|
||||
<Form layout="vertical">
|
||||
<Form.Item label={t("certificate.props.san")}>
|
||||
<Input value={data.san} placeholder="" />
|
||||
<Form.Item label={t("certificate.props.subject_alt_names")}>
|
||||
<Input value={data.subjectAltNames} placeholder="" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={t("certificate.props.expiry")}>
|
||||
<Input value={dayjs(data.expireAt).format("YYYY-MM-DD HH:mm:ss")} placeholder="" />
|
||||
<Form.Item label={t("certificate.props.validity")}>
|
||||
<Input value={`${dayjs(data.effectAt).format("YYYY-MM-DD HH:mm:ss")} ~ ${dayjs(data.expireAt).format("YYYY-MM-DD HH:mm:ss")}`} placeholder="" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<div className="mb-2 flex w-full items-center justify-between">
|
||||
<label>{t("certificate.props.certificate_chain")}</label>
|
||||
<label>{t("certificate.props.certificate")}</label>
|
||||
<Tooltip title={t("common.button.copy")}>
|
||||
<CopyToClipboard
|
||||
text={data.certificate}
|
||||
|
||||
@@ -68,7 +68,7 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
|
||||
return (
|
||||
<Space>
|
||||
<Avatar src={provider?.icon} size="small" />
|
||||
<Typography.Text className="truncate">{t(provider?.name ?? " ")}</Typography.Text>
|
||||
<Typography.Text className="truncate">{t(provider?.name ?? "")}</Typography.Text>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
|
||||
<div className="flex items-center justify-between space-x-2">
|
||||
<Typography.Text className="truncate">{t(channel?.name ?? " ")}</Typography.Text>
|
||||
<Typography.Text className="truncate" type="secondary">
|
||||
{(node.config?.subject as string) ?? ""}
|
||||
{config.subject ?? ""}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ const WorkflowRunDetailDrawer = ({ data, loading, trigger, ...props }: WorkflowR
|
||||
|
||||
<Drawer destroyOnClose open={open} loading={loading} placement="right" title={`runlog-${data?.id}`} width={640} onClose={() => setOpen(false)}>
|
||||
<Show when={!!data}>
|
||||
<Show when={data!.succeed}>
|
||||
<Show when={data!.succeeded}>
|
||||
<Alert showIcon type="success" message={<Typography.Text type="success">{t("workflow_run.props.status.succeeded")}</Typography.Text>} />
|
||||
</Show>
|
||||
|
||||
@@ -42,7 +42,7 @@ const WorkflowRunDetailDrawer = ({ data, loading, trigger, ...props }: WorkflowR
|
||||
|
||||
<div className="mt-4 rounded-md bg-black p-4 text-stone-200">
|
||||
<div className="flex flex-col space-y-3">
|
||||
{data!.log.map((item, i) => {
|
||||
{data!.logs.map((item, i) => {
|
||||
return (
|
||||
<div key={i} className="flex flex-col space-y-2">
|
||||
<div>{item.nodeName}</div>
|
||||
|
||||
@@ -46,7 +46,7 @@ const WorkflowRuns = ({ className, style, workflowId }: WorkflowRunsProps) => {
|
||||
title: t("workflow_run.props.status"),
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
if (record.succeed) {
|
||||
if (record.succeeded) {
|
||||
return (
|
||||
<Space>
|
||||
<CheckCircleOutlinedIcon style={{ color: themeToken.colorSuccess }} />
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
import { type WorkflowModel } from "./workflow";
|
||||
|
||||
export interface CertificateModel extends BaseModel {
|
||||
san: string;
|
||||
source: string;
|
||||
subjectAltNames: string;
|
||||
certificate: string;
|
||||
privateKey: string;
|
||||
issuerCertificate: string;
|
||||
certUrl: string;
|
||||
certStableUrl: string;
|
||||
output: string;
|
||||
effectAt: ISO8601String;
|
||||
expireAt: ISO8601String;
|
||||
workflow: string;
|
||||
nodeId: string;
|
||||
workflowId: string;
|
||||
expand: {
|
||||
workflow?: WorkflowModel;
|
||||
workflowId?: WorkflowModel; // TODO: ugly, maybe to use an alias?
|
||||
};
|
||||
}
|
||||
|
||||
export const CERTIFICATE_SOURCES = Object.freeze({
|
||||
WORKFLOW: "workflow",
|
||||
UPLOAD: "upload",
|
||||
} as const);
|
||||
|
||||
export type CertificateSourceType = (typeof CERTIFICATE_SOURCES)[keyof typeof CERTIFICATE_SOURCES];
|
||||
|
||||
@@ -400,9 +400,10 @@ export const isAllNodesValidated = (node: WorkflowNode): boolean => {
|
||||
*/
|
||||
export const getExecuteMethod = (node: WorkflowNode): { trigger: string; triggerCron: string } => {
|
||||
if (node.type === WorkflowNodeType.Start) {
|
||||
const config = node.config as WorkflowNodeConfigAsStart;
|
||||
return {
|
||||
trigger: (node.config?.trigger as string) ?? "",
|
||||
triggerCron: (node.config?.triggerCron as string) ?? "",
|
||||
trigger: config.trigger ?? "",
|
||||
triggerCron: config.triggerCron ?? "",
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export interface WorkflowRunModel extends BaseModel {
|
||||
workflow: string;
|
||||
log: WorkflowRunLog[];
|
||||
workflowId: string;
|
||||
logs: WorkflowRunLog[];
|
||||
error: string;
|
||||
succeed: boolean;
|
||||
succeeded: boolean;
|
||||
}
|
||||
|
||||
export type WorkflowRunLog = {
|
||||
nodeId: string;
|
||||
nodeName: string;
|
||||
error: string;
|
||||
outputs: WorkflowRunLogOutput[];
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type WorkflowRunLogOutput = {
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
"certificate.action.delete": "Delete certificate",
|
||||
"certificate.action.download": "Download certificate",
|
||||
|
||||
"certificate.props.san": "Name",
|
||||
"certificate.props.expiry": "Expiry",
|
||||
"certificate.props.expiry.left_days": "{{left}} / {{total}} days left",
|
||||
"certificate.props.expiry.expired": "Expired",
|
||||
"certificate.props.expiry.expiration": "Expire on {{date}}",
|
||||
"certificate.props.expiry.filter.expire_soon": "Expire soon",
|
||||
"certificate.props.expiry.filter.expired": "Expired",
|
||||
"certificate.props.workflow": "Workflow",
|
||||
"certificate.props.subject_alt_names": "Name",
|
||||
"certificate.props.validity": "Expiry",
|
||||
"certificate.props.validity.left_days": "{{left}} / {{total}} days left",
|
||||
"certificate.props.validity.expired": "Expired",
|
||||
"certificate.props.validity.expiration": "Expire on {{date}}",
|
||||
"certificate.props.validity.filter.expire_soon": "Expire soon",
|
||||
"certificate.props.validity.filter.expired": "Expired",
|
||||
"certificate.props.source": "Source",
|
||||
"certificate.props.source.workflow": "Workflow",
|
||||
"certificate.props.certificate_chain": "Certificate chain",
|
||||
"certificate.props.source.upload": "Upload",
|
||||
"certificate.props.certificate": "Certificate chain",
|
||||
"certificate.props.private_key": "Private key",
|
||||
"certificate.props.created_at": "Created at",
|
||||
"certificate.props.updated_at": "Updated at"
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
"certificate.action.delete": "删除证书",
|
||||
"certificate.action.download": "下载证书",
|
||||
|
||||
"certificate.props.san": "名称",
|
||||
"certificate.props.expiry": "有效期限",
|
||||
"certificate.props.expiry.left_days": "{{left}} / {{total}} 天",
|
||||
"certificate.props.expiry.expired": "已到期",
|
||||
"certificate.props.expiry.expiration": "{{date}} 到期",
|
||||
"certificate.props.expiry.filter.expire_soon": "即将到期",
|
||||
"certificate.props.expiry.filter.expired": "已到期",
|
||||
"certificate.props.workflow": "所属工作流",
|
||||
"certificate.props.subject_alt_names": "名称",
|
||||
"certificate.props.validity": "有效期限",
|
||||
"certificate.props.validity.left_days": "{{left}} / {{total}} 天",
|
||||
"certificate.props.validity.expired": "已到期",
|
||||
"certificate.props.validity.expiration": "{{date}} 到期",
|
||||
"certificate.props.validity.filter.expire_soon": "即将到期",
|
||||
"certificate.props.validity.filter.expired": "已到期",
|
||||
"certificate.props.source": "来源",
|
||||
"certificate.props.source.workflow": "工作流",
|
||||
"certificate.props.certificate_chain": "证书内容",
|
||||
"certificate.props.source.upload": "用户上传",
|
||||
"certificate.props.certificate": "证书内容",
|
||||
"certificate.props.private_key": "私钥内容",
|
||||
"certificate.props.created_at": "创建时间",
|
||||
"certificate.props.updated_at": "更新时间"
|
||||
|
||||
@@ -9,7 +9,7 @@ import dayjs from "dayjs";
|
||||
import { ClientResponseError } from "pocketbase";
|
||||
|
||||
import CertificateDetailDrawer from "@/components/certificate/CertificateDetailDrawer";
|
||||
import { type CertificateModel } from "@/domain/certificate";
|
||||
import { CERTIFICATE_SOURCES, type CertificateModel } from "@/domain/certificate";
|
||||
import { type ListCertificateRequest, list as listCertificate } from "@/repository/certificate";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
|
||||
@@ -33,18 +33,18 @@ const CertificateList = () => {
|
||||
},
|
||||
{
|
||||
key: "name",
|
||||
title: t("certificate.props.san"),
|
||||
render: (_, record) => <Typography.Text>{record.san}</Typography.Text>,
|
||||
title: t("certificate.props.subject_alt_names"),
|
||||
render: (_, record) => <Typography.Text>{record.subjectAltNames}</Typography.Text>,
|
||||
},
|
||||
{
|
||||
key: "expiry",
|
||||
title: t("certificate.props.expiry"),
|
||||
title: t("certificate.props.validity"),
|
||||
ellipsis: true,
|
||||
defaultFilteredValue: searchParams.has("state") ? [searchParams.get("state") as string] : undefined,
|
||||
filterDropdown: ({ setSelectedKeys, confirm, clearFilters }) => {
|
||||
const items: Required<MenuProps>["items"] = [
|
||||
["expireSoon", "certificate.props.expiry.filter.expire_soon"],
|
||||
["expired", "certificate.props.expiry.filter.expired"],
|
||||
["expireSoon", "certificate.props.validity.filter.expire_soon"],
|
||||
["expired", "certificate.props.validity.filter.expired"],
|
||||
].map(([key, label]) => {
|
||||
return {
|
||||
key,
|
||||
@@ -94,13 +94,13 @@ const CertificateList = () => {
|
||||
return (
|
||||
<Space className="max-w-full" direction="vertical" size={4}>
|
||||
{left > 0 ? (
|
||||
<Typography.Text type="success">{t("certificate.props.expiry.left_days", { left, total })}</Typography.Text>
|
||||
<Typography.Text type="success">{t("certificate.props.validity.left_days", { left, total })}</Typography.Text>
|
||||
) : (
|
||||
<Typography.Text type="danger">{t("certificate.props.expiry.expired")}</Typography.Text>
|
||||
<Typography.Text type="danger">{t("certificate.props.validity.expired")}</Typography.Text>
|
||||
)}
|
||||
|
||||
<Typography.Text type="secondary">
|
||||
{t("certificate.props.expiry.expiration", { date: dayjs(record.expireAt).format("YYYY-MM-DD") })}
|
||||
{t("certificate.props.validity.expiration", { date: dayjs(record.expireAt).format("YYYY-MM-DD") })}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
);
|
||||
@@ -111,23 +111,29 @@ const CertificateList = () => {
|
||||
title: t("certificate.props.source"),
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
const workflowId = record.workflow;
|
||||
return workflowId ? (
|
||||
<Space className="max-w-full" direction="vertical" size={4}>
|
||||
<Typography.Text>{t("certificate.props.source.workflow")}</Typography.Text>
|
||||
<Typography.Link
|
||||
type="secondary"
|
||||
ellipsis
|
||||
onClick={() => {
|
||||
navigate(`/workflows/${workflowId}`);
|
||||
}}
|
||||
>
|
||||
{record.expand?.workflow?.name ?? ""}
|
||||
</Typography.Link>
|
||||
</Space>
|
||||
) : (
|
||||
<>TODO: 支持手动上传</>
|
||||
);
|
||||
if (record.source === CERTIFICATE_SOURCES.WORKFLOW) {
|
||||
const workflowId = record.workflowId;
|
||||
return (
|
||||
<Space className="max-w-full" direction="vertical" size={4}>
|
||||
<Typography.Text>{t("certificate.props.source.workflow")}</Typography.Text>
|
||||
<Typography.Link
|
||||
type="secondary"
|
||||
ellipsis
|
||||
onClick={() => {
|
||||
if (workflowId) {
|
||||
navigate(`/workflows/${workflowId}`);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{record.expand?.workflowId?.name ?? `#${workflowId}`}
|
||||
</Typography.Link>
|
||||
</Space>
|
||||
);
|
||||
} else if (record.source === CERTIFICATE_SOURCES.UPLOAD) {
|
||||
return <Typography.Text>{t("certificate.props.source.upload")}</Typography.Text>;
|
||||
}
|
||||
|
||||
return <></>;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ export const list = async (request: ListCertificateRequest) => {
|
||||
|
||||
const options: RecordListOptions = {
|
||||
sort: "-created",
|
||||
expand: "workflow",
|
||||
expand: "workflowId",
|
||||
requestKey: null,
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export const list = async (request: ListWorkflowRunsRequest) => {
|
||||
return await getPocketBase()
|
||||
.collection(COLLECTION_NAME)
|
||||
.getList<WorkflowRunModel>(page, perPage, {
|
||||
filter: getPocketBase().filter("workflow={:workflowId}", { workflowId: request.workflowId }),
|
||||
filter: getPocketBase().filter("workflowId={:workflowId}", { workflowId: request.workflowId }),
|
||||
sort: "-created",
|
||||
requestKey: null,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user