From ebce8f698bc5d866da2c6bf5bbeecd623dc6a3b0 Mon Sep 17 00:00:00 2001 From: fccview Date: Wed, 31 Dec 2025 20:09:11 +0000 Subject: [PATCH 01/11] start replacing all UI with terminal UI --- .../Cronjobs/Parts/CronJobItem.tsx | 73 ++-- .../Cronjobs/Parts/MinimalCronJobItem.tsx | 49 ++- .../FeatureComponents/Layout/Sidebar.tsx | 30 +- .../Layout/TabbedInterface.tsx | 26 +- .../FeatureComponents/LoginForm/LoginForm.tsx | 8 +- .../Modals/CreateTaskModal.tsx | 22 +- .../Modals/DeleteScriptModal.tsx | 6 +- .../Modals/DeleteTaskModal.tsx | 6 +- .../Modals/EditTaskModal.tsx | 8 +- .../Modals/ErrorDetailsModal.tsx | 8 +- .../FeatureComponents/Modals/FiltersModal.tsx | 31 +- .../FeatureComponents/Modals/LiveLogModal.tsx | 20 +- .../FeatureComponents/Modals/LogsModal.tsx | 20 +- .../Modals/RestoreBackupModal.tsx | 8 +- .../FeatureComponents/Modals/ScriptModal.tsx | 32 +- .../Modals/SelectScriptModal.tsx | 8 +- .../PWA/PWAInstallPrompt.tsx | 4 +- .../FeatureComponents/Scripts/BashEditor.tsx | 60 ++- .../Scripts/BashSnippetHelper.tsx | 2 +- .../Scripts/CronExpressionHelper.tsx | 16 +- .../Scripts/ScriptsManager.tsx | 10 +- .../Scripts/catppuccin-theme.ts | 36 ++ .../System/PerformanceSummary.tsx | 6 +- .../FeatureComponents/System/SystemInfo.tsx | 7 - .../FeatureComponents/System/SystemStatus.tsx | 28 +- .../FeatureComponents/Theme/ThemeToggle.tsx | 21 +- .../FeatureComponents/User/UserFilter.tsx | 12 +- .../FeatureComponents/User/UserSwitcher.tsx | 7 +- .../GlobalComponents/Badges/StatusBadge.tsx | 28 +- .../GlobalComponents/Cards/Card.tsx | 63 +-- .../GlobalComponents/Cards/MetricCard.tsx | 12 +- .../GlobalComponents/FormElements/Input.tsx | 11 +- .../GlobalComponents/UIElements/Button.tsx | 42 +- .../UIElements/DropdownMenu.tsx | 6 +- .../GlobalComponents/UIElements/Modal.tsx | 113 ++---- .../UIElements/ProgressBar.tsx | 24 +- .../GlobalComponents/UIElements/Switch.tsx | 19 +- .../GlobalComponents/UIElements/Toast.tsx | 12 +- app/_providers/ThemeProvider.tsx | 16 +- app/globals.css | 360 ++++++------------ app/layout.tsx | 32 +- app/page.tsx | 70 ++-- package.json | 6 +- postcss.config.js | 1 + public/webtui/base.css | 1 + public/webtui/theme-catppuccin.css | 1 + yarn.lock | 24 ++ 47 files changed, 634 insertions(+), 771 deletions(-) create mode 100644 app/_components/FeatureComponents/Scripts/catppuccin-theme.ts create mode 100644 public/webtui/base.css create mode 100644 public/webtui/theme-catppuccin.css diff --git a/app/_components/FeatureComponents/Cronjobs/Parts/CronJobItem.tsx b/app/_components/FeatureComponents/Cronjobs/Parts/CronJobItem.tsx index 23cd238..ac035d9 100644 --- a/app/_components/FeatureComponents/Cronjobs/Parts/CronJobItem.tsx +++ b/app/_components/FeatureComponents/Cronjobs/Parts/CronJobItem.tsx @@ -108,12 +108,12 @@ export const CronJobItem = ({ }, ...(job.logsEnabled ? [ - { - label: t("cronjobs.viewLogs"), - icon: , - onClick: () => onViewLogs(job), - }, - ] + { + label: t("cronjobs.viewLogs"), + icon: , + onClick: () => onViewLogs(job), + }, + ] : []), { label: job.paused @@ -148,22 +148,21 @@ export const CronJobItem = ({ return (
{(scheduleDisplayMode === "cron" || scheduleDisplayMode === "both") && ( - - {job.schedule} - - )} + + {job.schedule} + + )} {scheduleDisplayMode === "human" && cronExplanation?.isValid && ( -
- +
+

{cronExplanation.humanReadable}

@@ -172,7 +171,7 @@ export const CronJobItem = ({
{commandCopied === job.id && ( - + )}
 {
@@ -181,7 +180,7 @@ export const CronJobItem = ({
                     setCommandCopied(job.id);
                     setTimeout(() => setCommandCopied(null), 3000);
                   }}
-                  className="w-full cursor-pointer overflow-x-auto text-sm font-medium text-foreground bg-muted/30 px-2 py-1 rounded border border-border/30 hide-scrollbar"
+                  className="w-full cursor-pointer overflow-x-auto text-sm font-medium terminal-font bg-background1 px-2 py-1 ascii-border hide-scrollbar"
                 >
                   {unwrapCommand(displayCommand)}
                 
@@ -191,8 +190,8 @@ export const CronJobItem = ({
{scheduleDisplayMode === "both" && cronExplanation?.isValid && ( -
- +
+

{cronExplanation.humanReadable}

@@ -201,7 +200,7 @@ export const CronJobItem = ({ {job.comment && (

{job.comment} @@ -210,13 +209,13 @@ export const CronJobItem = ({

-
+
{job.user}
{ const success = await copyToClipboard(job.id); @@ -227,7 +226,7 @@ export const CronJobItem = ({ }} > {showCopyConfirmation ? ( - + ) : ( )} @@ -235,14 +234,14 @@ export const CronJobItem = ({
{job.paused && ( - - {t("cronjobs.paused")} + + {t("cronjobs.paused")} )} {job.logsEnabled && ( - - {t("cronjobs.logged")} + + {t("cronjobs.logged")} )} @@ -252,11 +251,11 @@ export const CronJobItem = ({ e.stopPropagation(); onViewLogs(job); }} - className="flex items-center gap-1 text-xs bg-red-500/10 text-red-600 dark:text-red-400 px-2 py-0.5 rounded border border-red-500/30 hover:bg-red-500/20 transition-colors cursor-pointer" + className="flex items-center gap-1 text-xs bg-background0 px-2 py-0.5 ascii-border hover:bg-background1 transition-colors cursor-pointer terminal-font" title="Latest execution failed - Click to view error log" > - - + + {t("cronjobs.failed", { exitCode: job.logError?.exitCode?.toString() ?? "", })} @@ -272,12 +271,12 @@ export const CronJobItem = ({ e.stopPropagation(); onViewLogs(job); }} - className="flex items-center gap-1 text-xs bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 px-2 py-0.5 rounded border border-yellow-500/30 hover:bg-yellow-500/20 transition-colors cursor-pointer" + className="flex items-center gap-1 text-xs bg-background0 px-2 py-0.5 ascii-border hover:bg-background1 transition-colors cursor-pointer terminal-font" title="Latest execution succeeded, but has historical failures - Click to view logs" > - - {t("cronjobs.healthy")} - + + {t("cronjobs.healthy")} + )} @@ -285,9 +284,9 @@ export const CronJobItem = ({ !job.logError?.hasError && !job.logError?.hasHistoricalFailures && job.logError?.latestExitCode === 0 && ( -
- - {t("cronjobs.healthy")} +
+ + {t("cronjobs.healthy")}
)} diff --git a/app/_components/FeatureComponents/Cronjobs/Parts/MinimalCronJobItem.tsx b/app/_components/FeatureComponents/Cronjobs/Parts/MinimalCronJobItem.tsx index 5ded090..87e4a35 100644 --- a/app/_components/FeatureComponents/Cronjobs/Parts/MinimalCronJobItem.tsx +++ b/app/_components/FeatureComponents/Cronjobs/Parts/MinimalCronJobItem.tsx @@ -139,19 +139,19 @@ export const MinimalCronJobItem = ({ return (
{scheduleDisplayMode === "cron" && ( - + {job.schedule} )} {scheduleDisplayMode === "human" && cronExplanation?.isValid && ( -
- +
+ {cronExplanation.humanReadable} @@ -159,15 +159,15 @@ export const MinimalCronJobItem = ({ )} {scheduleDisplayMode === "both" && (
- + {job.schedule} {cronExplanation?.isValid && (
- +
)}
@@ -177,7 +177,7 @@ export const MinimalCronJobItem = ({
{commandCopied === job.id && ( - + )}
 {
@@ -186,7 +186,7 @@ export const MinimalCronJobItem = ({
                 setCommandCopied(job.id);
                 setTimeout(() => setCommandCopied(null), 3000);
               }}
-              className="flex-1 cursor-pointer overflow-hidden text-sm font-medium text-foreground bg-muted/30 px-2 py-1 rounded border border-border/30 truncate"
+              className="flex-1 cursor-pointer overflow-hidden text-sm font-medium terminal-font bg-background1 px-2 py-1 ascii-border truncate"
               title={unwrapCommand(job.command)}
             >
               {unwrapCommand(displayCommand)}
@@ -197,25 +197,25 @@ export const MinimalCronJobItem = ({
         
{job.logsEnabled && (
)} {job.paused && (
)} {!job.logError?.hasError && job.logsEnabled && (
)} {job.logsEnabled && job.logError?.hasError && (
{ e.stopPropagation(); @@ -225,21 +225,22 @@ export const MinimalCronJobItem = ({ )} {!job.logsEnabled && errors.length > 0 && (
onErrorClick(errors[0])} /> )}
-
+
-
+
-
- +
+
{(!isCollapsed || !isCollapsed) && ( -

+

{t("sidebar.systemOverview")}

)} @@ -131,22 +131,22 @@ export const Sidebar = forwardRef(
{quickStats ? ( <> -
- +
+ {quickStats.cpu}%
-
- +
+ {quickStats.memory}%
-
- +
+
{quickStats.network} @@ -163,7 +163,7 @@ export const Sidebar = forwardRef( return (
diff --git a/app/_components/FeatureComponents/Layout/TabbedInterface.tsx b/app/_components/FeatureComponents/Layout/TabbedInterface.tsx index 06d006d..31fec23 100644 --- a/app/_components/FeatureComponents/Layout/TabbedInterface.tsx +++ b/app/_components/FeatureComponents/Layout/TabbedInterface.tsx @@ -24,33 +24,31 @@ export const TabbedInterface = ({ return (
-
-
+
+
diff --git a/app/_components/FeatureComponents/LoginForm/LoginForm.tsx b/app/_components/FeatureComponents/LoginForm/LoginForm.tsx index fb5fb6a..cbc0226 100644 --- a/app/_components/FeatureComponents/LoginForm/LoginForm.tsx +++ b/app/_components/FeatureComponents/LoginForm/LoginForm.tsx @@ -112,8 +112,8 @@ export const LoginForm = ({ {hasPassword && hasOIDC ? t("login.signInWithPasswordOrSSO") : hasOIDC - ? t("login.signInWithSSO") - : t("login.enterPasswordToContinue")} + ? t("login.signInWithSSO") + : t("login.enterPasswordToContinue")} @@ -175,7 +175,7 @@ export const LoginForm = ({
- + {t("login.orContinueWith")}
@@ -203,7 +203,7 @@ export const LoginForm = ({
{version && ( -
+
Cr*nMaster {t("common.version", { version })}
diff --git a/app/_components/FeatureComponents/Modals/CreateTaskModal.tsx b/app/_components/FeatureComponents/Modals/CreateTaskModal.tsx index a850a2f..1dbafe9 100644 --- a/app/_components/FeatureComponents/Modals/CreateTaskModal.tsx +++ b/app/_components/FeatureComponents/Modals/CreateTaskModal.tsx @@ -124,9 +124,9 @@ export const CreateTaskModal = ({ diff --git a/app/_components/FeatureComponents/Modals/EditTaskModal.tsx b/app/_components/FeatureComponents/Modals/EditTaskModal.tsx index 928ebef..553e227 100644 --- a/app/_components/FeatureComponents/Modals/EditTaskModal.tsx +++ b/app/_components/FeatureComponents/Modals/EditTaskModal.tsx @@ -59,7 +59,7 @@ export const EditTaskModal = ({ value={form.command} onChange={(e) => onFormChange({ command: e.target.value })} placeholder="/usr/bin/command" - className="font-mono bg-muted/30 border-border/50 focus:border-primary/50" + className="font-mono bg-muted/30 border-border focus:border-primary/50" required />
@@ -80,11 +80,11 @@ export const EditTaskModal = ({ value={form.comment} onChange={(e) => onFormChange({ comment: e.target.value })} placeholder={t("cronjobs.whatDoesThisTaskDo")} - className="bg-muted/30 border-border/50 focus:border-primary/50" + className="bg-muted/30 border-border focus:border-primary/50" />
-
+
-
+
-
+
diff --git a/app/_components/FeatureComponents/Modals/LiveLogModal.tsx b/app/_components/FeatureComponents/Modals/LiveLogModal.tsx index ffe72a0..35d573a 100644 --- a/app/_components/FeatureComponents/Modals/LiveLogModal.tsx +++ b/app/_components/FeatureComponents/Modals/LiveLogModal.tsx @@ -228,19 +228,19 @@ export const LiveLogModal = ({
{t("cronjobs.liveJobExecution")}{jobComment && `: ${jobComment}`} {status === "running" && ( - + {t("cronjobs.running")} )} {status === "completed" && ( - + {t("cronjobs.completed", { exitCode: exitCode ?? 0 })} )} {status === "failed" && ( - + {t("cronjobs.jobFailed", { exitCode: exitCode ?? 1 })} @@ -268,7 +268,7 @@ export const LiveLogModal = ({ id="maxLines" value={maxLines} onChange={(e) => setMaxLines(parseInt(e.target.value, 10))} - className="bg-background border border-border rounded px-2 py-1 text-sm" + className="bg-background0 border border-border rounded px-2 py-1 text-sm" > @@ -316,7 +316,7 @@ export const LiveLogModal = ({ )}
{truncated && !showFullLog && ( -
+
{t("cronjobs.showingLastOf", { lineCount: lineCount.toLocaleString(), @@ -327,8 +327,8 @@ export const LiveLogModal = ({
{showSizeWarning && ( -
- +
+

{t("cronjobs.largeLogFileDetected")} ({formatFileSize(fileSize)}) @@ -340,7 +340,7 @@ export const LiveLogModal = ({ variant="ghost" size="sm" onClick={toggleTailMode} - className="text-orange-500 hover:text-orange-400 hover:bg-orange-500/10 h-auto py-1 px-2 text-xs" + className="text-status-warning hover:text-status-warning hover:bg-background2 h-auto py-1 px-2 text-xs" title={tailMode ? t("cronjobs.showAllLines") : t("cronjobs.enableTailMode")} > {tailMode ? : } @@ -348,8 +348,8 @@ export const LiveLogModal = ({

)} -
-
+        
+
             {logContent || t("cronjobs.waitingForJobToStart")}
             
diff --git a/app/_components/FeatureComponents/Modals/LogsModal.tsx b/app/_components/FeatureComponents/Modals/LogsModal.tsx index a462955..2e910c0 100644 --- a/app/_components/FeatureComponents/Modals/LogsModal.tsx +++ b/app/_components/FeatureComponents/Modals/LogsModal.tsx @@ -208,11 +208,11 @@ export const LogsModal = ({ logs.map((log) => (
handleViewLog(log.filename)} > @@ -220,9 +220,9 @@ export const LogsModal = ({
{log.hasError ? ( - + ) : log.exitCode === 0 ? ( - + ) : ( )} @@ -236,9 +236,9 @@ export const LogsModal = ({

{log.exitCode !== undefined && ( Exit: {log.exitCode} @@ -271,7 +271,7 @@ export const LogsModal = ({ {t("common.loading")}...
) : selectedLog ? ( -
+                
                   {logContent}
                 
) : ( diff --git a/app/_components/FeatureComponents/Modals/RestoreBackupModal.tsx b/app/_components/FeatureComponents/Modals/RestoreBackupModal.tsx index 2fb4795..f8eb270 100644 --- a/app/_components/FeatureComponents/Modals/RestoreBackupModal.tsx +++ b/app/_components/FeatureComponents/Modals/RestoreBackupModal.tsx @@ -124,7 +124,7 @@ export const RestoreBackupModal = ({ {backups.map((backup) => (
@@ -136,7 +136,7 @@ export const RestoreBackupModal = ({
{commandCopied === backup.filename && ( - + )}
 {
@@ -145,7 +145,7 @@ export const RestoreBackupModal = ({
                           setCommandCopied(backup.filename);
                           setTimeout(() => setCommandCopied(null), 3000);
                         }}
-                        className="flex-1 cursor-pointer overflow-hidden text-sm font-medium text-foreground bg-muted/30 px-2 py-1 rounded border border-border/30 truncate"
+                        className="flex-1 cursor-pointer overflow-hidden text-sm font-medium text-foreground bg-muted/30 px-2 py-1 rounded border border-border truncate"
                         title={unwrapCommand(backup.job.command)}
                       >
                         {unwrapCommand(backup.job.command)}
@@ -204,7 +204,7 @@ export const RestoreBackupModal = ({
           
)} -
+

{t("cronjobs.availableBackups")}: {backups.length}

diff --git a/app/_components/FeatureComponents/Modals/ScriptModal.tsx b/app/_components/FeatureComponents/Modals/ScriptModal.tsx index c09a4a0..2fbe35c 100644 --- a/app/_components/FeatureComponents/Modals/ScriptModal.tsx +++ b/app/_components/FeatureComponents/Modals/ScriptModal.tsx @@ -80,11 +80,11 @@ export const ScriptModal = ({ return ( -
+
-
-