Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/gatsby-browser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "antd/dist/reset.css";
import "./src/styles/global.css";
import "./src/i18n";

import AuthProvider from "./src/hooks/provider";

Expand Down
4 changes: 4 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@
"gatsby-plugin-sitemap": "^6.14.0",
"gatsby-source-filesystem": "^5.14.0",
"gatsby-transformer-sharp": "^5.14.0",
"i18next": "^25.3.2",
"i18next-browser-languagedetector": "^8.2.0",
"install": "^0.13.0",
"js-yaml": "^4.1.0",
"lucide-react": "^0.460.0",
"postcss": "^8.4.49",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^15.6.0",
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^15.6.1",
"react-vnc": "^3.0.8",
Expand All @@ -54,6 +57,7 @@
"zustand": "^5.0.1"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/lodash.debounce": "^4.0.9",
"@types/node": "^22.9.0",
"@types/react": "^18.2.55",
Expand Down
Binary file added frontend/src/assets/light2_bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 12 additions & 9 deletions frontend/src/components/common/filerenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
X,
Download,
} from "lucide-react";
import { useTranslation } from "react-i18next";
import MarkdownRenderer from "./markdownrender";
import { ClickableImage } from "../views/atoms";
import { AgentMessageConfig } from "../types/datamodel";
Expand Down Expand Up @@ -98,6 +99,7 @@ const FileModal: React.FC<FileModalProps> = ({
file,
content,
}) => {
const { t } = useTranslation();
const [isFullScreen, setIsFullScreen] = useState<boolean>(false);
const modalRef = React.useRef<HTMLDivElement>(null);
const [downloadUrl, setDownloadUrl] = useState<string | null>(null);
Expand Down Expand Up @@ -188,7 +190,7 @@ const FileModal: React.FC<FileModalProps> = ({
return (
<div className="flex flex-col items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
<p className="mt-4 text-gray-600">Loading file content...</p>
<p className="mt-4 text-gray-600">{t("fileRenderer.loadingFileContent")}</p>
</div>
);
}
Expand All @@ -212,11 +214,11 @@ const FileModal: React.FC<FileModalProps> = ({
<div className="flex flex-col">
{isLoading ? (
<div className="flex flex-col items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
<p className="mt-4 text-gray-600">Processing large file...</p>
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
<p className="mt-4 text-gray-600">{t("fileRenderer.processingLargeFile")}</p>
</div>
) : processedContent === null ? (
<div className="p-4 text-gray-500">No content available</div>
<div className="p-4 text-gray-500">{t("fileRenderer.noContentAvailable")}</div>
) : (
<MarkdownRenderer
content={processedContent}
Expand Down Expand Up @@ -244,8 +246,8 @@ const FileModal: React.FC<FileModalProps> = ({
// For unknown file types, show a message
return (
<div className="p-4 text-center">
<p>Unable to preview this file type.</p>
<p>Filename: {file.name}</p>
<p>{t("fileRenderer.unableToPreviewFileType")}</p>
<p>{t("fileRenderer.filename")}: {file.name}</p>
</div>
);
};
Expand All @@ -271,7 +273,7 @@ const FileModal: React.FC<FileModalProps> = ({
href={downloadUrl}
download={file.name}
className="p-1 rounded-full hover:bg-gray-200 text-black flex items-center justify-center"
title="Download file"
title={t("fileRenderer.downloadFile")}
onClick={(e) => e.stopPropagation()}
>
<Download size={18} />
Expand All @@ -287,7 +289,7 @@ const FileModal: React.FC<FileModalProps> = ({
<button
onClick={onClose}
className="p-1 rounded-full hover:bg-gray-200 text-black"
title="Close"
title={t("fileRenderer.close")}
>
<X size={18} />
</button>
Expand Down Expand Up @@ -367,6 +369,7 @@ ImageThumbnail.displayName = "ImageThumbnail";

// Add this new component for the download button
const DownloadButton = memo<{ file: FileInfo }>(({ file }) => {
const { t } = useTranslation();
const handleDownload = (e: React.MouseEvent) => {
e.stopPropagation(); // Prevent opening the modal

Expand All @@ -388,7 +391,7 @@ const DownloadButton = memo<{ file: FileInfo }>(({ file }) => {
<button
onClick={handleDownload}
className="absolute top-2 right-2 p-1.5 rounded-full bg-white/90 hover:bg-white shadow-md opacity-0 group-hover:opacity-100 transition-opacity duration-200"
title="Download file"
title={t("fileRenderer.downloadFile")}
>
<Download size={16} className="text-gray-700" />
</button>
Expand Down
18 changes: 10 additions & 8 deletions frontend/src/components/contentheader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import SignInModal from "./signin";
import SettingsModal from "./settings/SettingsModal";
import logo from "../assets/logo.svg";
import { Button } from "./common/Button";
import { useTranslation } from "react-i18next";

type ContentHeaderProps = {
onMobileMenuToggle: () => void;
Expand All @@ -26,14 +27,15 @@ const ContentHeader = ({
useConfigStore();
const [isEmailModalOpen, setIsEmailModalOpen] = React.useState(false);
const [isSettingsOpen, setIsSettingsOpen] = React.useState(false);
const { t } = useTranslation();

return (
<div className="sticky top-0 bg-primary">
<div className="sticky top-0">
<div className="flex h-16 items-center justify-between">
{/* Left side: Text and Sidebar Controls */}
<div className="flex items-center">
{/* Sidebar Toggle */}
<Tooltip title={isSidebarOpen ? "Close Sidebar" : "Open Sidebar"}>
<Tooltip title={isSidebarOpen ? t('header.closeSidebar') : t('header.openSidebar')}>
<Button
variant="tertiary"
size="sm"
Expand All @@ -52,7 +54,7 @@ const ContentHeader = ({
{/* New Session Button */}
<div className="w-[40px]">
{!isSidebarOpen && (
<Tooltip title="Create new session">
<Tooltip title={t('header.createNewSession')}>
<Button
variant="tertiary"
size="sm"
Expand All @@ -64,16 +66,16 @@ const ContentHeader = ({
)}
</div>
<div className="flex items-center space-x-2">
<img src={logo} alt="Magentic-UI Logo" className="h-10 w-10" />
<div className="text-primary text-2xl font-bold">Magentic-UI</div>
<img src={logo} alt={t('header.logo')} className="h-10 w-10" />
<div className="text-primary text-2xl font-bold">{t('header.title')}</div>
</div>
</div>

{/* User Profile and Settings */}
<div className="flex items-center space-x-4">
{/* User Profile */}
{user && (
<Tooltip title="View or update your profile">
<Tooltip title={t('header.viewProfile')}>
<div
className="flex items-center space-x-2 cursor-pointer"
onClick={() => setIsEmailModalOpen(true)}
Expand All @@ -95,14 +97,14 @@ const ContentHeader = ({

{/* Settings Button */}
<div className="text-primary">
<Tooltip title="Settings">
<Tooltip title={t('header.settings')}>
<Button
variant="tertiary"
size="sm"
icon={<Settings className="h-8 w-8" />}
onClick={() => setIsSettingsOpen(true)}
className="!px-0 transition-colors hover:text-accent"
aria-label="Settings"
aria-label={t('header.settings')}
/>
</Tooltip>
</div>
Expand Down
28 changes: 15 additions & 13 deletions frontend/src/components/features/Plans/LearnPlanButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useContext } from "react";
import { message, Spin, Tooltip } from "antd";
import { useTranslation } from "react-i18next";
import { appContext } from "../../../hooks/provider";
import { PlanAPI } from "../../views/api";
import { LightBulbIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
Expand All @@ -20,6 +21,7 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
const [isLearning, setIsLearning] = useState(false);
const [isLearned, setIsLearned] = useState(false);
const [error, setError] = useState<string | null>(null);
const { t } = useTranslation();
const { user, darkMode } = useContext(appContext);
const planAPI = new PlanAPI();

Expand All @@ -38,23 +40,23 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({

const handleLearnPlan = async () => {
if (!sessionId || !effectiveUserId) {
message.error("Missing session or user information");
message.error(t("learnPlanButton.missingSessionOrUser"));
return;
}

try {
setIsLearning(true);
setError(null);
message.loading({
content: "Creating plan from conversation...",
content: t("learnPlanButton.creatingPlan"),
key: "learnPlan",
});

const response = await planAPI.learnPlan(sessionId, effectiveUserId);

if (response && response.status) {
message.success({
content: "Plan created successfully!",
content: t("learnPlanButton.planCreatedSuccessfully"),
key: "learnPlan",
duration: 2,
});
Expand All @@ -71,14 +73,14 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
learnedPlans[`${sessionId}-${messageId}`] = true;
localStorage.setItem("learned_plans", JSON.stringify(learnedPlans));
} else {
throw new Error(response?.message || "Failed to create plan");
throw new Error(response?.message || t("learnPlanButton.failedToCreatePlan"));
}
} catch (error) {
console.error("Error creating plan:", error);
setError(error instanceof Error ? error.message : "Unknown error");
setError(error instanceof Error ? error.message : t("learnPlanButton.unknownError"));
message.error({
content: `Failed to create plan: ${
error instanceof Error ? error.message : "Unknown error"
content: `${t("learnPlanButton.failedToCreatePlan")}: ${
error instanceof Error ? error.message : t("learnPlanButton.unknownError")
}`,
key: "learnPlan",
});
Expand All @@ -90,7 +92,7 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
// If already learned, show success message
if (isLearned) {
return (
<Tooltip title="This plan has been saved to your library">
<Tooltip title={t("learnPlanButton.planSavedToLibrary")}>
<div
className={`inline-flex items-center px-3 py-1.5 rounded-md ${
darkMode === "dark"
Expand All @@ -99,7 +101,7 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
}`}
>
<CheckCircleIcon className="h-4 w-4 mr-1.5" />
<span className="text-sm font-medium">Plan Learned</span>
<span className="text-sm font-medium">{t("learnPlanButton.planLearned")}</span>
</div>
</Tooltip>
);
Expand All @@ -108,7 +110,7 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
// If learning, show spinner
if (isLearning) {
return (
<Tooltip title="Creating a plan from this conversation">
<Tooltip title={t("learnPlanButton.creatingPlanFromConversation")}>
<button
disabled
className={`inline-flex items-center px-3 py-1.5 rounded-md transition-colors ${
Expand All @@ -118,15 +120,15 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
} cursor-wait`}
>
<Spin size="small" className="mr-2" />
<span className="text-sm font-medium">Learning Plan...</span>
<span className="text-sm font-medium">{t("learnPlanButton.learningPlan")}</span>
</button>
</Tooltip>
);
}

// Default state - ready to learn
return (
<Tooltip title="Learn a reusable plan from this conversation and save it to your library">
<Tooltip title={t("learnPlanButton.learnReusablePlan")}>
<button
onClick={handleLearnPlan}
disabled={!sessionId || !effectiveUserId}
Expand All @@ -145,7 +147,7 @@ export const LearnPlanButton: React.FC<LearnPlanButtonProps> = ({
darkMode === "dark" ? "text-blue-400" : "text-blue-800"
}`}
/>
<span className="text-sm font-medium">Learn Plan</span>
<span className="text-sm font-medium">{t("learnPlanButton.learnPlan")}</span>
</button>
</Tooltip>
);
Expand Down
Loading