From d5568608f51c2e47fa11a722e7b4007e0dfb35af Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 21 Jan 2025 00:42:28 +0800 Subject: [PATCH 1/9] refactor: clean code --- internal/applicant/acme_user.go | 7 ++-- internal/applicant/applicant.go | 2 +- internal/domain/workflow.go | 10 ++--- internal/pkg/core/logger/builtin.go | 4 +- internal/pkg/utils/types/types.go | 1 + internal/workflow/processor/processor.go | 38 ++++++++--------- ui/src/components/workflow/node/AddNode.tsx | 6 +-- .../workflow/node/ConditionNode.tsx | 4 +- .../workflow/node/ExecuteResultNode.tsx | 19 +++++---- .../components/workflow/node/_SharedNode.tsx | 41 ++++++++----------- ui/src/domain/workflow.ts | 20 ++++----- .../i18n/locales/en/nls.workflow.nodes.json | 12 +++--- .../i18n/locales/zh/nls.workflow.nodes.json | 12 +++--- 13 files changed, 85 insertions(+), 91 deletions(-) diff --git a/internal/applicant/acme_user.go b/internal/applicant/acme_user.go index daa7a4cf..1ab4c424 100644 --- a/internal/applicant/acme_user.go +++ b/internal/applicant/acme_user.go @@ -82,9 +82,9 @@ type acmeAccountRepository interface { var registerGroup singleflight.Group -func registerAcmeUser(client *lego.Client, sslProviderConfig *acmeSSLProviderConfig, user *acmeUser) (*registration.Resource, error) { +func registerAcmeUserWithSingleFlight(client *lego.Client, sslProviderConfig *acmeSSLProviderConfig, user *acmeUser) (*registration.Resource, error) { resp, err, _ := registerGroup.Do(fmt.Sprintf("register_acme_user_%s_%s", sslProviderConfig.Provider, user.GetEmail()), func() (interface{}, error) { - return register(client, sslProviderConfig, user) + return registerAcmeUser(client, sslProviderConfig, user) }) if err != nil { @@ -94,7 +94,7 @@ func registerAcmeUser(client *lego.Client, sslProviderConfig *acmeSSLProviderCon return resp.(*registration.Resource), nil } -func register(client *lego.Client, sslProviderConfig *acmeSSLProviderConfig, user *acmeUser) (*registration.Resource, error) { +func registerAcmeUser(client *lego.Client, sslProviderConfig *acmeSSLProviderConfig, user *acmeUser) (*registration.Resource, error) { var reg *registration.Resource var err error switch sslProviderConfig.Provider { @@ -123,7 +123,6 @@ func register(client *lego.Client, sslProviderConfig *acmeSSLProviderConfig, use } repo := repository.NewAcmeAccountRepository() - resp, err := repo.GetByCAAndEmail(sslProviderConfig.Provider, user.GetEmail()) if err == nil { user.privkey = resp.Key diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index abee203a..a612ebda 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -159,7 +159,7 @@ func apply(challengeProvider challenge.Provider, options *applicantOptions) (*Ap // New users need to register first if !acmeUser.hasRegistration() { - reg, err := registerAcmeUser(client, sslProviderConfig, acmeUser) + reg, err := registerAcmeUserWithSingleFlight(client, sslProviderConfig, acmeUser) if err != nil { return nil, fmt.Errorf("failed to register: %w", err) } diff --git a/internal/domain/workflow.go b/internal/domain/workflow.go index ff675f08..10ca1c28 100644 --- a/internal/domain/workflow.go +++ b/internal/domain/workflow.go @@ -68,11 +68,11 @@ type WorkflowNodeConfigForApply struct { ProviderConfig map[string]any `json:"providerConfig"` // DNS 提供商额外配置 KeyAlgorithm string `json:"keyAlgorithm"` // 密钥算法 Nameservers string `json:"nameservers"` // DNS 服务器列表,以半角逗号分隔 - DnsPropagationTimeout int32 `json:"dnsPropagationTimeout"` // DNS 传播超时时间(默认取决于提供商) - DnsTTL int32 `json:"dnsTTL"` // DNS TTL(默认取决于提供商) - DisableFollowCNAME bool `json:"disableFollowCNAME"` // 是否禁用 CNAME 跟随 - DisableARI bool `json:"disableARI"` // 是否禁用 ARI - SkipBeforeExpiryDays int32 `json:"skipBeforeExpiryDays"` // 证书到期前多少天前跳过续期(默认值:30) + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout"` // DNS 传播超时时间(零值取决于提供商的默认值) + DnsTTL int32 `json:"dnsTTL"` // DNS TTL(零值取决于提供商的默认值) + DisableFollowCNAME bool `json:"disableFollowCNAME"` // 是否关闭 CNAME 跟随 + DisableARI bool `json:"disableARI"` // 是否关闭 ARI + SkipBeforeExpiryDays int32 `json:"skipBeforeExpiryDays"` // 证书到期前多少天前跳过续期(零值将使用默认值 30) } type WorkflowNodeConfigForDeploy struct { diff --git a/internal/pkg/core/logger/builtin.go b/internal/pkg/core/logger/builtin.go index d3209d70..9787817d 100644 --- a/internal/pkg/core/logger/builtin.go +++ b/internal/pkg/core/logger/builtin.go @@ -5,6 +5,8 @@ import ( "fmt" "reflect" "strings" + + "github.com/usual2970/certimate/internal/pkg/utils/types" ) // 表示默认的日志记录器类型。 @@ -21,7 +23,7 @@ func (l *DefaultLogger) Logt(tag string, data ...any) { temp[0] = tag for i, v := range data { s := "" - if v == nil { + if types.IsNil(v) { s = "" } else { switch reflect.ValueOf(v).Kind() { diff --git a/internal/pkg/utils/types/types.go b/internal/pkg/utils/types/types.go index b88467b1..cd2b1602 100644 --- a/internal/pkg/utils/types/types.go +++ b/internal/pkg/utils/types/types.go @@ -3,6 +3,7 @@ import "reflect" // 判断对象是否为 nil。 +// 与直接使用 `obj == nil` 不同,该函数会正确判断接口类型对象的真实值是否为空。 // // 入参: // - value:待判断的对象。 diff --git a/internal/workflow/processor/processor.go b/internal/workflow/processor/processor.go index ec6a8da4..f011c152 100644 --- a/internal/workflow/processor/processor.go +++ b/internal/workflow/processor/processor.go @@ -42,23 +42,23 @@ func (w *workflowProcessor) processNode(ctx context.Context, node *domain.Workfl var runErr error var processor nodes.NodeProcessor for { - if current.Type != domain.WorkflowNodeTypeBranch && current.Type != domain.WorkflowNodeTypeExecuteResultBranch { - processor, runErr = nodes.GetProcessor(current) - if runErr != nil { - break - } - - runErr = processor.Run(ctx) - - log := processor.Log(ctx) - if log != nil { - w.logs = append(w.logs, *log) - } - if runErr != nil { - break - } + if current.Type == domain.WorkflowNodeTypeBranch || current.Type == domain.WorkflowNodeTypeExecuteResultBranch { + break + } + + processor, runErr = nodes.GetProcessor(current) + if runErr != nil { + break + } + + runErr = processor.Run(ctx) + log := processor.Log(ctx) + if log != nil { + w.logs = append(w.logs, *log) + } + if runErr != nil { + break } - break } if runErr != nil && current.Next != nil && current.Next.Type != domain.WorkflowNodeTypeExecuteResultBranch { @@ -70,8 +70,8 @@ func (w *workflowProcessor) processNode(ctx context.Context, node *domain.Workfl } else { current = current.Next } - } + return nil } @@ -79,10 +79,6 @@ func setContextWorkflowId(ctx context.Context, id string) context.Context { return context.WithValue(ctx, "workflow_id", id) } -func GetWorkflowId(ctx context.Context) string { - return ctx.Value("workflow_id").(string) -} - func getBranchByType(branches []domain.WorkflowNode, nodeType domain.WorkflowNodeType) *domain.WorkflowNode { for _, branch := range branches { if branch.Type == nodeType { diff --git a/ui/src/components/workflow/node/AddNode.tsx b/ui/src/components/workflow/node/AddNode.tsx index a4fa451f..0c1d07b8 100644 --- a/ui/src/components/workflow/node/AddNode.tsx +++ b/ui/src/components/workflow/node/AddNode.tsx @@ -26,13 +26,13 @@ const AddNode = ({ node, disabled }: AddNodeProps) => { return [ [WorkflowNodeType.Apply, "workflow_node.apply.label", ], [WorkflowNodeType.Deploy, "workflow_node.deploy.label", ], + [WorkflowNodeType.Notify, "workflow_node.notify.label", ], [WorkflowNodeType.Branch, "workflow_node.branch.label", ], [WorkflowNodeType.ExecuteResultBranch, "workflow_node.execute_result_branch.label", ], - [WorkflowNodeType.Notify, "workflow_node.notify.label", ], ] .filter(([type]) => { - if (node.type !== WorkflowNodeType.Apply && node.type !== WorkflowNodeType.Deploy && type === WorkflowNodeType.ExecuteResultBranch) { - return false; + if (node.type !== WorkflowNodeType.Apply && node.type !== WorkflowNodeType.Deploy && node.type !== WorkflowNodeType.Notify) { + return type !== WorkflowNodeType.ExecuteResultBranch; } return true; diff --git a/ui/src/components/workflow/node/ConditionNode.tsx b/ui/src/components/workflow/node/ConditionNode.tsx index f33b9bb5..d84e8550 100644 --- a/ui/src/components/workflow/node/ConditionNode.tsx +++ b/ui/src/components/workflow/node/ConditionNode.tsx @@ -16,6 +16,8 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP return ( <> } variant="text" />} /> } - overlayClassName="shadow-md" - overlayInnerStyle={{ padding: 0 }} placement="rightTop" > diff --git a/ui/src/components/workflow/node/ExecuteResultNode.tsx b/ui/src/components/workflow/node/ExecuteResultNode.tsx index a90b7970..b53b2a8c 100644 --- a/ui/src/components/workflow/node/ExecuteResultNode.tsx +++ b/ui/src/components/workflow/node/ExecuteResultNode.tsx @@ -1,9 +1,12 @@ import { memo } from "react"; import { useTranslation } from "react-i18next"; -import { MoreOutlined as MoreOutlinedIcon } from "@ant-design/icons"; -import { Button, Card, Popover } from "antd"; +import { + CheckCircleOutlined as CheckCircleOutlinedIcon, + CloseCircleOutlined as CloseCircleOutlinedIcon, + MoreOutlined as MoreOutlinedIcon, +} from "@ant-design/icons"; +import { Button, Card, Popover, theme } from "antd"; -import { CheckCircleIcon, XCircleIcon } from "lucide-react"; import { WorkflowNodeType } from "@/domain/workflow"; import AddNode from "./AddNode"; import SharedNode, { type SharedNodeProps } from "./_SharedNode"; @@ -16,9 +19,13 @@ export type ConditionNodeProps = SharedNodeProps & { const ExecuteResultNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeProps) => { const { t } = useTranslation(); + const { token: themeToken } = theme.useToken(); + return ( <> } variant="text" />} /> } - overlayClassName="shadow-md" - overlayInnerStyle={{ padding: 0 }} placement="rightTop" > @@ -38,12 +43,12 @@ const ExecuteResultNode = ({ node, disabled, branchId, branchIndex }: ConditionN
{node.type === WorkflowNodeType.ExecuteSuccess ? ( <> - +
{t("workflow_node.execute_success.label")}
) : ( <> - +
{t("workflow_node.execute_failure.label")}
)} diff --git a/ui/src/components/workflow/node/_SharedNode.tsx b/ui/src/components/workflow/node/_SharedNode.tsx index 868481ef..f2a4df60 100644 --- a/ui/src/components/workflow/node/_SharedNode.tsx +++ b/ui/src/components/workflow/node/_SharedNode.tsx @@ -64,6 +64,16 @@ type SharedNodeMenuProps = SharedNodeProps & { afterDelete?: () => void; }; +const isBranchingNode = (node: WorkflowNode) => { + return ( + node.type === WorkflowNodeType.Branch || + node.type === WorkflowNodeType.Condition || + node.type === WorkflowNodeType.ExecuteResultBranch || + node.type === WorkflowNodeType.ExecuteSuccess || + node.type === WorkflowNodeType.ExecuteFailure + ); +}; + const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterUpdate, afterDelete }: SharedNodeMenuProps) => { const { t } = useTranslation(); @@ -91,13 +101,7 @@ const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterU }; const handleDeleteClick = async () => { - if ( - node.type === WorkflowNodeType.Branch || - node.type === WorkflowNodeType.Condition || - node.type === WorkflowNodeType.ExecuteResultBranch || - node.type === WorkflowNodeType.ExecuteSuccess || - node.type === WorkflowNodeType.ExecuteFailure - ) { + if (isBranchingNode(node)) { await removeBranch(branchId!, branchIndex!); } else { await removeNode(node.id); @@ -116,19 +120,13 @@ const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterU { key: "rename", disabled: disabled, - label: - node.type === WorkflowNodeType.Branch || node.type === WorkflowNodeType.Condition - ? t("workflow_node.action.rename_branch") - : t("workflow_node.action.rename_node"), + label: isBranchingNode(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"), icon: , onClick: () => { nameRef.current = node.name; const dialog = modalApi.confirm({ - title: - node.type === WorkflowNodeType.Branch || node.type === WorkflowNodeType.Condition - ? t("workflow_node.action.rename_branch") - : t("workflow_node.action.rename_node"), + title: isBranchingNode(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"), content: (
, danger: true, onClick: handleDeleteClick, @@ -193,10 +184,10 @@ const SharedNodeBlock = ({ children, node, disabled, onClick }: SharedNodeBlockP return ( <> } variant="text" />} />} - overlayClassName="shadow-md" - overlayInnerStyle={{ padding: 0 }} placement="rightTop" > diff --git a/ui/src/domain/workflow.ts b/ui/src/domain/workflow.ts index 6d35d578..8c8e1f79 100644 --- a/ui/src/domain/workflow.ts +++ b/ui/src/domain/workflow.ts @@ -29,28 +29,28 @@ export type WorkflowTriggerType = (typeof WORKFLOW_TRIGGERS)[keyof typeof WORKFL export enum WorkflowNodeType { Start = "start", End = "end", - Branch = "branch", - ExecuteResultBranch = "execute_result_branch", - ExecuteSuccess = "execute_success", - ExecuteFailure = "execute_failure", - Condition = "condition", Apply = "apply", Deploy = "deploy", Notify = "notify", + Branch = "branch", + Condition = "condition", + ExecuteResultBranch = "execute_result_branch", + ExecuteSuccess = "execute_success", + ExecuteFailure = "execute_failure", Custom = "custom", } const workflowNodeTypeDefaultNames: Map = new Map([ [WorkflowNodeType.Start, i18n.t("workflow_node.start.label")], [WorkflowNodeType.End, i18n.t("workflow_node.end.label")], - [WorkflowNodeType.Branch, i18n.t("workflow_node.branch.label")], - [WorkflowNodeType.ExecuteResultBranch, i18n.t("workflow_node.execute_result_branch.label")], - [WorkflowNodeType.ExecuteSuccess, i18n.t("workflow_node.execute_success.label")], - [WorkflowNodeType.ExecuteFailure, i18n.t("workflow_node.execute_failure.label")], - [WorkflowNodeType.Condition, i18n.t("workflow_node.condition.label")], [WorkflowNodeType.Apply, i18n.t("workflow_node.apply.label")], [WorkflowNodeType.Deploy, i18n.t("workflow_node.deploy.label")], [WorkflowNodeType.Notify, i18n.t("workflow_node.notify.label")], + [WorkflowNodeType.Branch, i18n.t("workflow_node.branch.label")], + [WorkflowNodeType.Condition, i18n.t("workflow_node.condition.label")], + [WorkflowNodeType.ExecuteResultBranch, i18n.t("workflow_node.execute_result_branch.label")], + [WorkflowNodeType.ExecuteSuccess, i18n.t("workflow_node.execute_success.label")], + [WorkflowNodeType.ExecuteFailure, i18n.t("workflow_node.execute_failure.label")], [WorkflowNodeType.Custom, i18n.t("workflow_node.custom.title")], ]); diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index f6def82c..c9c7c8ba 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -1,5 +1,5 @@ { - "workflow_node.action.configure_node": "Configure", + "workflow_node.action.configure_node": "Configure node", "workflow_node.action.add_node": "Add node", "workflow_node.action.rename_node": "Rename node", "workflow_node.action.remove_node": "Delete node", @@ -379,13 +379,13 @@ "workflow_node.end.label": "End", - "workflow_node.branch.label": "Branch", + "workflow_node.branch.label": "Parallel branch", - "workflow_node.execute_result_branch.label": "Execute result branch", + "workflow_node.condition.label": "Branch", - "workflow_node.execute_success.label": "Execute success", + "workflow_node.execute_result_branch.label": "Execution result branch", - "workflow_node.execute_failure.label": "Execute failure", + "workflow_node.execute_success.label": "If the previous node succeeded ...", - "workflow_node.condition.label": "Condition" + "workflow_node.execute_failure.label": "If the previous node failed ..." } diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index aa82404e..c54656c8 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -3,7 +3,7 @@ "workflow_node.branch.add_node": "添加节点", "workflow_node.action.rename_node": "重命名", "workflow_node.action.remove_node": "删除节点", - "workflow_node.action.add_branch": "添加分支", + "workflow_node.action.add_branch": "添加并行分支", "workflow_node.action.rename_branch": "重命名", "workflow_node.action.remove_branch": "删除分支", @@ -379,13 +379,13 @@ "workflow_node.end.label": "结束", - "workflow_node.branch.label": "分支", + "workflow_node.branch.label": "并行分支", + + "workflow_node.condition.label": "分支", "workflow_node.execute_result_branch.label": "执行结果分支", - "workflow_node.execute_success.label": "执行成功", + "workflow_node.execute_success.label": "若前一节点执行成功…", - "workflow_node.execute_failure.label": "执行失败", - - "workflow_node.condition.label": "条件" + "workflow_node.execute_failure.label": "若前一节点执行失败…" } From c61b2d2d3f475ce545d70358135a53a4b50909e5 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 21 Jan 2025 21:41:25 +0800 Subject: [PATCH 2/9] fix: couldn't list expire soon certificates --- go.mod | 28 +++++------- go.sum | 72 ++++++++++++++---------------- internal/repository/certificate.go | 11 ++--- ui/src/api/certificates.ts | 2 +- 4 files changed, 53 insertions(+), 60 deletions(-) diff --git a/go.mod b/go.mod index b91c2e36..1567878b 100644 --- a/go.mod +++ b/go.mod @@ -18,14 +18,14 @@ require ( github.com/baidubce/bce-sdk-go v0.9.214 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.40 github.com/go-acme/lego/v4 v4.21.0 - github.com/go-resty/resty/v2 v2.16.3 + github.com/go-resty/resty/v2 v2.16.4 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.132 github.com/nikoksr/notify v1.3.0 github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 github.com/pkg/sftp v1.13.7 github.com/pocketbase/dbx v1.11.0 - github.com/pocketbase/pocketbase v0.24.3 + github.com/pocketbase/pocketbase v0.24.4 github.com/qiniu/go-sdk/v7 v7.25.2 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1084 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1084 @@ -73,7 +73,6 @@ require ( github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect @@ -92,9 +91,6 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect - modernc.org/gc/v3 v3.0.0-20250105121824-520be1a3aee6 // indirect - modernc.org/strutil v1.2.1 // indirect - modernc.org/token v1.1.0 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect @@ -115,22 +111,22 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2 v1.33.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect - github.com/aws/aws-sdk-go-v2/config v1.29.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.53 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.54 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.51 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.52 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.73.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.10 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.8 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 // indirect github.com/aws/smithy-go v1.22.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect @@ -192,8 +188,8 @@ require ( google.golang.org/protobuf v1.36.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.55.3 // indirect + modernc.org/libc v1.61.9 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.8.2 // indirect - modernc.org/sqlite v1.34.4 // indirect + modernc.org/sqlite v1.34.5 // indirect ) diff --git a/go.sum b/go.sum index 27e5c075..bbb65a6a 100644 --- a/go.sum +++ b/go.sum @@ -214,14 +214,14 @@ github.com/aws/aws-sdk-go-v2 v1.33.0 h1:Evgm4DI9imD81V0WwD+TN4DCwjUMdc94TrduMLbg github.com/aws/aws-sdk-go-v2 v1.33.0/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= -github.com/aws/aws-sdk-go-v2/config v1.29.0 h1:Vk/u4jof33or1qAQLdofpjKV7mQQT7DcUpnYx8kdmxY= -github.com/aws/aws-sdk-go-v2/config v1.29.0/go.mod h1:iXAZK3Gxvpq3tA+B9WaDYpZis7M8KFgdrDPMmHrgbJM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.53 h1:lwrVhiEDW5yXsuVKlFVUnR2R50zt2DklhOyeLETqDuE= -github.com/aws/aws-sdk-go-v2/credentials v1.17.53/go.mod h1:CkqM1bIw/xjEpBMhBnvqUXYZbpCFuj6dnCAyDk2AtAY= +github.com/aws/aws-sdk-go-v2/config v1.29.1 h1:JZhGawAyZ/EuJeBtbQYnaoftczcb2drR2Iq36Wgz4sQ= +github.com/aws/aws-sdk-go-v2/config v1.29.1/go.mod h1:7bR2YD5euaxBhzt2y/oDkt3uNRb6tjFp98GlTFueRwk= +github.com/aws/aws-sdk-go-v2/credentials v1.17.54 h1:4UmqeOqJPvdvASZWrKlhzpRahAulBfyTJQUaYy4+hEI= +github.com/aws/aws-sdk-go-v2/credentials v1.17.54/go.mod h1:RTdfo0P0hbbTxIhmQrOsC/PquBZGabEPnCaxxKRPSnI= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 h1:5grmdTdMsovn9kPZPI23Hhvp0ZyNm5cRO+IZFIYiAfw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24/go.mod h1:zqi7TVKTswH3Ozq28PkmBmgzG1tona7mo9G2IJg4Cis= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.51 h1:Q0FNHs6JTGuoBWNQycD5LRSf+/WVHWEl+FwJ0tEDZUE= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.51/go.mod h1:B9sW5/AD5bStKdTyUdz1xWRKOwnyUwJ4eJ4olQBtZo0= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.52 h1:6kI83R98XOnnyzHv9g9KTYXFawMyeQq8NeEERWMAwJk= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.52/go.mod h1:Juj7unpf3CIrWpEyJZhRJ6rJl9IYX7Hd8HOlwaZq/LE= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 h1:igORFSiH3bfq4lxKFkTSYDhJEUCYo6C8VKiWJjYwQuQ= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28/go.mod h1:3So8EA/aAYm36L7XIvCVwLa0s5N0P7o2b1oqnx/2R4g= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 h1:1mOW9zAUMhTSrMDssEHS/ajx8JcAj/IcftzcmNlmVLI= @@ -233,22 +233,22 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28/go.mod h1:pyaOYEdp1MJWgtXLy6q8 github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.1 h1:mJ9FRktB8v1Ihpqwfk0AWvYEd0FgQtLsshc2Qb2TVc8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.1/go.mod h1:dIW8puxSbYLSPv/ju0d9A3CpwXdtqvJtYKDMVmPLOWE= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2 h1:e6um6+DWYQP1XCa+E9YVtG/9v1qk5lyAOelMOVwSyO8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2/go.mod h1:dIW8puxSbYLSPv/ju0d9A3CpwXdtqvJtYKDMVmPLOWE= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 h1:TQmKDyETFGiXVhZfQ/I0cCFziqqX58pi4tKJGYGFSz0= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9/go.mod h1:HVLPK2iHQBUx7HfZeOQSEu3v2ubZaAY2YPbAm5/WUyY= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9 h1:2aInXbh02XsbO0KobPGMNXyv2QP73VDKsWPNJARj/+4= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9/go.mod h1:dgXS1i+HgWnYkPXqNoPIPKeUsUUYHaUbThC90aDnNiE= github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1 h1:njgAP7Rtt4DGdTGFPhJ4gaZXCD1CDj/SZDa5W4ZgSTs= github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1/go.mod h1:TN4PcCL0lvqmYcv+AV8iZFC4Sd0FM06QDaoBXrFEftU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.73.1 h1:OzmyfYGiMCOIAq5pa0KWcaZoA9F8FqajOJevh+hhFdY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.73.1/go.mod h1:K+0a0kWDHAUXBH8GvYGS3cQRwIuRjO9bMWUz6vpNCaU= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.10 h1:DyZUj3xSw3FR3TXSwDhPhuZkkT14QHBiacdbUVcD0Dg= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.10/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9 h1:I1TsPEs34vbpOnR81GIcAq4/3Ud+jRHVGwx6qLQUHLs= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9/go.mod h1:Fzsj6lZEb8AkTE5S68OhcbBqeWPsR8RnGuKPr8Todl8= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.8 h1:pqEJQtlKWvnv3B6VRt60ZmsHy3SotlEBvfUBPB1KVcM= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.8/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2 h1:F3h8VYq9ZLBXYurmwrT8W0SPhgCcU0q+0WZJfT1dFt0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2/go.mod h1:jGJ/v7FIi7Ys9t54tmEFnrxuaWeJLpwNgKp2DXAVhOU= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 h1:kuIyu4fTT38Kj7YCC7ouNbVZSSpqkZ+LzIfhCr6Dg+I= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.11/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 h1:l+dgv/64iVlQ3WsBbnn+JSbkj01jIi+SM0wYsj3y/hY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10/go.mod h1:Fzsj6lZEb8AkTE5S68OhcbBqeWPsR8RnGuKPr8Todl8= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 h1:BRVDbewN6VZcwr+FBOszDKvYeXY1kJ+GGMCcpghlw0U= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.9/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= @@ -393,8 +393,8 @@ github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.7.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk= -github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E= -github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= +github.com/go-resty/resty/v2 v2.16.4 h1:81IjtszQKwbz7dot4LLYGwhJNUsNwECD2O7nru5q60E= +github.com/go-resty/resty/v2 v2.16.4/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= @@ -542,8 +542,6 @@ github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= @@ -723,8 +721,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU= github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs= -github.com/pocketbase/pocketbase v0.24.3 h1:WUrzW11ijCySlDsVRHon3HXdtiratWv+ODK26/k6cI8= -github.com/pocketbase/pocketbase v0.24.3/go.mod h1:EfXV/8RUY76jA6g1RPNHjOuW7wTd2bz0QlvAI/RU8YY= +github.com/pocketbase/pocketbase v0.24.4 h1:kw/c23HccoxMV/19U9QlDcvNJgQ66vlUrxGQDZicWKM= +github.com/pocketbase/pocketbase v0.24.4/go.mod h1:EfXV/8RUY76jA6g1RPNHjOuW7wTd2bz0QlvAI/RU8YY= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1385,29 +1383,27 @@ k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8X k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= -modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= -modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= +modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0= +modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.23.13 h1:PFiaemQwE/jdwi8XEHyEV+qYWoIuikLP3T4rvDeJb00= +modernc.org/ccgo/v4 v4.23.13/go.mod h1:vdN4h2WR5aEoNondUx26K7G8X+nuBscYnAEWSRmN2/0= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= -modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= -modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= -modernc.org/gc/v3 v3.0.0-20250105121824-520be1a3aee6 h1:JoKwHjIFumiKrjMbp1cNbC5E9UyCgA/ZcID0xOWQ2N8= -modernc.org/gc/v3 v3.0.0-20250105121824-520be1a3aee6/go.mod h1:LG5UO1Ran4OO0JRKz2oNiXhR5nNrgz0PzH7UKhz0aMU= -modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= -modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/gc/v2 v2.6.1 h1:+Qf6xdG8l7B27TQ8D8lw/iFMUj1RXRBOuMUWziJOsk8= +modernc.org/gc/v2 v2.6.1/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/libc v1.61.9 h1:PLSBXVkifXGELtJ5BOnBUyAHr7lsatNwFU/RRo4kfJM= +modernc.org/libc v1.61.9/go.mod h1:61xrnzk/aR8gr5bR7Uj/lLFLuXu2/zMpIjcry63Eumk= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI= modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.34.4 h1:sjdARozcL5KJBvYQvLlZEmctRgW9xqIZc2ncN7PU0P8= -modernc.org/sqlite v1.34.4/go.mod h1:3QQFCG2SEMtc2nv+Wq4cQCH7Hjcg+p/RMlS1XK+zwbk= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g= +modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/internal/repository/certificate.go b/internal/repository/certificate.go index 6aee6add..5e1a7f8d 100644 --- a/internal/repository/certificate.go +++ b/internal/repository/certificate.go @@ -19,11 +19,11 @@ func NewCertificateRepository() *CertificateRepository { } func (r *CertificateRepository) ListExpireSoon(ctx context.Context) ([]*domain.Certificate, error) { - records, err := app.GetApp().FindRecordsByFilter( + records, err := app.GetApp().FindAllRecords( domain.CollectionNameCertificate, - "expireAt>DATETIME('now') && expireAtDATETIME('now')"), + dbx.NewExp("expireAt { const pb = getPocketBase(); - const resp = await pb.send(`/api/certificates/${encodeURIComponent(id)}/archive`, { + const resp = await pb.send>(`/api/certificates/${encodeURIComponent(id)}/archive`, { method: "POST", headers: { "Content-Type": "application/json", From 8dc86209df06dfd5cedc5f430e8727ea52930cb8 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 21 Jan 2025 23:11:48 +0800 Subject: [PATCH 3/9] feat: support removing workflow runs --- internal/pkg/utils/certs/transformer.go | 23 ++------ ui/src/components/workflow/WorkflowRuns.tsx | 54 +++++++++++++++++-- ui/src/i18n/locales/en/nls.workflow.runs.json | 4 ++ ui/src/i18n/locales/zh/nls.workflow.runs.json | 4 ++ ui/src/pages/workflows/WorkflowList.tsx | 41 ++++++-------- ui/src/repository/workflowRun.ts | 4 ++ 6 files changed, 82 insertions(+), 48 deletions(-) diff --git a/internal/pkg/utils/certs/transformer.go b/internal/pkg/utils/certs/transformer.go index c3575b3e..cd1a2039 100644 --- a/internal/pkg/utils/certs/transformer.go +++ b/internal/pkg/utils/certs/transformer.go @@ -2,12 +2,11 @@ import ( "bytes" - "crypto/ecdsa" - "crypto/rsa" "encoding/pem" "errors" "time" + "github.com/go-acme/lego/v4/certcrypto" "github.com/pavlo-v-chernykh/keystore-go/v4" "software.sslmate.com/src/go-pkcs12" ) @@ -28,23 +27,9 @@ func TransformCertificateFromPEMToPFX(certPem string, privkeyPem string, pfxPass return nil, err } - var privkey interface{} - switch cert.PublicKey.(type) { - case *rsa.PublicKey: - { - privkey, err = ParsePKCS1PrivateKeyFromPEM(privkeyPem) - if err != nil { - return nil, err - } - } - - case *ecdsa.PublicKey: - { - privkey, err = ParseECPrivateKeyFromPEM(privkeyPem) - if err != nil { - return nil, err - } - } + privkey, err := certcrypto.ParsePEMPrivateKey([]byte(privkeyPem)) + if err != nil { + return nil, err } pfxData, err := pkcs12.LegacyRC2.Encode(privkey, cert, nil, pfxPassword) diff --git a/ui/src/components/workflow/WorkflowRuns.tsx b/ui/src/components/workflow/WorkflowRuns.tsx index ef9fd5ea..493f6396 100644 --- a/ui/src/components/workflow/WorkflowRuns.tsx +++ b/ui/src/components/workflow/WorkflowRuns.tsx @@ -4,17 +4,18 @@ import { CheckCircleOutlined as CheckCircleOutlinedIcon, ClockCircleOutlined as ClockCircleOutlinedIcon, CloseCircleOutlined as CloseCircleOutlinedIcon, + DeleteOutlined as DeleteOutlinedIcon, SelectOutlined as SelectOutlinedIcon, SyncOutlined as SyncOutlinedIcon, } from "@ant-design/icons"; import { useRequest } from "ahooks"; -import { Button, Empty, Table, type TableProps, Tag, notification } from "antd"; +import { Button, Empty, Modal, Table, type TableProps, Tag, Tooltip, notification } from "antd"; import dayjs from "dayjs"; import { ClientResponseError } from "pocketbase"; import { WORKFLOW_TRIGGERS } from "@/domain/workflow"; import { WORKFLOW_RUN_STATUSES, type WorkflowRunModel } from "@/domain/workflowRun"; -import { list as listWorkflowRuns } from "@/repository/workflowRun"; +import { list as listWorkflowRuns, remove as removeWorkflowRun } from "@/repository/workflowRun"; import { getErrMsg } from "@/utils/error"; import WorkflowRunDetailDrawer from "./WorkflowRunDetailDrawer"; @@ -27,6 +28,7 @@ export type WorkflowRunsProps = { const WorkflowRuns = ({ className, style, workflowId }: WorkflowRunsProps) => { const { t } = useTranslation(); + const [modalApi, ModelContextHolder] = Modal.useModal(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); const tableColumns: TableProps["columns"] = [ @@ -118,7 +120,27 @@ const WorkflowRuns = ({ className, style, workflowId }: WorkflowRunsProps) => { width: 120, render: (_, record) => ( - } variant="text" />} /> + + - - - diff --git a/ui/src/pages/workflows/WorkflowList.tsx b/ui/src/pages/workflows/WorkflowList.tsx index 99eebbbd..28b776e7 100644 --- a/ui/src/pages/workflows/WorkflowList.tsx +++ b/ui/src/pages/workflows/WorkflowList.tsx @@ -7,6 +7,7 @@ import { CloseCircleOutlined as CloseCircleOutlinedIcon, DeleteOutlined as DeleteOutlinedIcon, EditOutlined as EditOutlinedIcon, + PauseCircleOutlined as PauseCircleOutlinedIcon, PlusOutlined as PlusOutlinedIcon, SyncOutlined as SyncOutlinedIcon, } from "@ant-design/icons"; @@ -168,6 +169,8 @@ const WorkflowList = () => { icon = ; } else if (record.lastRunStatus === WORKFLOW_RUN_STATUSES.FAILED) { icon = ; + } else if (record.lastRunStatus === WORKFLOW_RUN_STATUSES.CANCELED) { + icon = ; } return ( From 7e0f575e0a15110c0ef5ff7b32cf36360394d380 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 22 Jan 2025 03:44:54 +0800 Subject: [PATCH 5/9] feat(ui): jump to workflow detail page in dashboard --- ui/src/i18n/locales/zh/nls.workflow.runs.json | 2 +- ui/src/pages/dashboard/Dashboard.tsx | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/ui/src/i18n/locales/zh/nls.workflow.runs.json b/ui/src/i18n/locales/zh/nls.workflow.runs.json index 0263e072..13a7f704 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.runs.json +++ b/ui/src/i18n/locales/zh/nls.workflow.runs.json @@ -1,7 +1,7 @@ { "workflow_run.action.edit": "查看详情", "workflow_run.action.delete": "删除执行历史", - "workflow_run.action.delete.confirm": "确定要删除此执行历史吗?", + "workflow_run.action.delete.confirm": "确定要删除此执行历史吗?此操作仅清除日志,不会影响各节点的执行结果和签发的证书。", "workflow_run.props.id": "ID", "workflow_run.props.status": "状态", diff --git a/ui/src/pages/dashboard/Dashboard.tsx b/ui/src/pages/dashboard/Dashboard.tsx index c25f130e..d80c8c10 100644 --- a/ui/src/pages/dashboard/Dashboard.tsx +++ b/ui/src/pages/dashboard/Dashboard.tsx @@ -85,14 +85,22 @@ const Dashboard = () => { key: "name", title: t("workflow.props.name"), ellipsis: true, - render: (_, record) => ( - - {record.expand?.workflowId?.name} - - {record.expand?.workflowId?.description} - - - ), + render: (_, record) => { + const workflow = record.expand?.workflowId; + return ( + { + if (workflow) { + navigate(`/workflows/${workflow.id}`); + } + }} + > + {workflow?.name ?? {t(`#${record.workflowId}`)}} + + ); + }, }, { key: "status", From bee4ba10cbb15a7d09fd6c3cef56fde04fc644bc Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 22 Jan 2025 03:48:58 +0800 Subject: [PATCH 6/9] feat: generate run record at the beginning of the workflow execution --- internal/repository/workflow.go | 45 +++++++++++++++++++++++++-------- internal/workflow/service.go | 19 +++++++++----- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/internal/repository/workflow.go b/internal/repository/workflow.go index ac9b3e9f..edf7cf7f 100644 --- a/internal/repository/workflow.go +++ b/internal/repository/workflow.go @@ -55,10 +55,10 @@ func (r *WorkflowRepository) GetById(ctx context.Context, id string) (*domain.Wo return r.castRecordToModel(record) } -func (r *WorkflowRepository) Save(ctx context.Context, workflow *domain.Workflow) error { +func (r *WorkflowRepository) Save(ctx context.Context, workflow *domain.Workflow) (*domain.Workflow, error) { collection, err := app.GetApp().FindCollectionByNameOrId(domain.CollectionNameWorkflow) if err != nil { - return err + return workflow, err } var record *core.Record @@ -68,9 +68,9 @@ func (r *WorkflowRepository) Save(ctx context.Context, workflow *domain.Workflow record, err = app.GetApp().FindRecordById(domain.CollectionNameWorkflow, workflow.Id) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return domain.ErrRecordNotFound + return workflow, domain.ErrRecordNotFound } - return err + return workflow, err } } @@ -86,18 +86,36 @@ func (r *WorkflowRepository) Save(ctx context.Context, workflow *domain.Workflow record.Set("lastRunStatus", string(workflow.LastRunStatus)) record.Set("lastRunTime", workflow.LastRunTime) - return app.GetApp().Save(record) + if err := app.GetApp().Save(record); err != nil { + return workflow, err + } + + workflow.Id = record.Id + workflow.CreatedAt = record.GetDateTime("created").Time() + workflow.UpdatedAt = record.GetDateTime("updated").Time() + return workflow, nil } -func (r *WorkflowRepository) SaveRun(ctx context.Context, workflowRun *domain.WorkflowRun) error { +func (r *WorkflowRepository) SaveRun(ctx context.Context, workflowRun *domain.WorkflowRun) (*domain.WorkflowRun, error) { collection, err := app.GetApp().FindCollectionByNameOrId(domain.CollectionNameWorkflowRun) if err != nil { - return err + return workflowRun, err + } + + var workflowRunRecord *core.Record + if workflowRun.Id == "" { + workflowRunRecord = core.NewRecord(collection) + } else { + workflowRunRecord, err = app.GetApp().FindRecordById(domain.CollectionNameWorkflowRun, workflowRun.Id) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return workflowRun, err + } + workflowRunRecord = core.NewRecord(collection) + } } err = app.GetApp().RunInTransaction(func(txApp core.App) error { - workflowRunRecord := core.NewRecord(collection) - workflowRunRecord.Id = workflowRun.Id workflowRunRecord.Set("workflowId", workflowRun.WorkflowId) workflowRunRecord.Set("trigger", string(workflowRun.Trigger)) workflowRunRecord.Set("status", string(workflowRun.Status)) @@ -115,6 +133,7 @@ func (r *WorkflowRepository) SaveRun(ctx context.Context, workflowRun *domain.Wo return err } + workflowRecord.IgnoreUnchangedFields(true) workflowRecord.Set("lastRunId", workflowRunRecord.Id) workflowRecord.Set("lastRunStatus", workflowRunRecord.GetString("status")) workflowRecord.Set("lastRunTime", workflowRunRecord.GetString("startedAt")) @@ -123,13 +142,17 @@ func (r *WorkflowRepository) SaveRun(ctx context.Context, workflowRun *domain.Wo return err } + workflowRun.Id = workflowRunRecord.Id + workflowRun.CreatedAt = workflowRunRecord.GetDateTime("created").Time() + workflowRun.UpdatedAt = workflowRunRecord.GetDateTime("updated").Time() + return nil }) if err != nil { - return err + return workflowRun, err } - return nil + return workflowRun, nil } func (r *WorkflowRepository) castRecordToModel(record *core.Record) (*domain.Workflow, error) { diff --git a/internal/workflow/service.go b/internal/workflow/service.go index 5a34805e..25564ad8 100644 --- a/internal/workflow/service.go +++ b/internal/workflow/service.go @@ -23,8 +23,8 @@ type workflowRunData struct { type workflowRepository interface { ListEnabledAuto(ctx context.Context) ([]*domain.Workflow, error) GetById(ctx context.Context, id string) (*domain.Workflow, error) - Save(ctx context.Context, workflow *domain.Workflow) error - SaveRun(ctx context.Context, workflowRun *domain.WorkflowRun) error + Save(ctx context.Context, workflow *domain.Workflow) (*domain.Workflow, error) + SaveRun(ctx context.Context, workflowRun *domain.WorkflowRun) (*domain.WorkflowRun, error) } type WorkflowService struct { @@ -88,9 +88,10 @@ func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) err workflow.LastRunTime = time.Now() workflow.LastRunStatus = domain.WorkflowRunStatusTypePending workflow.LastRunId = "" - - if err := s.repo.Save(ctx, workflow); err != nil { + if resp, err := s.repo.Save(ctx, workflow); err != nil { return err + } else { + workflow = resp } s.ch <- &workflowRunData{ @@ -122,13 +123,17 @@ func (s *WorkflowService) run(ctx context.Context) { func (s *WorkflowService) runWithData(ctx context.Context, runData *workflowRunData) error { workflow := runData.Workflow - run := &domain.WorkflowRun{ WorkflowId: workflow.Id, Status: domain.WorkflowRunStatusTypeRunning, Trigger: runData.RunTrigger, StartedAt: time.Now(), } + if resp, err := s.repo.SaveRun(ctx, run); err != nil { + return err + } else { + run = resp + } processor := processor.NewWorkflowProcessor(workflow) if runErr := processor.Run(ctx); runErr != nil { @@ -136,7 +141,7 @@ func (s *WorkflowService) runWithData(ctx context.Context, runData *workflowRunD run.EndedAt = time.Now() run.Logs = processor.GetRunLogs() run.Error = runErr.Error() - if err := s.repo.SaveRun(ctx, run); err != nil { + if _, err := s.repo.SaveRun(ctx, run); err != nil { app.GetLogger().Error("failed to save workflow run", "err", err) } @@ -151,7 +156,7 @@ func (s *WorkflowService) runWithData(ctx context.Context, runData *workflowRunD } else { run.Status = domain.WorkflowRunStatusTypeFailed } - if err := s.repo.SaveRun(ctx, run); err != nil { + if _, err := s.repo.SaveRun(ctx, run); err != nil { app.GetLogger().Error("failed to save workflow run", "err", err) return err } From 0f945881a172f0a57c775e82e3f1d5e04aef28d7 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 22 Jan 2025 04:13:16 +0800 Subject: [PATCH 7/9] feat: cancel workflow run --- internal/domain/dtos/workflow.go | 7 +- internal/rest/handlers/certificate.go | 4 +- internal/rest/handlers/workflow.go | 24 +++-- internal/workflow/event.go | 2 +- internal/workflow/service.go | 10 ++- ui/src/api/certificates.ts | 4 +- ui/src/api/workflows.ts | 21 ++++- ui/src/components/workflow/WorkflowRuns.tsx | 88 +++++++++++++------ ui/src/i18n/locales/en/nls.workflow.runs.json | 6 +- ui/src/i18n/locales/zh/nls.workflow.runs.json | 8 +- ui/src/pages/workflows/WorkflowDetail.tsx | 4 +- 11 files changed, 130 insertions(+), 48 deletions(-) diff --git a/internal/domain/dtos/workflow.go b/internal/domain/dtos/workflow.go index 3a760971..9d1f5781 100644 --- a/internal/domain/dtos/workflow.go +++ b/internal/domain/dtos/workflow.go @@ -2,7 +2,12 @@ import "github.com/usual2970/certimate/internal/domain" -type WorkflowRunReq struct { +type WorkflowStartRunReq struct { WorkflowId string `json:"-"` Trigger domain.WorkflowTriggerType `json:"trigger"` } + +type WorkflowCancelRunReq struct { + WorkflowId string `json:"-"` + RunId string `json:"-"` +} diff --git a/internal/rest/handlers/certificate.go b/internal/rest/handlers/certificate.go index 26788de6..5f240bb0 100644 --- a/internal/rest/handlers/certificate.go +++ b/internal/rest/handlers/certificate.go @@ -24,12 +24,12 @@ func NewCertificateHandler(router *router.RouterGroup[*core.RequestEvent], servi } group := router.Group("/certificates") - group.POST("/{id}/archive", handler.run) + group.POST("/{certificateId}/archive", handler.run) } func (handler *CertificateHandler) run(e *core.RequestEvent) error { req := &dtos.CertificateArchiveFileReq{} - req.CertificateId = e.Request.PathValue("id") + req.CertificateId = e.Request.PathValue("certificateId") if err := e.BindBody(req); err != nil { return resp.Err(e, err) } diff --git a/internal/rest/handlers/workflow.go b/internal/rest/handlers/workflow.go index b1ba70e4..83b3302b 100644 --- a/internal/rest/handlers/workflow.go +++ b/internal/rest/handlers/workflow.go @@ -11,7 +11,8 @@ import ( ) type workflowService interface { - Run(ctx context.Context, req *dtos.WorkflowRunReq) error + StartRun(ctx context.Context, req *dtos.WorkflowStartRunReq) error + CancelRun(ctx context.Context, req *dtos.WorkflowCancelRunReq) error Stop(ctx context.Context) } @@ -25,17 +26,30 @@ func NewWorkflowHandler(router *router.RouterGroup[*core.RequestEvent], service } group := router.Group("/workflows") - group.POST("/{id}/run", handler.run) + group.POST("/{workflowId}/runs", handler.run) + group.POST("/{workflowId}/runs/{runId}/cancel", handler.cancel) } func (handler *WorkflowHandler) run(e *core.RequestEvent) error { - req := &dtos.WorkflowRunReq{} - req.WorkflowId = e.Request.PathValue("id") + req := &dtos.WorkflowStartRunReq{} + req.WorkflowId = e.Request.PathValue("workflowId") if err := e.BindBody(req); err != nil { return resp.Err(e, err) } - if err := handler.service.Run(e.Request.Context(), req); err != nil { + if err := handler.service.StartRun(e.Request.Context(), req); err != nil { + return resp.Err(e, err) + } + + return resp.Ok(e, nil) +} + +func (handler *WorkflowHandler) cancel(e *core.RequestEvent) error { + req := &dtos.WorkflowCancelRunReq{} + req.WorkflowId = e.Request.PathValue("workflowId") + req.RunId = e.Request.PathValue("runId") + + if err := handler.service.CancelRun(e.Request.Context(), req); err != nil { return resp.Err(e, err) } diff --git a/internal/workflow/event.go b/internal/workflow/event.go index 9bb3b310..f8117dbc 100644 --- a/internal/workflow/event.go +++ b/internal/workflow/event.go @@ -65,7 +65,7 @@ func onWorkflowRecordCreateOrUpdate(ctx context.Context, record *core.Record) er // 反之,重新添加定时任务 err := scheduler.Add(fmt.Sprintf("workflow#%s", workflowId), record.GetString("triggerCron"), func() { - NewWorkflowService(repository.NewWorkflowRepository()).Run(ctx, &dtos.WorkflowRunReq{ + NewWorkflowService(repository.NewWorkflowRepository()).StartRun(ctx, &dtos.WorkflowStartRunReq{ WorkflowId: workflowId, Trigger: domain.WorkflowTriggerTypeAuto, }) diff --git a/internal/workflow/service.go b/internal/workflow/service.go index 25564ad8..1f103d72 100644 --- a/internal/workflow/service.go +++ b/internal/workflow/service.go @@ -60,7 +60,7 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error { scheduler := app.GetScheduler() for _, workflow := range workflows { err := scheduler.Add(fmt.Sprintf("workflow#%s", workflow.Id), workflow.TriggerCron, func() { - s.Run(ctx, &dtos.WorkflowRunReq{ + s.StartRun(ctx, &dtos.WorkflowStartRunReq{ WorkflowId: workflow.Id, Trigger: domain.WorkflowTriggerTypeAuto, }) @@ -74,7 +74,7 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error { return nil } -func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) error { +func (s *WorkflowService) StartRun(ctx context.Context, req *dtos.WorkflowStartRunReq) error { workflow, err := s.repo.GetById(ctx, req.WorkflowId) if err != nil { app.GetLogger().Error("failed to get workflow", "id", req.WorkflowId, "err", err) @@ -102,6 +102,12 @@ func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) err return nil } +func (s *WorkflowService) CancelRun(ctx context.Context, req *dtos.WorkflowCancelRunReq) error { + // TODO: 取消运行,防止因为某些原因意外挂起(如进程被杀死)导致工作流一直处于 running 状态无法重新运行 + + return nil +} + func (s *WorkflowService) Stop(ctx context.Context) { s.cancel() s.wg.Wait() diff --git a/ui/src/api/certificates.ts b/ui/src/api/certificates.ts index 4b566ecf..71ef30aa 100644 --- a/ui/src/api/certificates.ts +++ b/ui/src/api/certificates.ts @@ -3,10 +3,10 @@ import { ClientResponseError } from "pocketbase"; import { type CertificateFormatType } from "@/domain/certificate"; import { getPocketBase } from "@/repository/_pocketbase"; -export const archive = async (id: string, format?: CertificateFormatType) => { +export const archive = async (certificateId: string, format?: CertificateFormatType) => { const pb = getPocketBase(); - const resp = await pb.send>(`/api/certificates/${encodeURIComponent(id)}/archive`, { + const resp = await pb.send>(`/api/certificates/${encodeURIComponent(certificateId)}/archive`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/ui/src/api/workflows.ts b/ui/src/api/workflows.ts index 4ad9e2d3..6a9d69f6 100644 --- a/ui/src/api/workflows.ts +++ b/ui/src/api/workflows.ts @@ -3,10 +3,10 @@ import { ClientResponseError } from "pocketbase"; import { WORKFLOW_TRIGGERS } from "@/domain/workflow"; import { getPocketBase } from "@/repository/_pocketbase"; -export const run = async (id: string) => { +export const startRun = async (workflowId: string) => { const pb = getPocketBase(); - const resp = await pb.send(`/api/workflows/${encodeURIComponent(id)}/run`, { + const resp = await pb.send(`/api/workflows/${encodeURIComponent(workflowId)}/runs`, { method: "POST", headers: { "Content-Type": "application/json", @@ -22,3 +22,20 @@ export const run = async (id: string) => { return resp; }; + +export const cancelRun = async (workflowId: string, runId: string) => { + const pb = getPocketBase(); + + const resp = await pb.send(`/api/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/cancel`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + }); + + if (resp.code != 0) { + throw new ClientResponseError({ status: resp.code, response: resp, data: {} }); + } + + return resp; +}; diff --git a/ui/src/components/workflow/WorkflowRuns.tsx b/ui/src/components/workflow/WorkflowRuns.tsx index 788bf1e0..c90ab5a3 100644 --- a/ui/src/components/workflow/WorkflowRuns.tsx +++ b/ui/src/components/workflow/WorkflowRuns.tsx @@ -6,6 +6,7 @@ import { CloseCircleOutlined as CloseCircleOutlinedIcon, DeleteOutlined as DeleteOutlinedIcon, PauseCircleOutlined as PauseCircleOutlinedIcon, + PauseOutlined as PauseOutlinedIcon, SelectOutlined as SelectOutlinedIcon, SyncOutlined as SyncOutlinedIcon, } from "@ant-design/icons"; @@ -14,6 +15,7 @@ import { Button, Empty, Modal, Table, type TableProps, Tag, Tooltip, notificatio import dayjs from "dayjs"; import { ClientResponseError } from "pocketbase"; +import { cancelRun as cancelWorkflowRun } from "@/api/workflows"; import { WORKFLOW_TRIGGERS } from "@/domain/workflow"; import { WORKFLOW_RUN_STATUSES, type WorkflowRunModel } from "@/domain/workflowRun"; import { list as listWorkflowRuns, remove as removeWorkflowRun } from "@/repository/workflowRun"; @@ -125,35 +127,51 @@ const WorkflowRuns = ({ className, style, workflowId }: WorkflowRunsProps) => { align: "end", fixed: "right", width: 120, - render: (_, record) => ( - - -
+ +
+ ); +}; + +export default WorkflowElementsContainer; diff --git a/ui/src/pages/ConsoleLayout.tsx b/ui/src/pages/ConsoleLayout.tsx index a370d46c..4fbaf492 100644 --- a/ui/src/pages/ConsoleLayout.tsx +++ b/ui/src/pages/ConsoleLayout.tsx @@ -41,7 +41,7 @@ const ConsoleLayout = () => { } return ( - +
@@ -53,8 +53,8 @@ const ConsoleLayout = () => {
- - + +
} size="large" />} /> @@ -76,7 +76,7 @@ const ConsoleLayout = () => {
- + diff --git a/ui/src/pages/workflows/WorkflowDetail.tsx b/ui/src/pages/workflows/WorkflowDetail.tsx index 8df424b0..f85394d1 100644 --- a/ui/src/pages/workflows/WorkflowDetail.tsx +++ b/ui/src/pages/workflows/WorkflowDetail.tsx @@ -7,10 +7,7 @@ import { DeleteOutlined as DeleteOutlinedIcon, DownOutlined as DownOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon, - ExpandOutlined as ExpandOutlinedIcon, HistoryOutlined as HistoryOutlinedIcon, - MinusOutlined as MinusOutlinedIcon, - PlusOutlined as PlusOutlinedIcon, UndoOutlined as UndoOutlinedIcon, } from "@ant-design/icons"; import { PageHeader } from "@ant-design/pro-components"; @@ -22,7 +19,7 @@ import { z } from "zod"; import { startRun as startWorkflowRun } from "@/api/workflows"; import ModalForm from "@/components/ModalForm"; import Show from "@/components/Show"; -import WorkflowElements from "@/components/workflow/WorkflowElements"; +import WorkflowElementsContainer from "@/components/workflow/WorkflowElementsContainer"; import WorkflowRuns from "@/components/workflow/WorkflowRuns"; import { isAllNodesValidated } from "@/domain/workflow"; import { WORKFLOW_RUN_STATUSES } from "@/domain/workflowRun"; @@ -40,8 +37,6 @@ const WorkflowDetail = () => { const [modalApi, ModalContextHolder] = Modal.useModal(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); - const [scale, setScale] = useState(1); - const { id: workflowId } = useParams(); const { workflow, initialized, ...workflowState } = useWorkflowStore( useZustandShallowSelector(["workflow", "initialized", "init", "destroy", "setEnabled", "release", "discard"]) @@ -58,15 +53,12 @@ const WorkflowDetail = () => { const [tabValue, setTabValue] = useState<"orchestration" | "runs">("orchestration"); const [isRunning, setIsRunning] = useState(false); + const lastRunStatus = useMemo(() => workflow.lastRunStatus, [workflow]); const [allowDiscard, setAllowDiscard] = useState(false); const [allowRelease, setAllowRelease] = useState(false); const [allowRun, setAllowRun] = useState(false); - const lastRunStatus = useMemo(() => { - return workflow.lastRunStatus; - }, [workflow]); - useEffect(() => { setIsRunning(lastRunStatus == WORKFLOW_RUN_STATUSES.RUNNING); }, [lastRunStatus]); @@ -206,123 +198,129 @@ const WorkflowDetail = () => { }; return ( -
+
{MessageContextHolder} {ModalContextHolder} {NotificationContextHolder} - - {t("common.button.edit")}} />, +
+ + {t("common.button.edit")}} />, - , + , - , - onClick: () => { - handleDeleteClick(); - }, - }, - ], - }} - trigger={["click"]} - > - - , - ] - : [] - } - > - {workflow.description} - }, - { key: "runs", label: t("workflow.detail.runs.tab"), icon: }, - ]} - renderTabBar={(props, DefaultTabBar) => } - tabBarStyle={{ border: "none" }} - onChange={(key) => setTabValue(key as typeof tabValue)} - /> - - - -
- - -
-
-
- - {t("workflow.detail.orchestration.draft.alert")}
} type="warning" /> - -
-
- - - - - - - , - onClick: handleDiscardClick, + , + onClick: () => { + handleDeleteClick(); }, - ], - }} - trigger={["click"]} - > -
-
-
-
- -
- -
-
- - - - - + }, + ], + }} + trigger={["click"]} + > + + , + ] + : [] + } + > + {workflow.description} + }, + { key: "runs", label: t("workflow.detail.runs.tab"), icon: }, + ]} + renderTabBar={(props, DefaultTabBar) => } + tabBarStyle={{ border: "none" }} + onChange={(key) => setTabValue(key as typeof tabValue)} + /> +
+ + +
+ +
+
+ + {t("workflow.detail.orchestration.draft.alert")}
} type="warning" /> + +
+
+ + + + + + + , + onClick: handleDiscardClick, + }, + ], + }} + trigger={["click"]} + > +
+
+ + +
+
+ + + +
+ + + +
+
); }; diff --git a/ui/src/pages/workflows/WorkflowNew.tsx b/ui/src/pages/workflows/WorkflowNew.tsx index f24dde4c..68c5d96d 100644 --- a/ui/src/pages/workflows/WorkflowNew.tsx +++ b/ui/src/pages/workflows/WorkflowNew.tsx @@ -109,7 +109,7 @@ const WorkflowNew = () => {
{NotificationContextHolder} - + {t("workflow.new.subtitle")} diff --git a/ui/src/repository/workflowRun.ts b/ui/src/repository/workflowRun.ts index 2d70c3e2..0aa88080 100644 --- a/ui/src/repository/workflowRun.ts +++ b/ui/src/repository/workflowRun.ts @@ -14,7 +14,7 @@ export type ListWorkflowRunsRequest = { export const list = async (request: ListWorkflowRunsRequest) => { const page = request.page || 1; const perPage = request.perPage || 10; - console.log("request.workflowId", request.workflowId); + let filter = ""; const params: Record = {}; if (request.workflowId) { diff --git a/ui/src/utils/css.ts b/ui/src/utils/css.ts new file mode 100644 index 00000000..048bd5e6 --- /dev/null +++ b/ui/src/utils/css.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export const mergeCls = (...inputs: ClassValue[]) => { + return twMerge(clsx(inputs)); +}; diff --git a/ui/src/utils/error.ts b/ui/src/utils/error.ts index 0647d48b..df5465f4 100644 --- a/ui/src/utils/error.ts +++ b/ui/src/utils/error.ts @@ -1,5 +1,9 @@ +import { ClientResponseError } from "pocketbase"; + export const getErrMsg = (error: unknown): string => { - if (error instanceof Error) { + if (error instanceof ClientResponseError) { + return error.response != null ? getErrMsg(error.response) : error.message; + } else if (error instanceof Error) { return error.message; } else if (typeof error === "object" && error != null) { if ("message" in error) {