Skip to content

Commit cdbb330

Browse files
committed
Merge branch 'develop' of https://github.com/oqtopus-team/qdash into fix/#760-chip-create-reload
2 parents 1d8ac1d + 4d75500 commit cdbb330

File tree

4 files changed

+124
-106
lines changed

4 files changed

+124
-106
lines changed

ui/src/components/features/chat/CopilotChatPage.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,11 @@ export function CopilotChatPage() {
382382

383383
const [input, setInput] = useState("");
384384
const [showSessionSidebar, setShowSessionSidebar] = useState(true);
385+
useEffect(() => {
386+
if (window.innerWidth < 640) {
387+
setShowSessionSidebar(false);
388+
}
389+
}, []);
385390
const messagesEndRef = useRef<HTMLDivElement>(null);
386391
const inputRef = useRef<HTMLTextAreaElement>(null);
387392

ui/src/components/features/chip/modals/TaskHistoryModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,12 @@ export function TaskHistoryModal({
242242
{selectedTask.task_id && (
243243
<div className="flex items-center gap-2">
244244
<span className="font-semibold">Task ID:</span>
245-
<a
245+
<Link
246246
href={`/task-results/${selectedTask.task_id}`}
247247
className="font-mono truncate link link-primary"
248248
>
249249
{selectedTask.task_id}
250-
</a>
250+
</Link>
251251
</div>
252252
)}
253253
{selectedTask.end_at && (

ui/src/components/features/provenance/ProvenanceGraph.tsx

Lines changed: 116 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,107 @@ export function ProvenanceGraph({
958958
);
959959
}
960960

961+
const controlsBody = (
962+
<>
963+
<div className="flex items-center gap-2 bg-base-100/90 border border-base-300 rounded-lg px-3 py-2 shadow-sm w-full sm:w-auto">
964+
<input
965+
type="text"
966+
value={searchQuery}
967+
onChange={(e) => setSearchQuery(e.target.value)}
968+
placeholder="Find parameter/task..."
969+
className="input input-bordered input-sm w-full sm:w-56 pointer-events-auto"
970+
/>
971+
{searchQuery && (
972+
<button
973+
className="btn btn-ghost btn-sm pointer-events-auto"
974+
onClick={() => setSearchQuery("")}
975+
>
976+
Clear
977+
</button>
978+
)}
979+
</div>
980+
<div className="flex flex-col sm:flex-row items-center gap-2 bg-base-100/90 border border-base-300 rounded-lg px-3 py-2 shadow-sm w-full sm:w-auto">
981+
<div className="flex items-center gap-2">
982+
<div className="text-xs text-base-content/60 whitespace-nowrap">
983+
Focus
984+
</div>
985+
<input
986+
type="range"
987+
min={1}
988+
max={Math.max(1, Math.min(10, maxDistance || 10))}
989+
value={Math.min(
990+
focusHops,
991+
Math.max(1, Math.min(10, maxDistance || 10)),
992+
)}
993+
onChange={(e) => setFocusHops(Number(e.target.value))}
994+
className="range range-xs range-primary w-28 pointer-events-auto"
995+
disabled={effectiveShowAll}
996+
/>
997+
<div className="text-xs font-medium tabular-nums w-10 text-right">
998+
{effectiveShowAll ? "All" : `${focusHops}h`}
999+
</div>
1000+
<button
1001+
className={`btn btn-xs pointer-events-auto ${effectiveShowAll ? "btn-primary" : ""}`}
1002+
onClick={() => setShowAll((v) => !v)}
1003+
>
1004+
All
1005+
</button>
1006+
</div>
1007+
<div className="flex items-center gap-2">
1008+
<label className="flex items-center gap-2 ml-2 cursor-pointer pointer-events-auto">
1009+
<input
1010+
type="checkbox"
1011+
className="checkbox checkbox-xs checkbox-primary pointer-events-auto"
1012+
checked={showDerivedEdges}
1013+
onChange={(e) => setShowDerivedEdges(e.target.checked)}
1014+
/>
1015+
<span className="text-xs text-base-content/60">derived</span>
1016+
</label>
1017+
<div className="join ml-2">
1018+
<button
1019+
className={`btn btn-xs join-item pointer-events-auto ${viewDetail === "full" ? "btn-primary" : ""}`}
1020+
onClick={() => setViewDetail("full")}
1021+
>
1022+
Detail
1023+
</button>
1024+
<button
1025+
className={`btn btn-xs join-item pointer-events-auto ${viewDetail === "taskFlow" ? "btn-primary" : ""}`}
1026+
onClick={() => setViewDetail("taskFlow")}
1027+
>
1028+
Task Flow
1029+
</button>
1030+
</div>
1031+
</div>
1032+
</div>
1033+
<div className="flex flex-wrap items-center gap-1 sm:gap-2 bg-base-100/90 border border-base-300 rounded-lg px-2 sm:px-3 py-2 shadow-sm w-full sm:w-auto sm:shrink-0">
1034+
<span className="badge badge-primary badge-sm whitespace-nowrap">
1035+
{initialNodes.length}/{apiNodes.length} shown
1036+
</span>
1037+
<span className="badge badge-ghost badge-sm whitespace-nowrap">
1038+
params {visibleCounts.entityCount}
1039+
</span>
1040+
<span className="badge badge-ghost badge-sm whitespace-nowrap">
1041+
tasks {visibleCounts.taskCount}
1042+
</span>
1043+
{visibleCounts.failedTasks > 0 && (
1044+
<span className="badge badge-error badge-sm whitespace-nowrap">
1045+
failed {visibleCounts.failedTasks}
1046+
</span>
1047+
)}
1048+
{visibleCounts.lowConfidenceParams > 0 && (
1049+
<span className="badge badge-warning badge-sm whitespace-nowrap">
1050+
uncertain {visibleCounts.lowConfidenceParams}
1051+
</span>
1052+
)}
1053+
{visibleCounts.staleInputs > 0 && (
1054+
<span className="badge badge-info badge-sm whitespace-nowrap">
1055+
updated {visibleCounts.staleInputs}
1056+
</span>
1057+
)}
1058+
</div>
1059+
</>
1060+
);
1061+
9611062
return (
9621063
<div className="h-[calc(100vh-16rem)] min-h-[500px] flex bg-base-200 rounded-lg border border-base-300 overflow-hidden">
9631064
{/* Graph canvas */}
@@ -999,107 +1100,24 @@ export function ProvenanceGraph({
9991100
/>
10001101
</ReactFlow>
10011102

1002-
{/* Controls / Summary */}
1003-
<div className="absolute top-4 left-4 right-4 flex flex-col sm:flex-row sm:flex-wrap gap-2 items-start sm:items-center z-20 pointer-events-none">
1004-
<div className="flex items-center gap-2 bg-base-100/90 border border-base-300 rounded-lg px-3 py-2 shadow-sm w-full sm:w-auto">
1005-
<input
1006-
type="text"
1007-
value={searchQuery}
1008-
onChange={(e) => setSearchQuery(e.target.value)}
1009-
placeholder="Find parameter/task..."
1010-
className="input input-bordered input-sm w-full sm:w-56 pointer-events-auto"
1011-
/>
1012-
{searchQuery && (
1013-
<button
1014-
className="btn btn-ghost btn-sm pointer-events-auto"
1015-
onClick={() => setSearchQuery("")}
1016-
>
1017-
Clear
1018-
</button>
1019-
)}
1020-
</div>
1021-
1022-
<div className="flex items-center gap-2 bg-base-100/90 border border-base-300 rounded-lg px-3 py-2 shadow-sm w-full sm:w-auto sm:mr-auto">
1023-
<div className="text-xs text-base-content/60 whitespace-nowrap">
1024-
Focus
1025-
</div>
1026-
<input
1027-
type="range"
1028-
min={1}
1029-
max={Math.max(1, Math.min(10, maxDistance || 10))}
1030-
value={Math.min(
1031-
focusHops,
1032-
Math.max(1, Math.min(10, maxDistance || 10)),
1033-
)}
1034-
onChange={(e) => setFocusHops(Number(e.target.value))}
1035-
className="range range-xs range-primary w-28 pointer-events-auto"
1036-
disabled={effectiveShowAll}
1037-
/>
1038-
<div className="text-xs font-medium tabular-nums w-10 text-right">
1039-
{effectiveShowAll ? "All" : `${focusHops}h`}
1040-
</div>
1041-
<button
1042-
className={`btn btn-xs pointer-events-auto ${effectiveShowAll ? "btn-primary" : ""}`}
1043-
onClick={() => setShowAll((v) => !v)}
1103+
{/* Controls — SP: accordion (hidden on sm+) */}
1104+
<details className="group absolute top-2 left-2 right-2 z-20 pointer-events-auto sm:hidden">
1105+
<summary className="bg-base-100/90 border border-base-300 rounded-lg px-3 py-2 shadow-sm cursor-pointer select-none list-none text-sm font-medium flex items-center gap-2">
1106+
<span
1107+
className="inline-block transition-transform group-open:rotate-90"
1108+
aria-hidden="true"
10441109
>
1045-
All
1046-
</button>
1047-
<div className="flex items-center gap-2 ml-2">
1048-
<input
1049-
type="checkbox"
1050-
className="checkbox checkbox-xs checkbox-primary pointer-events-auto"
1051-
checked={showDerivedEdges}
1052-
onChange={(e) => setShowDerivedEdges(e.target.checked)}
1053-
id="show-derived"
1054-
/>
1055-
<label
1056-
htmlFor="show-derived"
1057-
className="text-xs text-base-content/60 cursor-pointer pointer-events-auto"
1058-
>
1059-
derived
1060-
</label>
1061-
</div>
1062-
<div className="join ml-2">
1063-
<button
1064-
className={`btn btn-xs join-item pointer-events-auto ${viewDetail === "full" ? "btn-primary" : ""}`}
1065-
onClick={() => setViewDetail("full")}
1066-
>
1067-
Detail
1068-
</button>
1069-
<button
1070-
className={`btn btn-xs join-item pointer-events-auto ${viewDetail === "taskFlow" ? "btn-primary" : ""}`}
1071-
onClick={() => setViewDetail("taskFlow")}
1072-
>
1073-
Task Flow
1074-
</button>
1075-
</div>
1076-
</div>
1077-
<div className="flex flex-wrap items-center gap-1 sm:gap-2 bg-base-100/90 border border-base-300 rounded-lg px-2 sm:px-3 py-2 shadow-sm w-full sm:w-auto sm:shrink-0">
1078-
<span className="badge badge-primary badge-sm whitespace-nowrap">
1079-
{initialNodes.length}/{apiNodes.length} shown
1080-
</span>
1081-
<span className="badge badge-ghost badge-sm whitespace-nowrap">
1082-
params {visibleCounts.entityCount}
1083-
</span>
1084-
<span className="badge badge-ghost badge-sm whitespace-nowrap">
1085-
tasks {visibleCounts.taskCount}
1110+
10861111
</span>
1087-
{visibleCounts.failedTasks > 0 && (
1088-
<span className="badge badge-error badge-sm whitespace-nowrap">
1089-
failed {visibleCounts.failedTasks}
1090-
</span>
1091-
)}
1092-
{visibleCounts.lowConfidenceParams > 0 && (
1093-
<span className="badge badge-warning badge-sm whitespace-nowrap">
1094-
uncertain {visibleCounts.lowConfidenceParams}
1095-
</span>
1096-
)}
1097-
{visibleCounts.staleInputs > 0 && (
1098-
<span className="badge badge-info badge-sm whitespace-nowrap">
1099-
updated {visibleCounts.staleInputs}
1100-
</span>
1101-
)}
1112+
Controls
1113+
</summary>
1114+
<div className="flex flex-col gap-2 items-start mt-2">
1115+
{controlsBody}
11021116
</div>
1117+
</details>
1118+
{/* Controls — PC: always visible (hidden below sm) */}
1119+
<div className="hidden sm:flex sm:flex-row sm:flex-wrap gap-2 items-center absolute top-4 left-4 right-4 z-20 pointer-events-none">
1120+
{controlsBody}
11031121
</div>
11041122

11051123
{/* Legend */}

ui/src/contexts/AuthContext.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
22

3-
import { useRouter } from "next/navigation";
43
import type { ReactNode } from "react";
54
import {
65
createContext,
@@ -26,7 +25,6 @@ interface AuthContextType {
2625
const AuthContext = createContext<AuthContextType | undefined>(undefined);
2726

2827
export function AuthProvider({ children }: { children: ReactNode }) {
29-
const router = useRouter();
3028
const [user, setUser] = useState<User | null>(null);
3129
const [username, setUsername] = useState<string | null>(null);
3230
const [accessToken, setAccessToken] = useState<string | null>(null);
@@ -126,9 +124,6 @@ export function AuthProvider({ children }: { children: ReactNode }) {
126124

127125
// Save auth info (access_token and username)
128126
saveAuth(response.data.access_token, response.data.username);
129-
130-
// Redirect immediately
131-
router.replace("/execution");
132127
} catch (error) {
133128
console.error("Login failed:", error);
134129
// Clear auth info
@@ -139,7 +134,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
139134
setLoading(false); // End loading
140135
}
141136
},
142-
[loginMutation, saveAuth, router, removeAuth],
137+
[loginMutation, saveAuth, removeAuth],
143138
);
144139

145140
const logout = useCallback(async () => {

0 commit comments

Comments
 (0)