mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-11-10 17:00:11 +01:00
[STYLE] Agent UI mobile styles (#1665)
* implement mobile styles for new agent settings ui * fix on off label not updating for generate & save files to browser * update sql connector modal for mobile * small changes for UI normalization * breakout layout from forms for mobile/desktop * add back no-borders --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
parent
05870ec8d0
commit
9644f671c2
@ -8,8 +8,8 @@ export default function ContextualSaveBar({
|
||||
if (!showing) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed top-0 left-0 right-0 h-14 bg-[#18181B] flex items-center justify-end px-4 z-[9999]">
|
||||
<div className="absolute left-1/2 transform -translate-x-1/2 flex items-center gap-x-2">
|
||||
<div className="fixed top-0 left-0 right-0 h-14 bg-[#18181B] flex items-center justify-end px-4 z-[999]">
|
||||
<div className="absolute ml-4 left-0 md:left-1/2 transform md:-translate-x-1/2 flex items-center gap-x-2">
|
||||
<Warning size={18} className="text-white" />
|
||||
<p className="text-white font-medium text-xs">Unsaved Changes</p>
|
||||
</div>
|
||||
|
@ -74,7 +74,7 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
// to the parent container form so we don't have nested forms.
|
||||
return createPortal(
|
||||
<ModalWrapper isOpen={isOpen}>
|
||||
<div className="relative w-1/3 max-h-full mt-8">
|
||||
<div className="relative w-full md:w-1/3 max-w-2xl max-h-full md:mt-8">
|
||||
<div className="relative bg-main-gradient rounded-xl shadow-[0_4px_14px_rgba(0,0,0,0.25)] max-h-[85vh] overflow-y-scroll no-scroll">
|
||||
<div className="flex items-start justify-between p-4 border-b rounded-t border-gray-500/50">
|
||||
<h3 className="text-xl font-semibold text-white">
|
||||
@ -114,7 +114,7 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
<label className="text-white text-sm font-semibold block my-4">
|
||||
Select your SQL engine
|
||||
</label>
|
||||
<div className="flex w-full flex-wrap gap-x-4">
|
||||
<div className="grid md:grid-cols-4 gap-4 grid-cols-2">
|
||||
<DBEngine
|
||||
provider="postgresql"
|
||||
active={engine === "postgresql"}
|
||||
@ -148,8 +148,8 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-x-2">
|
||||
<div className="flex flex-col w-60">
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div className="flex flex-col">
|
||||
<label className="text-white text-sm font-semibold block mb-4">
|
||||
Database user
|
||||
</label>
|
||||
@ -163,7 +163,7 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
spellCheck={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col w-60">
|
||||
<div className="flex flex-col">
|
||||
<label className="text-white text-sm font-semibold block mb-4">
|
||||
Database user password
|
||||
</label>
|
||||
@ -179,8 +179,8 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-x-2">
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||
<div className="sm:col-span-2">
|
||||
<label className="text-white text-sm font-semibold block mb-4">
|
||||
Server endpoint
|
||||
</label>
|
||||
@ -194,7 +194,7 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
spellCheck={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col w-30">
|
||||
<div>
|
||||
<label className="text-white text-sm font-semibold block mb-4">
|
||||
Port
|
||||
</label>
|
||||
@ -210,7 +210,7 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col w-60">
|
||||
<div className="flex flex-col">
|
||||
<label className="text-white text-sm font-semibold block mb-4">
|
||||
Database
|
||||
</label>
|
||||
@ -264,7 +264,7 @@ function DBEngine({ provider, active, onClick }) {
|
||||
<img
|
||||
src={DB_LOGOS[provider]}
|
||||
className="h-[100px] rounded-md"
|
||||
alt="PostgreSQL"
|
||||
alt={provider}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { isMobile } from "react-device-detect";
|
||||
import Admin from "@/models/admin";
|
||||
import System from "@/models/system";
|
||||
import showToast from "@/utils/toast";
|
||||
import { CaretRight, Robot } from "@phosphor-icons/react";
|
||||
import { CaretLeft, CaretRight, Robot } from "@phosphor-icons/react";
|
||||
import ContextualSaveBar from "@/components/ContextualSaveBar";
|
||||
import { castToType } from "@/utils/types";
|
||||
import { FullScreenLoader } from "@/components/Preloader";
|
||||
@ -17,6 +17,7 @@ export default function AdminAgents() {
|
||||
const [selectedSkill, setSelectedSkill] = useState("");
|
||||
const [agentSkills, setAgentSkills] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [showSkillModal, setShowSkillModal] = useState(false);
|
||||
const formEl = useRef(null);
|
||||
|
||||
// Alert user if they try to leave the page with unsaved changes
|
||||
@ -110,21 +111,19 @@ export default function AdminAgents() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div
|
||||
id="workspace-agent-settings-container"
|
||||
className="w-screen h-screen overflow-hidden bg-sidebar flex"
|
||||
>
|
||||
<Sidebar />
|
||||
<div
|
||||
style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }}
|
||||
className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] w-full h-full flex"
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<SkillLayout
|
||||
hasChanges={hasChanges}
|
||||
handleCancel={() => setHasChanges(false)}
|
||||
handleSubmit={handleSubmit}
|
||||
>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
onChange={() => setHasChanges(true)}
|
||||
ref={formEl}
|
||||
className="flex-1 flex gap-x-6 p-4 mt-10"
|
||||
className="flex flex-col w-full p-4 mt-10"
|
||||
>
|
||||
<input
|
||||
name="system::default_agent_skills"
|
||||
@ -133,56 +132,167 @@ export default function AdminAgents() {
|
||||
/>
|
||||
|
||||
{/* Skill settings nav */}
|
||||
<div className="flex flex-col gap-y-[18px]">
|
||||
<div hidden={showSkillModal} className="flex flex-col gap-y-[18px]">
|
||||
<div className="text-white flex items-center gap-x-2">
|
||||
<Robot size={24} />
|
||||
<p className="text-lg font-medium">Agent Skills</p>
|
||||
</div>
|
||||
|
||||
{/* Default skills list */}
|
||||
{/* Default skills */}
|
||||
<SkillList
|
||||
isDefault={true}
|
||||
skills={defaultSkills}
|
||||
selectedSkill={selectedSkill}
|
||||
handleClick={setSelectedSkill}
|
||||
handleClick={(skill) => {
|
||||
setSelectedSkill(skill);
|
||||
setShowSkillModal(true);
|
||||
}}
|
||||
/>
|
||||
{/* Configurable skills */}
|
||||
<SkillList
|
||||
skills={configurableSkills}
|
||||
selectedSkill={selectedSkill}
|
||||
handleClick={setSelectedSkill}
|
||||
handleClick={(skill) => {
|
||||
setSelectedSkill(skill);
|
||||
setShowSkillModal(true);
|
||||
}}
|
||||
activeSkills={agentSkills}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Selected agent skill setting panel */}
|
||||
<div className="flex-[2] flex flex-col gap-y-[18px] mt-10">
|
||||
<div className="bg-[#303237] text-white rounded-xl flex-1 p-4">
|
||||
{SelectedSkillComponent ? (
|
||||
<SelectedSkillComponent
|
||||
skill={configurableSkills[selectedSkill]?.skill}
|
||||
settings={settings}
|
||||
toggleSkill={toggleAgentSkill}
|
||||
enabled={agentSkills.includes(
|
||||
configurableSkills[selectedSkill]?.skill
|
||||
)}
|
||||
setHasChanges={setHasChanges}
|
||||
{...(configurableSkills[selectedSkill] ||
|
||||
defaultSkills[selectedSkill])}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center h-full text-white/60">
|
||||
<Robot size={40} />
|
||||
<p className="font-medium">Select an agent skill</p>
|
||||
{/* Selected agent skill modal */}
|
||||
{showSkillModal && (
|
||||
<div className="fixed top-0 left-0 w-full h-full bg-sidebar z-30">
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex items-center p-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setShowSkillModal(false);
|
||||
setSelectedSkill("");
|
||||
}}
|
||||
className="text-white/60 hover:text-white transition-colors duration-200"
|
||||
>
|
||||
<div className="flex items-center text-sky-400">
|
||||
<CaretLeft size={24} />
|
||||
<div>Back</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 overflow-y-auto p-4">
|
||||
<div className="bg-[#303237] text-white rounded-xl p-4">
|
||||
{SelectedSkillComponent ? (
|
||||
<SelectedSkillComponent
|
||||
skill={configurableSkills[selectedSkill]?.skill}
|
||||
settings={settings}
|
||||
toggleSkill={toggleAgentSkill}
|
||||
enabled={agentSkills.includes(
|
||||
configurableSkills[selectedSkill]?.skill
|
||||
)}
|
||||
setHasChanges={setHasChanges}
|
||||
{...(configurableSkills[selectedSkill] ||
|
||||
defaultSkills[selectedSkill])}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center h-full text-white/60">
|
||||
<Robot size={40} />
|
||||
<p className="font-medium">Select an agent skill</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</SkillLayout>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SkillLayout
|
||||
hasChanges={hasChanges}
|
||||
handleCancel={() => setHasChanges(false)}
|
||||
handleSubmit={handleSubmit}
|
||||
>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
onChange={() => setHasChanges(true)}
|
||||
ref={formEl}
|
||||
className="flex-1 flex gap-x-6 p-4 mt-10"
|
||||
>
|
||||
<input
|
||||
name="system::default_agent_skills"
|
||||
type="hidden"
|
||||
value={agentSkills.join(",")}
|
||||
/>
|
||||
|
||||
{/* Skill settings nav */}
|
||||
<div className="flex flex-col gap-y-[18px]">
|
||||
<div className="text-white flex items-center gap-x-2">
|
||||
<Robot size={24} />
|
||||
<p className="text-lg font-medium">Agent Skills</p>
|
||||
</div>
|
||||
|
||||
{/* Default skills list */}
|
||||
<SkillList
|
||||
isDefault={true}
|
||||
skills={defaultSkills}
|
||||
selectedSkill={selectedSkill}
|
||||
handleClick={setSelectedSkill}
|
||||
/>
|
||||
{/* Configurable skills */}
|
||||
<SkillList
|
||||
skills={configurableSkills}
|
||||
selectedSkill={selectedSkill}
|
||||
handleClick={setSelectedSkill}
|
||||
activeSkills={agentSkills}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Selected agent skill setting panel */}
|
||||
<div className="flex-[2] flex flex-col gap-y-[18px] mt-10">
|
||||
<div className="bg-[#303237] text-white rounded-xl flex-1 p-4">
|
||||
{SelectedSkillComponent ? (
|
||||
<SelectedSkillComponent
|
||||
skill={configurableSkills[selectedSkill]?.skill}
|
||||
settings={settings}
|
||||
toggleSkill={toggleAgentSkill}
|
||||
enabled={agentSkills.includes(
|
||||
configurableSkills[selectedSkill]?.skill
|
||||
)}
|
||||
setHasChanges={setHasChanges}
|
||||
{...(configurableSkills[selectedSkill] ||
|
||||
defaultSkills[selectedSkill])}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center h-full text-white/60">
|
||||
<Robot size={40} />
|
||||
<p className="font-medium">Select an agent skill</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</SkillLayout>
|
||||
);
|
||||
}
|
||||
|
||||
function SkillLayout({ children, hasChanges, handleSubmit, handleCancel }) {
|
||||
return (
|
||||
<div
|
||||
id="workspace-agent-settings-container"
|
||||
className="w-screen h-screen overflow-hidden bg-sidebar flex md:mt-0 mt-6"
|
||||
>
|
||||
<Sidebar />
|
||||
<div
|
||||
style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }}
|
||||
className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] w-full h-full flex"
|
||||
>
|
||||
{children}
|
||||
<ContextualSaveBar
|
||||
showing={hasChanges}
|
||||
onSave={handleSubmit}
|
||||
onCancel={() => setHasChanges(false)}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -199,7 +309,11 @@ function SkillList({
|
||||
if (skills.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="bg-white/5 text-white min-w-[360px] w-fit rounded-xl">
|
||||
<div
|
||||
className={`bg-white/5 text-white rounded-xl ${
|
||||
isMobile ? "w-full" : "min-w-[360px] w-fit"
|
||||
}`}
|
||||
>
|
||||
{Object.entries(skills).map(([skill, settings], index) => (
|
||||
<div
|
||||
key={skill}
|
||||
|
Loading…
Reference in New Issue
Block a user