mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-26 19:44:51 +02:00
Merge branch 'eric/dev' into eric/redesign
# Conflicts: # backend/apps/agents/manager/run/RunOptions.py # electron/main.js # frontend/src/app/pages/Dashboard/canvas/DashboardCanvas.tsx # frontend/src/app/pages/Dashboard/cards/BrowserCard.tsx # frontend/src/app/pages/Dashboard/cards/DashboardViewCard.tsx # frontend/src/app/pages/Dashboard/hooks/lifecycle/useDashboardLifecycle.ts
This commit is contained in:
@@ -272,7 +272,9 @@ const AppShell: React.FC = () => {
|
||||
dispatch(setPendingBrowserUrl(url));
|
||||
const lastId = (window as any).__openswarm_last_dashboard_id as string | undefined;
|
||||
const firstDashboard = dashboardList[0];
|
||||
const targetId = lastId || firstDashboard?.id;
|
||||
// Only navigate to lastId if it's a REAL dashboard: a stale localStorage id for a deleted dashboard used to route to /dashboard/<phantom>, which 404s and re-fires the layout wipe (drops your cards / breaks a drag).
|
||||
const lastIsReal = !!lastId && dashboardList.some((d) => d.id === lastId);
|
||||
const targetId = (lastIsReal ? lastId : undefined) || firstDashboard?.id;
|
||||
if (targetId) {
|
||||
navigate(`/dashboard/${targetId}`);
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,8 @@ import FileDownloadIcon from '@mui/icons-material/FileDownload';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
|
||||
import { fetchWorkflows } from '@/shared/state/workflowsSlice';
|
||||
|
||||
import ImportDigest, { DigestHandle } from './ImportDigest';
|
||||
import ImportModal from './ImportModal';
|
||||
@@ -43,6 +45,8 @@ const delay = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
|
||||
const ImportEntryPoint: React.FC = () => {
|
||||
const c = useClaudeTokens();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useAppDispatch();
|
||||
const dashboardId = useAppSelector((s) => s.tempState.lastDashboardId) || undefined;
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const digestRef = useRef<DigestHandle | null>(null);
|
||||
const depth = useRef(0);
|
||||
@@ -56,10 +60,12 @@ const ImportEntryPoint: React.FC = () => {
|
||||
(rootType: string, rootId: string, name: string) => {
|
||||
const msg = rootType === 'app' ? `Added ${name} to your Apps` : `Added ${name}`;
|
||||
setToast({ msg, sev: 'success' });
|
||||
// A workflow has no route of its own, so nothing would pull it in: an open Workflows hub only fetches on mount and would keep showing a stale list. Import drops dashboard_id, and /list keeps unassigned workflows for every dashboard, so this surfaces it wherever the user is.
|
||||
if (rootType === 'workflow') dispatch(fetchWorkflows(dashboardId));
|
||||
const to = DEST[rootType]?.(rootId);
|
||||
if (to) navigate(to);
|
||||
},
|
||||
[navigate],
|
||||
[navigate, dispatch, dashboardId],
|
||||
);
|
||||
|
||||
const commitAndFinish = useCallback(
|
||||
|
||||
@@ -55,11 +55,11 @@ const ShareModal: React.FC<Props> = ({ target, open, onClose }) => {
|
||||
return load();
|
||||
}, [open, load]);
|
||||
|
||||
const handleDownload = async () => {
|
||||
const handleDownload = async (allowSecrets = false) => {
|
||||
if (!preflight) return;
|
||||
setDownloading(true);
|
||||
try {
|
||||
await downloadSwarm(target, preflight.filename);
|
||||
await downloadSwarm(target, preflight.filename, allowSecrets);
|
||||
setToast(`Saved ${preflight.filename}`);
|
||||
onClose();
|
||||
} catch (e: any) {
|
||||
@@ -68,6 +68,8 @@ const ShareModal: React.FC<Props> = ({ target, open, onClose }) => {
|
||||
setDownloading(false);
|
||||
}
|
||||
};
|
||||
// The file-content secret heuristic is overridable (download goes to people you trust); our own credential fields ("secret-shaped field(s)") are not.
|
||||
const secretOverridable = error.includes('secret-shaped value');
|
||||
|
||||
const optionRow = (
|
||||
selected: boolean,
|
||||
@@ -150,6 +152,16 @@ const ShareModal: React.FC<Props> = ({ target, open, onClose }) => {
|
||||
<Button size="small" onClick={load} sx={{ textTransform: 'none', color: c.accent.primary }}>
|
||||
Try again
|
||||
</Button>
|
||||
{secretOverridable && (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => { setError(''); handleDownload(true); }}
|
||||
disabled={downloading}
|
||||
sx={{ textTransform: 'none', color: c.status.error, ml: 1 }}
|
||||
>
|
||||
Export anyway (includes the flagged value; only send to people you trust)
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
) : preflight ? (
|
||||
<IncludesList summary={preflight.summary} />
|
||||
@@ -179,7 +191,7 @@ const ShareModal: React.FC<Props> = ({ target, open, onClose }) => {
|
||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: 1 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleDownload}
|
||||
onClick={() => handleDownload()}
|
||||
disabled={!preflight || downloading}
|
||||
startIcon={
|
||||
downloading ? (
|
||||
|
||||
@@ -28,11 +28,11 @@ export async function exportPreflight(target: ShareTarget): Promise<ExportPrefli
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function downloadSwarm(target: ShareTarget, filename: string): Promise<void> {
|
||||
export async function downloadSwarm(target: ShareTarget, filename: string, allowSecrets = false): Promise<void> {
|
||||
const res = await fetch(`${API_BASE}/swarm/export`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ type: target.kind, id: target.id }),
|
||||
body: JSON.stringify({ type: target.kind, id: target.id, allow_secrets: allowSecrets }),
|
||||
});
|
||||
if (!res.ok) throw new Error(await _detail(res, "We couldn't build the file."));
|
||||
const blob = await res.blob();
|
||||
|
||||
Reference in New Issue
Block a user