mirror of
https://github.com/Mintplex-Labs/anything-llm
synced 2026-04-25 17:15:37 +02:00
* Powerpoint File Creation (#5278) * wip * download card * UI for downloading * move to fs system with endpoint to pull files * refactor UI * final-pass * remove save-file-browser skill and refactor * remove fileDownload event * reset * reset file * reset timeout * persist toggle * Txt creation (#5279) * wip * download card * UI for downloading * move to fs system with endpoint to pull files * refactor UI * final-pass * remove save-file-browser skill and refactor * remove fileDownload event * reset * reset file * reset timeout * wip * persist toggle * add arbitrary text creation file * Add PDF document generation with markdown formatting (#5283) add support for branding in bottom right corner refactor core utils and frontend rendering * Xlsx document creation (#5284) add Excel doc & sheet creation * Basic docx creation (#5285) * Basic docx creation * add test theme support + styling and title pages * simplify skill selection * handle TG attachments * send documents over tg * lazy import * pin deps * fix lock * i18n for file creation (#5286) i18n for file-creation connect #5280 * theme overhaul * Add PPTX subagent for better results * forgot files * Add PPTX subagent for better results (#5287) * Add PPTX subagent for better results * forgot files * make sub-agent use proper tool calling if it can and better UI hints
188 lines
5.6 KiB
JavaScript
188 lines
5.6 KiB
JavaScript
import React, { useEffect, useState, useRef } from "react";
|
|
import Toggle, { SimpleToggleSwitch } from "@/components/lib/Toggle";
|
|
import { useTranslation } from "react-i18next";
|
|
import {
|
|
FilePpt,
|
|
FileXls,
|
|
FileDoc,
|
|
FilePdf,
|
|
FileText,
|
|
CircleNotch,
|
|
} from "@phosphor-icons/react";
|
|
import Admin from "@/models/admin";
|
|
|
|
const getCreateFileSkills = (t) => [
|
|
{
|
|
name: "create-text-file",
|
|
title: t("agent.skill.createFiles.skills.create-text-file.title"),
|
|
description: t(
|
|
"agent.skill.createFiles.skills.create-text-file.description"
|
|
),
|
|
icon: FileText,
|
|
},
|
|
{
|
|
name: "create-pptx-presentation",
|
|
title: t("agent.skill.createFiles.skills.create-pptx.title"),
|
|
description: t("agent.skill.createFiles.skills.create-pptx.description"),
|
|
icon: FilePpt,
|
|
},
|
|
{
|
|
name: "create-pdf-file",
|
|
title: t("agent.skill.createFiles.skills.create-pdf.title"),
|
|
description: t("agent.skill.createFiles.skills.create-pdf.description"),
|
|
icon: FilePdf,
|
|
},
|
|
{
|
|
name: "create-excel-file",
|
|
title: t("agent.skill.createFiles.skills.create-xlsx.title"),
|
|
description: t("agent.skill.createFiles.skills.create-xlsx.description"),
|
|
icon: FileXls,
|
|
},
|
|
{
|
|
name: "create-docx-file",
|
|
title: t("agent.skill.createFiles.skills.create-docx.title"),
|
|
description: t("agent.skill.createFiles.skills.create-docx.description"),
|
|
icon: FileDoc,
|
|
},
|
|
];
|
|
|
|
export default function CreateFileSkillPanel({
|
|
title,
|
|
skill,
|
|
toggleSkill,
|
|
enabled = false,
|
|
disabled = false,
|
|
image,
|
|
icon,
|
|
setHasChanges,
|
|
hasChanges = false,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const [disabledSkills, setDisabledSkills] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const prevHasChanges = useRef(hasChanges);
|
|
const skills = getCreateFileSkills(t);
|
|
|
|
useEffect(() => {
|
|
setLoading(true);
|
|
Admin.systemPreferencesByFields(["disabled_create_files_skills"])
|
|
.then((res) =>
|
|
setDisabledSkills(res?.settings?.disabled_create_files_skills ?? [])
|
|
)
|
|
.catch(() => setDisabledSkills([]))
|
|
.finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (prevHasChanges.current === true && hasChanges === false) {
|
|
Admin.systemPreferencesByFields(["disabled_create_files_skills"])
|
|
.then((res) =>
|
|
setDisabledSkills(res?.settings?.disabled_create_files_skills ?? [])
|
|
)
|
|
.catch(() => {});
|
|
}
|
|
prevHasChanges.current = hasChanges;
|
|
}, [hasChanges]);
|
|
|
|
function toggleFileSkill(skillName) {
|
|
setHasChanges(true);
|
|
setDisabledSkills((prev) =>
|
|
prev.includes(skillName)
|
|
? prev.filter((s) => s !== skillName)
|
|
: [...prev, skillName]
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-2">
|
|
<div className="flex flex-col gap-y-[18px] max-w-[500px]">
|
|
<div className="flex w-full justify-between items-center">
|
|
<div className="flex items-center gap-x-2">
|
|
{icon &&
|
|
React.createElement(icon, {
|
|
size: 24,
|
|
color: "var(--theme-text-primary)",
|
|
weight: "bold",
|
|
})}
|
|
<label
|
|
htmlFor="name"
|
|
className="text-theme-text-primary text-md font-bold"
|
|
>
|
|
{title}
|
|
</label>
|
|
</div>
|
|
<Toggle
|
|
size="lg"
|
|
enabled={enabled}
|
|
disabled={disabled}
|
|
onChange={() => toggleSkill(skill)}
|
|
/>
|
|
</div>
|
|
|
|
<img src={image} alt={title} className="w-full rounded-md" />
|
|
<p className="text-theme-text-secondary text-opacity-60 text-xs font-medium">
|
|
{t("agent.skill.createFiles.description")}
|
|
</p>
|
|
|
|
{enabled && (
|
|
<>
|
|
<input
|
|
name="system::disabled_create_files_skills"
|
|
type="hidden"
|
|
value={disabledSkills.join(",")}
|
|
/>
|
|
<div className="flex flex-col mt-2 gap-y-2">
|
|
<p className="text-theme-text-primary font-semibold text-sm">
|
|
{t("agent.skill.createFiles.configuration")}
|
|
</p>
|
|
{loading ? (
|
|
<div className="flex items-center justify-center py-4">
|
|
<CircleNotch
|
|
size={24}
|
|
className="animate-spin text-theme-text-primary"
|
|
/>
|
|
</div>
|
|
) : (
|
|
<div className="flex flex-col gap-y-2">
|
|
{skills.map((fileSkill) => (
|
|
<SkillRow
|
|
key={fileSkill.name}
|
|
skill={fileSkill}
|
|
disabled={disabledSkills.includes(fileSkill.name)}
|
|
onToggle={() => toggleFileSkill(fileSkill.name)}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function SkillRow({ skill, disabled, onToggle }) {
|
|
const Icon = skill.icon;
|
|
return (
|
|
<div
|
|
className={`flex items-center justify-between p-2 rounded-lg border ${
|
|
disabled
|
|
? "bg-theme-bg-secondary/30 border-theme-sidebar-border/30"
|
|
: "bg-theme-bg-secondary/50 border-theme-sidebar-border/50"
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-x-2">
|
|
<Icon size={22} className="text-slate-100 shrink-0" />
|
|
<div className="flex flex-col">
|
|
<span className="text-sm font-medium text-slate-100">
|
|
{skill.title}
|
|
</span>
|
|
<span className="text-xs text-slate-100/50">{skill.description}</span>
|
|
</div>
|
|
</div>
|
|
<SimpleToggleSwitch enabled={!disabled} onChange={onToggle} size="md" />
|
|
</div>
|
|
);
|
|
}
|