@aicupa/plugin-todo-dependency 1.0.3 → 1.0.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aicupa/plugin-todo-dependency",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Set and visualize dependencies between todo items",
5
5
  "description_zh": "设置并可视化待办事项之间的依赖关系",
6
6
  "main": "./service",
package/service.js CHANGED
@@ -54,11 +54,16 @@ module.exports = (api) => {
54
54
  const data = JSON.parse(content)
55
55
  const todotree = data.todotree
56
56
 
57
+ const allTodos = []
58
+ flattenTodos(todotree.tree, allTodos)
59
+ const existingIds = new Set(allTodos.map(t => t.id))
60
+ const validDepIds = depIds.filter(id => existingIds.has(id))
61
+
57
62
  function findAndUpdate(nodes) {
58
63
  for (const node of nodes) {
59
64
  if (node.todo && node.todo.id === todoId) {
60
- if (depIds.length > 0) {
61
- node.todo.depIds = depIds
65
+ if (validDepIds.length > 0) {
66
+ node.todo.depIds = validDepIds
62
67
  } else {
63
68
  delete node.todo.depIds
64
69
  }
package/view/index.html CHANGED
@@ -43,7 +43,8 @@
43
43
 
44
44
  #graphArea { flex: 1; overflow: auto; position: relative; background: #f7f8fa; }
45
45
  .dark #graphArea { background: #1e1e1e; }
46
- #graphContainer { position: relative; min-width: 100%; min-height: 100%; }
46
+ #graphContainer { min-width: 100%; min-height: 100%; display: flex; align-items: center; justify-content: center; }
47
+ #graphInner { position: relative; flex-shrink: 0; }
47
48
 
48
49
  .node {
49
50
  position: absolute; width: 200px; background: #fff;
@@ -241,8 +242,39 @@
241
242
  } catch { return }
242
243
  if (!data) return
243
244
 
244
- const { todos, edges } = data
245
- const nodeIds = Object.keys(todos).map(Number)
245
+ const { todos, edges: allEdges } = data
246
+
247
+ // Build adjacency (both directions) to find connected components
248
+ const allIds = new Set()
249
+ const neighbors = {}
250
+ for (const [from, to] of allEdges) {
251
+ allIds.add(from); allIds.add(to)
252
+ if (!neighbors[from]) neighbors[from] = []
253
+ if (!neighbors[to]) neighbors[to] = []
254
+ neighbors[from].push(to)
255
+ neighbors[to].push(from)
256
+ }
257
+ // BFS to find connected components, keep components that have any undone node
258
+ const visited = new Set()
259
+ const visibleIds = new Set()
260
+ for (const start of allIds) {
261
+ if (visited.has(start)) continue
262
+ const comp = []
263
+ const queue = [start]
264
+ visited.add(start)
265
+ while (queue.length) {
266
+ const cur = queue.shift()
267
+ comp.push(cur)
268
+ for (const nb of (neighbors[cur] || [])) {
269
+ if (!visited.has(nb)) { visited.add(nb); queue.push(nb) }
270
+ }
271
+ }
272
+ if (comp.some(id => !todos[id]?.done)) {
273
+ for (const id of comp) visibleIds.add(id)
274
+ }
275
+ }
276
+ const edges = allEdges.filter(([from, to]) => visibleIds.has(from) && visibleIds.has(to))
277
+ const nodeIds = [...visibleIds]
246
278
  if (!nodeIds.length) { showEmpty(); return }
247
279
 
248
280
  const { layers, hasCycle } = assignLayers(nodeIds, edges)
@@ -323,8 +355,11 @@
323
355
  function renderGraph(nodeIds, edges, positions, todoData, layout) {
324
356
  const container = document.getElementById('graphContainer')
325
357
  container.innerHTML = ''
326
- container.style.width = layout.width + 'px'
327
- container.style.height = layout.height + 'px'
358
+ const inner = document.createElement('div')
359
+ inner.id = 'graphInner'
360
+ inner.style.width = layout.width + 'px'
361
+ inner.style.height = layout.height + 'px'
362
+ container.appendChild(inner)
328
363
 
329
364
  // Build dependency map: nodeId -> [depIds]
330
365
  const depsOf = {}
@@ -382,7 +417,7 @@
382
417
  'marker-end': isBlockingEdge ? 'url(#arrow-blocked)' : 'url(#arrow)',
383
418
  }))
384
419
  }
385
- container.appendChild(svg)
420
+ inner.appendChild(svg)
386
421
 
387
422
  for (const id of nodeIds) {
388
423
  const pos = positions[id]; if (!pos) continue
@@ -431,7 +466,7 @@
431
466
  body.appendChild(sb)
432
467
  }
433
468
 
434
- el.appendChild(body); container.appendChild(el)
469
+ el.appendChild(body); inner.appendChild(el)
435
470
  }
436
471
  }
437
472