|
|
@@ -627,7 +627,7 @@ function RelationCard({ type, item, activeId, shouldScrollIntoView = false, sele
|
|
|
|
|
|
// ─── 详情抽屉内容 ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
-function DrawerContent({ type, data, dbData, onOpenPost, nodePostsMap }: { type: string; data: any; dbData: any; onOpenPost: (postId: string, post: any) => void; nodePostsMap?: Record<string, string[]> }) {
|
|
|
+function DrawerContent({ type, data, dbData, onOpenPost, nodePostsMap, selectedReqId }: { type: string; data: any; dbData: any; onOpenPost: (postId: string, post: any) => void; nodePostsMap?: Record<string, string[]>; selectedReqId?: string | null }) {
|
|
|
if (type === 'req') {
|
|
|
return (
|
|
|
<RequirementPostsDrawer
|
|
|
@@ -1104,43 +1104,50 @@ function DrawerContent({ type, data, dbData, onOpenPost, nodePostsMap }: { type:
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- {(data.req_associations || []).length > 0 && (
|
|
|
- <div>
|
|
|
- <div className="text-xs font-bold text-slate-500 mb-2">关联需求 ({data.req_associations.length})</div>
|
|
|
- <div className="space-y-3">
|
|
|
- {(data.req_associations as any[]).map((assoc: any) => {
|
|
|
- const trueNodes = (assoc.judgments || []).filter((j: any) => j.represents).map((j: any) => j.node);
|
|
|
- const falseNodes = (assoc.judgments || []).filter((j: any) => !j.represents).map((j: any) => j.node);
|
|
|
- return (
|
|
|
- <div key={assoc.req_id} className="bg-white border border-slate-100 rounded-xl p-3 space-y-2">
|
|
|
- <div className="flex items-center gap-2">
|
|
|
- <span className="font-mono text-[10px] text-indigo-500 shrink-0">{assoc.req_id}</span>
|
|
|
- <span className="text-xs text-slate-700 leading-snug line-clamp-2">{assoc.req_text}</span>
|
|
|
- </div>
|
|
|
- {assoc.judgments?.length > 0 && (
|
|
|
- <div className="flex flex-wrap gap-1">
|
|
|
- {(assoc.judgments as any[]).map((j: any) => (
|
|
|
- <span key={j.node} title={j.reason} className={cn(
|
|
|
- "px-1.5 py-0.5 rounded-full text-[10px] border font-medium cursor-help",
|
|
|
- j.represents
|
|
|
- ? "bg-emerald-50 text-emerald-700 border-emerald-200"
|
|
|
- : "bg-slate-50 text-slate-400 border-slate-200 line-through"
|
|
|
- )}>{j.node}</span>
|
|
|
- ))}
|
|
|
+ {(() => {
|
|
|
+ const filteredAssocs = selectedReqId
|
|
|
+ ? (data.req_associations || []).filter((assoc: any) => assoc.req_id === selectedReqId)
|
|
|
+ : (data.req_associations || []);
|
|
|
+
|
|
|
+ if (filteredAssocs.length === 0) {
|
|
|
+ return <div className="text-xs text-slate-400 text-center py-4">暂无关联需求数据</div>;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <div className="text-xs font-bold text-slate-500 mb-2">关联需求 ({filteredAssocs.length})</div>
|
|
|
+ <div className="space-y-3">
|
|
|
+ {filteredAssocs.map((assoc: any) => {
|
|
|
+ const trueNodes = (assoc.judgments || []).filter((j: any) => j.represents).map((j: any) => j.node);
|
|
|
+ const falseNodes = (assoc.judgments || []).filter((j: any) => !j.represents).map((j: any) => j.node);
|
|
|
+ return (
|
|
|
+ <div key={assoc.req_id} className="bg-white border border-slate-100 rounded-xl p-3 space-y-2">
|
|
|
+ <div className="flex items-center gap-2">
|
|
|
+ <span className="font-mono text-[10px] text-indigo-500 shrink-0">{assoc.req_id}</span>
|
|
|
+ <span className="text-xs text-slate-700 leading-snug line-clamp-2">{assoc.req_text}</span>
|
|
|
</div>
|
|
|
- )}
|
|
|
- {trueNodes.length === 0 && falseNodes.length > 0 && (
|
|
|
- <div className="text-[10px] text-slate-400">无节点被判断为代表该需求</div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- );
|
|
|
- })}
|
|
|
+ {assoc.judgments?.length > 0 && (
|
|
|
+ <div className="flex flex-wrap gap-1">
|
|
|
+ {(assoc.judgments as any[]).map((j: any) => (
|
|
|
+ <span key={j.node} title={j.reason} className={cn(
|
|
|
+ "px-1.5 py-0.5 rounded-full text-[10px] border font-medium cursor-help",
|
|
|
+ j.represents
|
|
|
+ ? "bg-emerald-50 text-emerald-700 border-emerald-200"
|
|
|
+ : "bg-slate-50 text-slate-400 border-slate-200 line-through"
|
|
|
+ )}>{j.node}</span>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ {trueNodes.length === 0 && falseNodes.length > 0 && (
|
|
|
+ <div className="text-[10px] text-slate-400">无节点被判断为代表该需求</div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- {(data.req_associations || []).length === 0 && (
|
|
|
- <div className="text-xs text-slate-400 text-center py-4">暂无关联需求数据</div>
|
|
|
- )}
|
|
|
+ );
|
|
|
+ })()}
|
|
|
</>
|
|
|
)}
|
|
|
</div>
|
|
|
@@ -2417,61 +2424,7 @@ export function Dashboard({ pendingNode, onPendingConsumed }: { pendingNode?: st
|
|
|
return ids.size > 0 ? ids : null;
|
|
|
}, [selectedItemset, collectDirectNodeIdsFromNames]);
|
|
|
|
|
|
- const relatedItemsetIds = useMemo((): Set<string> => {
|
|
|
- const byNode = selectedNode
|
|
|
- ? new Set<string>(
|
|
|
- allItemsets
|
|
|
- .filter((itemset: any) => (itemset.leaf_names || []).some((name: string) => selectedNodeDirectNames?.has(name)))
|
|
|
- .map((itemset: any) => String(itemset.id))
|
|
|
- )
|
|
|
- : null;
|
|
|
- const byReq = selectedReqId
|
|
|
- ? new Set<string>(
|
|
|
- allItemsets
|
|
|
- .filter((itemset: any) => (itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>()).has(selectedReqId))
|
|
|
- .map((itemset: any) => String(itemset.id))
|
|
|
- )
|
|
|
- : null;
|
|
|
- const byProc = selectedProcId
|
|
|
- ? new Set<string>(
|
|
|
- allItemsets
|
|
|
- .filter((itemset: any) => {
|
|
|
- const reqIds = itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>();
|
|
|
- return Array.from(reqIds).some((reqId) => selectedProcRequirementIds.has(reqId));
|
|
|
- })
|
|
|
- .map((itemset: any) => String(itemset.id))
|
|
|
- )
|
|
|
- : null;
|
|
|
- const byCap = selectedCapId
|
|
|
- ? new Set<string>(
|
|
|
- allItemsets
|
|
|
- .filter((itemset: any) => {
|
|
|
- const reqIds = itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>();
|
|
|
- return Array.from(reqIds).some((reqId) => selectedCapRequirementIds.has(reqId));
|
|
|
- })
|
|
|
- .map((itemset: any) => String(itemset.id))
|
|
|
- )
|
|
|
- : null;
|
|
|
- const byTool = selectedToolId
|
|
|
- ? new Set<string>(
|
|
|
- allItemsets
|
|
|
- .filter((itemset: any) => {
|
|
|
- const reqIds = itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>();
|
|
|
- return Array.from(reqIds).some((reqId) => selectedToolRequirementIds.has(reqId));
|
|
|
- })
|
|
|
- .map((itemset: any) => String(itemset.id))
|
|
|
- )
|
|
|
- : null;
|
|
|
|
|
|
- const activeSets = [byNode, byReq, byProc, byCap, byTool].filter((set): set is Set<string> => !!set);
|
|
|
- if (activeSets.length === 0) return new Set<string>();
|
|
|
- const [first, ...rest] = activeSets;
|
|
|
- const result = new Set<string>();
|
|
|
- first.forEach((value) => {
|
|
|
- if (rest.every((set) => set.has(value))) result.add(value);
|
|
|
- });
|
|
|
- return result;
|
|
|
- }, [allItemsets, itemsetReqIdsMap, selectedNode, selectedNodeDirectNames, selectedReqId, selectedProcId, selectedCapId, selectedToolId, selectedProcRequirementIds, selectedCapRequirementIds, selectedToolRequirementIds]);
|
|
|
|
|
|
const patternContextNodeNames = useMemo(() => {
|
|
|
const names = new Set<string>();
|
|
|
@@ -2659,46 +2612,161 @@ export function Dashboard({ pendingNode, onPendingConsumed }: { pendingNode?: st
|
|
|
return result;
|
|
|
};
|
|
|
|
|
|
+ const isGlobalConflict = useMemo(() => {
|
|
|
+ if (selectedNode && selectedReqId && !directNodeReqIds.has(selectedReqId)) return true;
|
|
|
+ if (selectedNode && selectedProcId && !directNodeProcIds.has(selectedProcId)) return true;
|
|
|
+ if (selectedNode && selectedCapId && !directNodeCapIds.has(selectedCapId)) return true;
|
|
|
+ if (selectedNode && selectedToolId && !directNodeToolIds.has(selectedToolId)) return true;
|
|
|
+
|
|
|
+ if (selectedReqId && selectedProcId && !selectedReqProcIds.has(selectedProcId)) return true;
|
|
|
+ if (selectedReqId && selectedCapId && !selectedReqCapabilityIds.has(selectedCapId)) return true;
|
|
|
+ if (selectedReqId && selectedToolId && !selectedReqToolIds.has(selectedToolId)) return true;
|
|
|
+ if (selectedReqId && selectedItemsetId && !(itemsetReqIdsMap.get(String(selectedItemsetId)) || new Set()).has(selectedReqId)) return true;
|
|
|
+
|
|
|
+ if (selectedProcId && selectedCapId && !selectedProcCapabilityIds.has(selectedCapId)) return true;
|
|
|
+ if (selectedProcId && selectedToolId) {
|
|
|
+ const tool = visibleData.tools.find(t => t.id === selectedToolId);
|
|
|
+ if (tool && !(tool.capability_ids || []).some((cid: string) => selectedProcCapabilityIds.has(cid))) return true;
|
|
|
+ }
|
|
|
+ if (selectedProcId && selectedItemsetId) {
|
|
|
+ const proc = dbData.procs.find((item) => item.id === selectedProcId);
|
|
|
+ if (proc && !(proc.requirement_ids || []).some((rid: string) => selectedItemsetReqIds?.has(rid))) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selectedCapId && selectedToolId) {
|
|
|
+ const tool = visibleData.tools.find(t => t.id === selectedToolId);
|
|
|
+ if (tool && !(tool.capability_ids || []).includes(selectedCapId)) return true;
|
|
|
+ }
|
|
|
+ if (selectedCapId && selectedItemsetId) {
|
|
|
+ const cap = allCaps.find((c: any) => c.id === selectedCapId);
|
|
|
+ if (cap && !(cap.requirement_ids || []).some((rid: string) => selectedItemsetReqIds?.has(rid))) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selectedToolId && selectedItemsetId) {
|
|
|
+ const tool = visibleData.tools.find(t => t.id === selectedToolId);
|
|
|
+ let found = false;
|
|
|
+ (tool?.capability_ids || []).forEach((cid: string) => {
|
|
|
+ const cap = allCaps.find((c: any) => c.id === cid);
|
|
|
+ if (cap && (cap.requirement_ids || []).some((rid: string) => selectedItemsetReqIds?.has(rid))) found = true;
|
|
|
+ });
|
|
|
+ if (!found) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }, [
|
|
|
+ selectedNode, selectedReqId, selectedProcId, selectedCapId, selectedToolId, selectedItemsetId,
|
|
|
+ directNodeReqIds, directNodeProcIds, directNodeCapIds, directNodeToolIds,
|
|
|
+ selectedReqProcIds, selectedReqCapabilityIds, selectedReqToolIds, itemsetReqIdsMap,
|
|
|
+ selectedProcCapabilityIds, visibleData.tools, selectedItemsetReqIds, dbData.procs, allCaps
|
|
|
+ ]);
|
|
|
+
|
|
|
+ const relatedItemsetIds = useMemo((): Set<string> => {
|
|
|
+ const byNode = selectedNode
|
|
|
+ ? new Set<string>(
|
|
|
+ allItemsets
|
|
|
+ .filter((itemset: any) => (itemset.leaf_names || []).some((name: string) => selectedNodeDirectNames?.has(name)))
|
|
|
+ .map((itemset: any) => String(itemset.id))
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+ const byReq = selectedReqId
|
|
|
+ ? new Set<string>(
|
|
|
+ allItemsets
|
|
|
+ .filter((itemset: any) => (itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>()).has(selectedReqId))
|
|
|
+ .map((itemset: any) => String(itemset.id))
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+ const byProc = selectedProcId
|
|
|
+ ? new Set<string>(
|
|
|
+ allItemsets
|
|
|
+ .filter((itemset: any) => {
|
|
|
+ const reqIds = itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>();
|
|
|
+ return Array.from(reqIds).some((reqId) => selectedProcRequirementIds.has(reqId));
|
|
|
+ })
|
|
|
+ .map((itemset: any) => String(itemset.id))
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+ const byCap = selectedCapId
|
|
|
+ ? new Set<string>(
|
|
|
+ allItemsets
|
|
|
+ .filter((itemset: any) => {
|
|
|
+ const reqIds = itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>();
|
|
|
+ return Array.from(reqIds).some((reqId) => selectedCapRequirementIds.has(reqId));
|
|
|
+ })
|
|
|
+ .map((itemset: any) => String(itemset.id))
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+ const byTool = selectedToolId
|
|
|
+ ? new Set<string>(
|
|
|
+ allItemsets
|
|
|
+ .filter((itemset: any) => {
|
|
|
+ const reqIds = itemsetReqIdsMap.get(String(itemset.id)) || new Set<string>();
|
|
|
+ return Array.from(reqIds).some((reqId) => selectedToolRequirementIds.has(reqId));
|
|
|
+ })
|
|
|
+ .map((itemset: any) => String(itemset.id))
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+ const byItemset = selectedItemsetId ? new Set<string>([String(selectedItemsetId)]) : null;
|
|
|
+
|
|
|
+ if (isGlobalConflict) return new Set<string>();
|
|
|
+
|
|
|
+ const activeSets = [byNode, byReq, byProc, byCap, byTool, byItemset].filter((set): set is Set<string> => !!set);
|
|
|
+ if (activeSets.length === 0) return new Set<string>();
|
|
|
+ const [first, ...rest] = activeSets;
|
|
|
+ const result = new Set<string>();
|
|
|
+ first.forEach((value) => {
|
|
|
+ if (rest.every((set) => set.has(value))) result.add(value);
|
|
|
+ });
|
|
|
+ return result;
|
|
|
+ }, [isGlobalConflict, allItemsets, itemsetReqIdsMap, selectedNode, selectedNodeDirectNames, selectedReqId, selectedProcId, selectedCapId, selectedToolId, selectedItemsetId, selectedProcRequirementIds, selectedCapRequirementIds, selectedToolRequirementIds]);
|
|
|
+
|
|
|
const relatedReqIds = useMemo((): Set<string> => {
|
|
|
+ if (isGlobalConflict) return new Set<string>();
|
|
|
const fromNode = selectedNode ? directNodeReqIds : null;
|
|
|
const fromProc = selectedProcId ? selectedProcRequirementIds : null;
|
|
|
+ const fromReq = selectedReqId ? new Set<string>([selectedReqId]) : null;
|
|
|
const fromCap = selectedCapId
|
|
|
? new Set<string>(selectedCapRequirementIds)
|
|
|
: null;
|
|
|
const fromTool = selectedToolId ? selectedToolRequirementIds : null;
|
|
|
const fromItemset = selectedItemsetId && selectedItemsetReqIds ? selectedItemsetReqIds : null;
|
|
|
- return intersectWithAllowed(intersectActiveSets(fromNode, fromProc, fromCap, fromTool, fromItemset), visibleReqIds);
|
|
|
- }, [directNodeReqIds, visibleReqIds, selectedNode, selectedProcId, selectedProcRequirementIds, selectedCapId, selectedCapRequirementIds, selectedToolId, selectedToolRequirementIds, selectedItemsetId, selectedItemsetReqIds]);
|
|
|
+ return intersectWithAllowed(intersectActiveSets(fromNode, fromProc, fromReq, fromCap, fromTool, fromItemset), visibleReqIds);
|
|
|
+ }, [directNodeReqIds, visibleReqIds, selectedNode, selectedProcId, selectedProcRequirementIds, selectedReqId, selectedCapId, selectedCapRequirementIds, selectedToolId, selectedToolRequirementIds, selectedItemsetId, selectedItemsetReqIds]);
|
|
|
|
|
|
const relatedProcIds = useMemo((): Set<string> => {
|
|
|
+ if (isGlobalConflict) return new Set<string>();
|
|
|
const fromNode = selectedNode ? directNodeProcIds : null;
|
|
|
const fromReq = selectedReqId ? selectedReqProcIds : null;
|
|
|
+ const fromProc = selectedProcId ? new Set<string>([selectedProcId]) : null;
|
|
|
const fromCap = selectedCapId ? selectedCapProcIds : null;
|
|
|
const fromTool = selectedToolId ? selectedToolProcIds : null;
|
|
|
const fromItemset = selectedItemsetId && selectedItemsetReqIds
|
|
|
? new Set<string>(dbData.procs.filter((workflow) => (workflow.requirement_ids || []).some((reqId: string) => selectedItemsetReqIds.has(reqId))).map((workflow) => workflow.id))
|
|
|
: null;
|
|
|
- return intersectWithAllowed(intersectActiveSets(fromNode, fromReq, fromCap, fromTool, fromItemset), visibleProcIds);
|
|
|
- }, [directNodeProcIds, visibleProcIds, selectedNode, selectedReqId, selectedReqProcIds, selectedCapId, selectedCapProcIds, selectedToolId, selectedToolProcIds, selectedItemsetId, selectedItemsetReqIds, dbData.procs]);
|
|
|
+ return intersectWithAllowed(intersectActiveSets(fromNode, fromReq, fromProc, fromCap, fromTool, fromItemset), visibleProcIds);
|
|
|
+ }, [directNodeProcIds, visibleProcIds, selectedNode, selectedReqId, selectedReqProcIds, selectedProcId, selectedCapId, selectedCapProcIds, selectedToolId, selectedToolProcIds, selectedItemsetId, selectedItemsetReqIds, dbData.procs]);
|
|
|
|
|
|
const relatedCapIds = useMemo((): Set<string> => {
|
|
|
+ if (isGlobalConflict) return new Set<string>();
|
|
|
const fromNode = selectedNode ? directNodeCapIds : null;
|
|
|
const fromProc = selectedProcId ? selectedProcCapabilityIds : null;
|
|
|
const fromReq = selectedReqId ? new Set<string>(selectedReqCapabilityIds) : null;
|
|
|
+ const fromCap = selectedCapId ? new Set<string>([selectedCapId]) : null;
|
|
|
const fromTool = selectedToolId ? new Set<string>(selectedToolCapabilityIds) : null;
|
|
|
const fromItemset = selectedItemsetId && selectedItemsetReqIds
|
|
|
? new Set<string>(allCaps.filter((cap: any) => (cap.requirement_ids || []).some((reqId: string) => selectedItemsetReqIds.has(reqId))).map((cap: any) => cap.id))
|
|
|
: null;
|
|
|
- return intersectWithAllowed(intersectActiveSets(fromNode, fromProc, fromReq, fromTool, fromItemset), visibleCapIds);
|
|
|
- }, [directNodeCapIds, visibleCapIds, selectedNode, selectedProcId, selectedProcCapabilityIds, selectedReqId, selectedReqCapabilityIds, selectedToolId, selectedToolCapabilityIds, selectedItemsetId, selectedItemsetReqIds, allCaps]);
|
|
|
+ return intersectWithAllowed(intersectActiveSets(fromNode, fromProc, fromReq, fromCap, fromTool, fromItemset), visibleCapIds);
|
|
|
+ }, [directNodeCapIds, visibleCapIds, selectedNode, selectedProcId, selectedProcCapabilityIds, selectedReqId, selectedReqCapabilityIds, selectedCapId, selectedToolId, selectedToolCapabilityIds, selectedItemsetId, selectedItemsetReqIds, allCaps]);
|
|
|
|
|
|
const relatedToolIds = useMemo((): Set<string> => {
|
|
|
+ if (isGlobalConflict) return new Set<string>();
|
|
|
const fromNode = selectedNode ? directNodeToolIds : null;
|
|
|
const fromProc = selectedProcId
|
|
|
? new Set<string>(visibleData.tools.filter((tool: any) => (tool.capability_ids || []).some((cid: string) => selectedProcCapabilityIds.has(cid))).map((tool: any) => tool.id))
|
|
|
: null;
|
|
|
const fromReq = selectedReqId ? selectedReqToolIds : null;
|
|
|
const fromCap = selectedCapId ? selectedCapToolIds : null;
|
|
|
+ const fromTool = selectedToolId ? new Set<string>([selectedToolId]) : null;
|
|
|
const fromItemset = selectedItemsetId && selectedItemsetReqIds
|
|
|
? new Set<string>(
|
|
|
visibleData.tools
|
|
|
@@ -2714,10 +2782,11 @@ export function Dashboard({ pendingNode, onPendingConsumed }: { pendingNode?: st
|
|
|
.map((tool: any) => tool.id)
|
|
|
)
|
|
|
: null;
|
|
|
- return intersectWithAllowed(intersectActiveSets(fromNode, fromProc, fromReq, fromCap, fromItemset), visibleToolIds);
|
|
|
+ return intersectWithAllowed(intersectActiveSets(fromNode, fromProc, fromReq, fromCap, fromTool, fromItemset), visibleToolIds);
|
|
|
}, [directNodeToolIds, visibleData.tools, visibleToolIds, selectedReqId, selectedReqToolIds, selectedCapId, selectedCapToolIds, selectedProcId, selectedProcCapabilityIds, selectedNode, selectedItemsetId, selectedItemsetReqIds, allCaps]);
|
|
|
|
|
|
const filteredData = useMemo(() => {
|
|
|
+ if (isGlobalConflict) return { reqs: [], caps: [], tools: [] };
|
|
|
const reqs = visibleData.reqs.filter((req: any) => {
|
|
|
if (!requirementMatches(req)) return false;
|
|
|
// 如果有节点选择,需求必须在 relatedReqIds 中
|
|
|
@@ -2838,6 +2907,7 @@ export function Dashboard({ pendingNode, onPendingConsumed }: { pendingNode?: st
|
|
|
}, [reqPlanBData, allItemsets, itemsetReqIdsMap, selectedReqId, collectDirectNodeIdsFromNames]);
|
|
|
|
|
|
const filteredProcItems = useMemo(() => {
|
|
|
+ if (isGlobalConflict) return [];
|
|
|
return visibleProcItems.filter((workflow) => {
|
|
|
if (selectedReqId && !(workflow.requirement_ids || []).includes(selectedReqId)) return false;
|
|
|
if (selectedProcId && workflow.id !== selectedProcId) return false;
|
|
|
@@ -3596,10 +3666,6 @@ export function Dashboard({ pendingNode, onPendingConsumed }: { pendingNode?: st
|
|
|
onSelectItemset={(itemsetId) => {
|
|
|
setSelectedItemsetId(itemsetId);
|
|
|
if (itemsetId !== null) {
|
|
|
- setSelectedReqId(null);
|
|
|
- setSelectedProcId(null);
|
|
|
- setSelectedCapId(null);
|
|
|
- setSelectedToolId(null);
|
|
|
setTreeFocusTrigger(prev => prev + 1);
|
|
|
}
|
|
|
setColumnFocusIndex(prev => ({ ...prev, pattern: 0 }));
|
|
|
@@ -3771,6 +3837,7 @@ export function Dashboard({ pendingNode, onPendingConsumed }: { pendingNode?: st
|
|
|
dbData={{ ...dbData, caps: allCaps }}
|
|
|
nodePostsMap={drawerItem.nodePostsMap}
|
|
|
onOpenPost={(postId, post) => setSelectedPostDetail({ postId, post })}
|
|
|
+ selectedReqId={selectedReqId}
|
|
|
/>
|
|
|
)
|
|
|
)}
|