Skip to content
Open
Show file tree
Hide file tree
Changes from all 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