|
|
@@ -1,15 +1,12 @@
|
|
|
import { useState } from 'react'
|
|
|
-import { AXIS_ICON, AXIS_LABEL, axisRowStats, axisValues, hasFinalKnowledge, isQuerySearched, pct } from './model.js'
|
|
|
+import { AXIS_ICON, AXIS_LABEL, axisRowStats, axisValues } from './model.js'
|
|
|
|
|
|
-export default function AxisColumn({ data, family, axis, latestByQuery }) {
|
|
|
+export default function AxisColumn({ data, family, axis }) {
|
|
|
const values = axisValues(data, family, axis)
|
|
|
const tree = data.axis_trees?.[axis] || []
|
|
|
const hasTree = tree.length > 0
|
|
|
const [collapsed, setCollapsed] = useState(() => new Set())
|
|
|
const familyItems = family.items || []
|
|
|
- const searched = familyItems.filter((item) => isQuerySearched(latestByQuery.get(item.query))).length
|
|
|
- const knowledge = familyItems.filter((item) => hasFinalKnowledge(latestByQuery.get(item.query))).length
|
|
|
- const total = familyItems.length || 1
|
|
|
const toggle = (path) => {
|
|
|
setCollapsed((prev) => {
|
|
|
const next = new Set(prev)
|
|
|
@@ -20,15 +17,13 @@ export default function AxisColumn({ data, family, axis, latestByQuery }) {
|
|
|
}
|
|
|
|
|
|
const renderFlatRow = (value, index) => {
|
|
|
- const stats = axisRowStats(familyItems, latestByQuery, axis, value)
|
|
|
- const isMuted = stats.searched === 0 && index > 8
|
|
|
+ const stats = axisRowStats(familyItems, axis, value)
|
|
|
+ const isMuted = stats.total === 0 && index > 8
|
|
|
return (
|
|
|
<div className={`axv ${isMuted ? 'muted' : ''}`} key={value}>
|
|
|
<span className="tree-caret empty" />
|
|
|
<span className="tree-label">{value}</span>
|
|
|
- <span className="tree-dots">
|
|
|
- {stats.searched > 0 && <i className="dot blue" />}
|
|
|
- {stats.knowledge > 0 && <i className="dot green" />}
|
|
|
+ <span className="tree-count">
|
|
|
{stats.total > 0 && <b>{stats.total}</b>}
|
|
|
</span>
|
|
|
</div>
|
|
|
@@ -38,13 +33,13 @@ export default function AxisColumn({ data, family, axis, latestByQuery }) {
|
|
|
const renderTreeNode = (node, level = 3) => {
|
|
|
const children = node.children || []
|
|
|
const childNames = children.map((child) => child.name)
|
|
|
- const stats = axisRowStats(familyItems, latestByQuery, axis, [node.name, ...childNames])
|
|
|
+ const stats = axisRowStats(familyItems, axis, [node.name, ...childNames])
|
|
|
const isCollapsed = collapsed.has(node.path)
|
|
|
const canExpand = level === 3 && children.length > 0
|
|
|
return (
|
|
|
<div className="tree-group" key={node.path}>
|
|
|
<button
|
|
|
- className={`axv tree-node level-${level} ${stats.searched === 0 ? 'muted' : ''}`}
|
|
|
+ className={`axv tree-node level-${level} ${stats.total === 0 ? 'muted' : ''}`}
|
|
|
type="button"
|
|
|
onClick={() => canExpand && toggle(node.path)}
|
|
|
>
|
|
|
@@ -52,21 +47,17 @@ export default function AxisColumn({ data, family, axis, latestByQuery }) {
|
|
|
{canExpand ? (isCollapsed ? '›' : '⌄') : ''}
|
|
|
</span>
|
|
|
<span className="tree-label">{node.name}</span>
|
|
|
- <span className="tree-dots">
|
|
|
- {stats.searched > 0 && <i className="dot blue" />}
|
|
|
- {stats.knowledge > 0 && <i className="dot green" />}
|
|
|
+ <span className="tree-count">
|
|
|
{stats.total > 0 && <b>{stats.total}</b>}
|
|
|
</span>
|
|
|
</button>
|
|
|
{canExpand && !isCollapsed && children.map((child) => {
|
|
|
- const childStats = axisRowStats(familyItems, latestByQuery, axis, child.name)
|
|
|
+ const childStats = axisRowStats(familyItems, axis, child.name)
|
|
|
return (
|
|
|
- <div className={`axv tree-node level-4 ${childStats.searched === 0 ? 'muted' : ''}`} key={child.path}>
|
|
|
+ <div className={`axv tree-node level-4 ${childStats.total === 0 ? 'muted' : ''}`} key={child.path}>
|
|
|
<span className="tree-caret empty" />
|
|
|
<span className="tree-label">{child.name}</span>
|
|
|
- <span className="tree-dots">
|
|
|
- {childStats.searched > 0 && <i className="dot blue" />}
|
|
|
- {childStats.knowledge > 0 && <i className="dot green" />}
|
|
|
+ <span className="tree-count">
|
|
|
{childStats.total > 0 && <b>{childStats.total}</b>}
|
|
|
</span>
|
|
|
</div>
|
|
|
@@ -83,20 +74,6 @@ export default function AxisColumn({ data, family, axis, latestByQuery }) {
|
|
|
<span className="axis-icon">{AXIS_ICON[axis] || axis.slice(0, 1)}</span>
|
|
|
<span>{AXIS_LABEL[axis] || axis}</span>
|
|
|
</div>
|
|
|
- <div className="axis-metrics">
|
|
|
- <div className="metric-pair">
|
|
|
- <span className="metric-blue">搜索 {pct(searched, total)}%</span>
|
|
|
- <span className="metric-green">知识 {pct(knowledge, total)}%</span>
|
|
|
- </div>
|
|
|
- <div className="mini-bars" aria-hidden="true">
|
|
|
- <span style={{ width: `${Math.min(100, pct(searched, total))}%` }} />
|
|
|
- <span style={{ width: `${Math.min(100, pct(knowledge, total))}%` }} />
|
|
|
- </div>
|
|
|
- <div className="metric-counts">
|
|
|
- <span>{searched}/{familyItems.length}</span>
|
|
|
- <span>{knowledge}/{familyItems.length}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
</div>
|
|
|
<div className="axlist">
|
|
|
{hasTree ? tree.map((node) => renderTreeNode(node)) : values.map(renderFlatRow)}
|