@basic-genomics/hivtrace-viz 1.1.3 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -918,8 +918,9 @@
918
918
  var attributes = null;
919
919
 
920
920
  // 从传入的options中获取配置
921
- var enableClusterTracking = options && options.enableClusterTracking === true;
922
921
  var expandClusters = options && Array.isArray(options.expand) ? options.expand : [];
922
+ // 获取自定义上下文菜单项配置
923
+ var customContextMenuItems = options && Array.isArray(options.customContextMenuItems) ? options.customContextMenuItems : [];
923
924
 
924
925
  // 获取基因距离阈值并动态更新簇标签
925
926
  var threshold = options && typeof options.threshold === 'number' ? options.threshold : 0.015;
@@ -953,6 +954,61 @@
953
954
  }
954
955
  );
955
956
 
957
+ // 将自定义上下文菜单项赋值给 user_graph 实例
958
+ if (customContextMenuItems.length > 0) {
959
+ user_graph.customContextMenuItems = customContextMenuItems;
960
+ // 设置点击回调,通过 postMessage 通知宿主应用
961
+ user_graph.onCustomMenuItemClick = function (itemId, clusterInfo) {
962
+ // 提取节点的关键信息(避免循环引用和不可序列化的对象)
963
+ var extractNodeInfo = function (node) {
964
+ if (!node) return null;
965
+ return {
966
+ id: node.id,
967
+ // 基本属性
968
+ degree: node.degree,
969
+ // 节点属性(如果存在)
970
+ attributes: node.patient_attributes || node.attributes || undefined,
971
+ // 位置信息
972
+ x: typeof node.x === 'number' ? node.x : undefined,
973
+ y: typeof node.y === 'number' ? node.y : undefined,
974
+ // 状态信息
975
+ is_hidden: Boolean(node.is_hidden),
976
+ match_filter: Boolean(node.match_filter),
977
+ // 子簇信息(如果存在)
978
+ subcluster_id: node.subcluster_id,
979
+ subcluster_label: node.subcluster_label,
980
+ };
981
+ };
982
+
983
+ var essentialClusterData = {
984
+ cluster_id: clusterInfo?.cluster_id ?? clusterInfo?.id ?? undefined,
985
+ node_count: clusterInfo?.node_count ?? (Array.isArray(clusterInfo?.nodes) ? clusterInfo.nodes.length : 0),
986
+ cluster_size: typeof clusterInfo?.cluster_size === 'number' ? clusterInfo.cluster_size : undefined,
987
+ position: {
988
+ x: typeof clusterInfo?.x === 'number' ? clusterInfo.x : undefined,
989
+ y: typeof clusterInfo?.y === 'number' ? clusterInfo.y : undefined
990
+ },
991
+ state: {
992
+ expanded: Boolean(clusterInfo?.expanded),
993
+ fixed: Boolean(clusterInfo?.fixed)
994
+ },
995
+ // 节点 ID 列表(向后兼容)
996
+ node_ids: Array.isArray(clusterInfo?.nodes)
997
+ ? clusterInfo.nodes.map(function (node) { return node?.id }).filter(Boolean)
998
+ : [],
999
+ // 完整节点信息(用于扩展)
1000
+ nodes: Array.isArray(clusterInfo?.nodes)
1001
+ ? clusterInfo.nodes.map(extractNodeInfo).filter(Boolean)
1002
+ : []
1003
+ };
1004
+ window.parent.postMessage({
1005
+ type: 'CUSTOM_MENU_CLICK',
1006
+ itemId: itemId,
1007
+ clusterInfo: essentialClusterData
1008
+ }, '*');
1009
+ };
1010
+ }
1011
+
956
1012
  if (user_graph.is_empty()) {
957
1013
  HandleAppError(
958
1014
  "This network contains no clusters and cannot be displayed"
@@ -1125,69 +1181,6 @@
1125
1181
 
1126
1182
 
1127
1183
 
1128
- // 可配置的追踪簇回调功能 - 基于传入参数决定是否启用
1129
- if (enableClusterTracking) {
1130
- user_graph.onTrackCluster = function (clusterInfo, allData) {
1131
- try {
1132
- // 直接提取需要的数据,避免复杂的数据清理
1133
- const essentialClusterData = {
1134
- cluster_id: clusterInfo?.cluster_id ?? clusterInfo?.id ?? undefined,
1135
- node_count: clusterInfo?.node_count ?? (Array.isArray(clusterInfo?.nodes) ? clusterInfo.nodes.length : 0),
1136
- cluster_size: typeof clusterInfo?.cluster_size === 'number' ? clusterInfo.cluster_size : undefined,
1137
- position: {
1138
- x: typeof clusterInfo?.x === 'number' ? clusterInfo.x : undefined,
1139
- y: typeof clusterInfo?.y === 'number' ? clusterInfo.y : undefined
1140
- },
1141
- state: {
1142
- expanded: Boolean(clusterInfo?.expanded),
1143
- fixed: Boolean(clusterInfo?.fixed)
1144
- },
1145
- // 只提取节点ID列表,避免传递复杂对象
1146
- node_ids: Array.isArray(clusterInfo?.nodes)
1147
- ? clusterInfo.nodes.slice(0, 20).map(node => node?.id).filter(Boolean)
1148
- : []
1149
- };
1150
-
1151
- // 提取网络统计信息
1152
- const networkStats = {
1153
- total_nodes: allData?.network_info?.node_count ?? user_graph?.nodes?.length ?? 0,
1154
- total_edges: allData?.network_info?.edge_count ?? user_graph?.edges?.length ?? 0,
1155
- total_clusters: allData?.network_info?.cluster_count ?? 0
1156
- };
1157
-
1158
- // 发送轻量级、精确的数据
1159
- window.parent.postMessage({
1160
- type: 'TRACK_CLUSTER',
1161
- clusterInfo: essentialClusterData,
1162
- allData: { network_info: networkStats }
1163
- }, '*');
1164
-
1165
- } catch (error) {
1166
- console.warn('簇追踪回调处理失败:', error.message);
1167
-
1168
- // 最小化降级数据
1169
- window.parent.postMessage({
1170
- type: 'TRACK_CLUSTER',
1171
- clusterInfo: {
1172
- cluster_id: 'fallback',
1173
- node_count: 0,
1174
- cluster_size: undefined,
1175
- position: { x: undefined, y: undefined },
1176
- state: { expanded: false, fixed: false },
1177
- node_ids: []
1178
- },
1179
- allData: {
1180
- network_info: {
1181
- total_nodes: 0,
1182
- total_edges: 0,
1183
- total_clusters: 0
1184
- }
1185
- }
1186
- }, '*');
1187
- }
1188
- };
1189
- }
1190
-
1191
1184
  [
1192
1185
  "#main-tab",
1193
1186
  "#graph-tab",
@@ -1303,11 +1296,17 @@
1303
1296
  overlay.innerHTML = `
1304
1297
  <i class="fa fa-exclamation-triangle hivtrace-error-icon"></i>
1305
1298
  <div class="hivtrace-error-message">${message}</div>
1306
- <button class="hivtrace-retry-btn" onclick="location.reload()">重试</button>
1299
+ <button class="hivtrace-retry-btn" onclick="requestRetry()">重试</button>
1307
1300
  `;
1308
1301
  window.parent.postMessage({ type: 'ERROR', message: message }, '*');
1309
1302
  }
1310
1303
 
1304
+ // 请求宿主应用重试
1305
+ function requestRetry() {
1306
+ window.parent.postMessage({ type: 'HIVTRACE_RETRY' }, '*');
1307
+ }
1308
+
1309
+
1311
1310
 
1312
1311
  function in_progress() {
1313
1312
  return $(".progress").length > 0;