Files
model-platform/frontend/app/features/platform/PublishModal.tsx
T
2026-08-25 16:52:10 +08:00

132 lines
4.3 KiB
TypeScript

import { type FormEvent } from "react";
import Icon from "../../components/common/Icon";
import type { ScriptItem, Visibility } from "../../services/api";
import { scriptIcon } from "../../features/platform/WorkspaceTree";
import {
formFieldClass,
formHintClass,
formInputClass,
formTextareaClass,
iconButtonClass,
modalBackdropClass,
modalEyebrowClass,
modalFooterClass,
modalFormClass,
modalHeaderClass,
modalPanelClass,
modalTitleClass,
primaryButtonClass,
secondaryButtonClass,
} 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) {
if (!publishTarget) return null;
return (
<div className={modalBackdropClass} role="presentation">
<section className={modalPanelClass} role="dialog" aria-modal="true">
<div className={modalHeaderClass}>
<div>
<span className={modalEyebrowClass}>不可变制品</span>
<h2 className={modalTitleClass}>发布稳定版本</h2>
</div>
<button
className={iconButtonClass}
type="button"
aria-label="关闭"
onClick={onClose}
>
<Icon name="close" />
</button>
</div>
<form className={modalFormClass} onSubmit={onSubmit}>
<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]"
}`}
>
<Icon name={scriptIcon(publishTarget)} 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>
<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={modalFooterClass}>
<button
className={secondaryButtonClass}
type="button"
onClick={onClose}
>
取消
</button>
<button
className={primaryButtonClass}
type="submit"
disabled={publishing}
>
{publishing
? <span className="button-spinner" />
: <Icon name="release" size={16} />}
{publishing ? "正在发布…" : "确认发布"}
</button>
</div>
</form>
</section>
</div>
);
}