Files
model-platform/frontend/app/features/platform/PublishModal.tsx
T
2026-08-28 12:00:14 +08:00

127 lines
4.2 KiB
TypeScript

import { type FormEvent } from "react";
import { ArrowUpFromLine, Loader2Icon } from "lucide-react";
import type { ScriptItem, Visibility } from "../../services/api";
import { scriptIcon } from "../../features/platform/WorkspaceTree";
import {
AppFormDialog,
dialogPrimaryButtonClass,
dialogSecondaryButtonClass,
} from "~/components/common/AppFormDialog";
import { Button } from "~/components/ui/button";
import {
formFieldClass,
formHintClass,
formInputClass,
formTextareaClass,
modalFormClass,
} from "./modalUi";
type PublishModalProps = {
publishTarget: ScriptItem | null;
releaseNote: string;
publishVisibility: Visibility;
publishing: boolean;
onReleaseNoteChange: (note: string) => void;
onPublishVisibilityChange: (visibility: Visibility) => void;
onSubmit: (event: FormEvent) => void;
onClose: () => void;
};
export function PublishModal({
publishTarget,
releaseNote,
publishVisibility,
publishing,
onReleaseNoteChange,
onPublishVisibilityChange,
onSubmit,
onClose,
}: PublishModalProps) {
const PublishTargetIcon = publishTarget ? scriptIcon(publishTarget) : null;
return (
<AppFormDialog
open={publishTarget !== null}
onOpenChange={(nextOpen) => {
if (!nextOpen) onClose();
}}
eyebrow="不可变制品"
title="发布稳定版本"
size="panel"
>
<form className={modalFormClass} onSubmit={onSubmit}>
{publishTarget && PublishTargetIcon ? (
<div className="mb-[17px] flex items-center gap-2.5 rounded-[7px] border border-[#dce6ef] bg-[#f8fbfd] px-3 py-[11px]">
<span
className={`grid size-[25px] shrink-0 place-items-center rounded-[5px] ${
publishTarget.script_type === "notebook"
? "bg-[#fff0ed] text-[#e15e50]"
: "bg-[#eaf3ff] text-[#2e73c6]"
}`}
>
<PublishTargetIcon size={18} />
</span>
<span className="flex min-w-0 flex-col gap-0.5">
<strong className="truncate text-xs text-[#34485d]">
{publishTarget.script_name}
</strong>
<small className="text-[9px] text-[#8b99a8]">
当前 Workspace 工作副本
</small>
</span>
</div>
) : null}
<label className={formFieldClass}>
<span>发布说明</span>
<textarea
className={formTextareaClass}
maxLength={1000}
placeholder="例如:完成数据清洗和特征工程"
value={releaseNote}
onChange={(event) => onReleaseNoteChange(event.target.value)}
/>
<small className={formHintClass}>
稳定版本内容不可修改,可作为后续调度节点输入。
</small>
</label>
<label className={formFieldClass}>
<span>可见范围</span>
<select
className={formInputClass}
value={publishVisibility}
onChange={(event) =>
onPublishVisibilityChange(event.target.value as Visibility)}
>
<option value="private">仅自己可见</option>
<option value="workspace">Workspace 成员可见</option>
<option value="public">公开</option>
</select>
</label>
<div className="mt-[3px] flex shrink-0 justify-end gap-2 border-t border-line bg-white -mx-[22px] px-[22px] py-3.5">
<Button
variant="outline"
size="sm"
type="button"
onClick={onClose}
className={dialogSecondaryButtonClass}
>
取消
</Button>
<Button
variant="default"
size="sm"
type="submit"
disabled={publishing}
className={dialogPrimaryButtonClass}
>
{publishing
? <Loader2Icon className="size-4 animate-spin" />
: <ArrowUpFromLine size={16} />}
{publishing ? "正在发布…" : "确认发布"}
</Button>
</div>
</form>
</AppFormDialog>
);
}