diff --git a/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js b/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js index 5b826dfb..f65ff21d 100644 --- a/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js +++ b/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js @@ -130,33 +130,32 @@ export default function LedgerChartAddresses({ data, isLoading }) { }} style={{ width: '100%', height: '600px' }} /> -
-
-
- Description -
-
-

- The total number of active, new, and reused addresses used per - day. -

-

- Active shows the number of unique addresses used. New shows the - number of addresses created. Reused shows the number of addresses - used that were created on a previous day. -

-
- {!isLoading && ( -
- - -
- )} +
+
+ Description +
+
+

+ The total number of active, new, and reused addresses used per day. +

+

+ Active shows the number of unique addresses used. New shows the + number of addresses created. Reused shows the number of addresses + used that were created on a previous day. +

+ {!isLoading && ( +
+ + +
+ )} +
+
-
-
-
- Description -
-
+
+
+ Description +
+
+

The number of confirmed send-type blocks per day where the amount in - the block is in a given range (in Nano) -

- {!isLoading && ( -
- - -
- )} + the block is in a given range (in Nano). +

+ {!isLoading && ( +
+ + +
+ )}
) diff --git a/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js b/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js index 52ea98a4..3309d150 100644 --- a/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js +++ b/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js @@ -152,25 +152,25 @@ export default function LedgerChartBlocks({ data, isLoading }) { }} style={{ width: '100%', height: '600px' }} /> -
-
-
- Description -
-
- The number of confirmed blocks (by type) per day. -
- {!isLoading && ( -
- - -
- )} +
+
+ Description +
+
+

The number of confirmed blocks (by type) per day.

+ {!isLoading && ( +
+ + +
+ )} +
+
{ if (price_history.length === 0) { get_price_history() @@ -191,25 +196,26 @@ export default function LedgerChartDistribution({ data, isLoading, price_history }} style={{ width: '100%', height: '600px' }} /> -
-
-
- Description -
-
- The relative distribution of the supply held by addresses within specific balance ranges. -
- {!isLoading && ( -
- - -
- )} +
+
+ Description
+
+

+ The relative distribution of the supply held by addresses within + specific balance ranges. +

+
+ {!isLoading && ( +
+ + +
+ )}
) diff --git a/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js b/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js index a8171c70..6706dfd9 100644 --- a/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js +++ b/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js @@ -122,29 +122,29 @@ export default function LedgerUSDTransferred({ data, isLoading }) { }} style={{ width: '100%', height: '600px' }} /> -
-
-
- Description -
-
-

The total amount of value transferred (in USD) per day.

-

- Based on the daily closing price of Nano/USD and the total amount - of Nano transferred that day. -

-
- {!isLoading && ( -
- - -
- )} +
+
+ Description +
+
+

The total amount of value transferred (in USD) per day.

+

+ Based on the daily closing price of Nano/USD and the total amount of + Nano transferred that day. +

+ {!isLoading && ( +
+ + +
+ )} +
+
[d[0], d[1]])} label='USD Transferred Stats' diff --git a/src/views/components/ledger-chart-volume/ledger-chart-volume.js b/src/views/components/ledger-chart-volume/ledger-chart-volume.js index 1ad738f4..376de255 100644 --- a/src/views/components/ledger-chart-volume/ledger-chart-volume.js +++ b/src/views/components/ledger-chart-volume/ledger-chart-volume.js @@ -154,26 +154,28 @@ export default function LedgerChartVolume({ data, isLoading }) { }} style={{ width: '100%', height: '600px' }} /> -
-
-
- Description -
-
+
+
+ Description +
+
+

The total amount sent (in Nano) and total amount of voting weight changed per day. -

- {!isLoading && ( -
- - -
- )} +

+ {!isLoading && ( +
+ + +
+ )} +
+
- ) -} - -TabPanel.propTypes = { - children: PropTypes.element, - value: PropTypes.number, - index: PropTypes.number -} - export default function LedgerPage({ load, data, isLoading }) { - const [value, setValue] = useState(0) + const previous_filter_text = useRef('') + const [cached_open_categories, set_cached_open_categories] = useState({ + Addresses: true + }) + const [selected_chart, set_selected_chart] = useState([ + 'Addresses', + 'Address Counts' + ]) + const [filter_text, set_filter_text] = useState('') + const [open_categories, set_open_categories] = useState({ Addresses: true }) + const [filtered_categories, set_filtered_categories] = useState({}) + const [menu_open, set_menu_open] = useState(false) + const filter_input_ref = useRef(null) useEffect(() => { load() }, []) - const handleChange = (event, value) => { - setValue(value) + useEffect(() => { + if (filter_text.length > 0) { + const result = {} + + for (const key of Object.keys(categories)) { + const item = categories[key] + + if (React.isValidElement(item) && fuzzySearch(filter_text, key)) { + result[key] = item + } else { + const charts = {} + for (const chart_key of Object.keys(item)) { + if (fuzzySearch(filter_text, chart_key)) { + charts[chart_key] = item[chart_key] + } + } + if (Object.keys(charts).length > 0) { + result[key] = charts + } + } + } + + set_filtered_categories(result) + } + + if (filter_text.length && !previous_filter_text.current.length) { + set_cached_open_categories({ ...open_categories }) + } + + if (filter_text.length === 0 && previous_filter_text.current.length) { + set_open_categories(cached_open_categories) + } + + previous_filter_text.current = filter_text + }, [filter_text]) + + useEffect(() => { + if (filter_text.length > 0) { + // Uncollapse all categories when filtering + set_open_categories( + Object.keys(filtered_categories).reduce( + (acc, key) => ({ ...acc, [key]: true }), + {} + ) + ) + } + }, [filtered_categories]) + + useEffect(() => { + if (menu_open) { + setTimeout(() => { + filter_input_ref.current.focus() + }, 300) // Delay to allow for transition effects + } else { + filter_input_ref.current.blur() + set_filter_text('') + } + }, [menu_open]) + + useEffect(() => { + const updateMenuHeight = () => { + const menuElement = document.querySelector('.ledger__menu-button') + const toggleButtonElement = document.querySelector( + '.ledger__toggle-button' + ) + if (menuElement && toggleButtonElement) { + if (menu_open) { + menuElement.style.height = '' + } else { + menuElement.style.height = `${toggleButtonElement.scrollHeight}px` + } + } + } + + window.addEventListener('resize', updateMenuHeight) + updateMenuHeight() + + return () => { + window.removeEventListener('resize', updateMenuHeight) + } + }, [menu_open, selected_chart]) + + const handle_menu_toggle = () => { + set_menu_open(!menu_open) + } + + const handle_click_away = () => { + set_menu_open(false) + set_filter_text('') + } + + const toggle_category = (category) => { + set_open_categories((prev) => ({ ...prev, [category]: !prev[category] })) + } + + const categories = { + Addresses: { + 'Address Counts': ( + + ) + }, + Blocks: { + 'Block Counts': + }, + Transactions: { + 'Value Transferred': ( + + ), + 'Transfer Volume': ( + + ), + 'Transfer Amounts': ( + + ) + }, + Distribution: { + 'Address Supply Distribution': ( + + ) + } + } + + const render_category = (category, charts, depth) => { + const is_open = open_categories[category] || false + return ( + <> + toggle_category(category)} + className={`ledger__category ledger__category-depth-${depth}`}> + + + + + + + {Object.entries(charts).map(([key, value]) => { + const is_selected = + selected_chart[0] === category && selected_chart[1] === key + const item_class = is_selected ? 'ledger__chart--selected' : '' + if (React.isValidElement(value)) { + return ( + set_selected_chart([category, key])} + className={`ledger__chart ledger__category-depth-${ + depth + 1 + } ${item_class}`}> + + + ) + } else { + return render_category(key, value, depth + 1) + } + })} + + + + ) } return ( @@ -62,38 +223,49 @@ export default function LedgerPage({ load, data, isLoading }) { 'transactions' ]} /> + +
+
+ + {selected_chart.join(' > ')} +
+
+ set_filter_text(e.target.value)} + inputRef={filter_input_ref} + /> +
+
+ + {Object.entries( + filter_text.length > 0 ? filtered_categories : categories + ).map(([category, charts]) => + render_category(category, charts, 0) + )} + +
+
+
- - - - - - - - - - - - - - - - - - - - - - - - - - +
+ {selected_chart.reduce((acc, key) => acc[key], categories)} +
diff --git a/src/views/pages/ledger/ledger.styl b/src/views/pages/ledger/ledger.styl index ecbea07e..d87a296c 100644 --- a/src/views/pages/ledger/ledger.styl +++ b/src/views/pages/ledger/ledger.styl @@ -1,17 +1,62 @@ .ledger__body display flex - flex-direction column + flex-direction row padding 24px 32px - max-width 1300px - width 100% - margin 0 auto + align-items flex-start .ledger__metric + display flex + flex-direction column + flex 1 width 100% -.ledger__body-menu - background white - border-radius 4px +.ledger__category + padding-top 4px + padding-bottom 4px + border-radius 6px + .MuiTypography-root + font-size 0.875rem + line-height 1.5 + color #1C2025 + font-weight 600 + +.ledger__chart + padding-top 4px + padding-bottom 4px + border-radius 6px + .MuiTypography-root + font-size 0.875rem + line-height 1.5 + color #1C2025 + font-weight 500 + &.ledger__chart--selected + background-color hsl(210, 100%, 96%) + color hsl(210, 100%, 42%) + +.ledger__category-depth-0 + padding-left 2px + +.ledger__category-depth-1 + padding-left 36px + &:before + content: ""; + display: block; + position: absolute; + z-index: 1; + left: 9.5px; + height: 100%; + width: 1px; + opacity: 1; + background: #E5EAF2 + + &.ledger__chart--selected:before + background hsl(210, 100%, 60%) + +.ledger__category-depth-2 + padding-left 49px + +.ledger__category-depth-3 + padding-left 62px .ledger__footer margin 32px auto @@ -21,11 +66,12 @@ .ledger__chart-sections display flex flex-wrap wrap + justify-content center .ledger__chart-section - max-width 500px + max-width 300px margin 16px - flex 1 0 300px + flex 1 0 250px .ledger__chart-section-body padding 0 12px @@ -46,6 +92,78 @@ p margin-bottom 16px +.ledger__chart-description + background white + padding 16px + border-radius 4px + max-width 800px + margin 16px auto 0 + width 100% + + .section__heading span + background white + +.ledger__menu-button + opacity 1 + pointer-events all + position fixed + top 10px + left 50% + transform translateX(-50%) scale(1) + z-index 101 + background-color white + border-radius 8px + width 30% + display flex + flex-direction column + align-items stretch + cursor pointer + height 40px + transition transform 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, width 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, height 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms + overflow hidden + border 1px solid rgba(0, 0, 0, 0.23) + &:hover + border 1px solid rgba(0, 0, 0, 0.23) + box-shadow #D0D0D0 4px 4px 0px 0px + + &.ledger__menu--open + border 1px solid rgba(0, 0, 0, 0.23) + box-shadow #D0D0D0 4px 4px 0px 0px + width 60% + height 80vh // Adjust height as needed for full visibility + +.ledger__toggle-button + padding 8px 16px + border none + border-radius 4px + cursor pointer + display flex + align-items center + justify-content flex-start + &:hover + color #4A90E2 + font-weight 600 + +.ledger__filter-container + padding 0 16px + border-top 1px solid rgba(0, 0, 0, 0.23) + +.ledger__category-container + padding 0 8px + display flex + flex-direction column + overflow-y auto + border-top 1px solid rgba(0, 0, 0, 0.23) + +@media (max-width 750px) + .ledger__body + flex-direction column + .ledger__menu-button + width 60% + @media (min-width 750px) - .ledger__body-menu - margin 0 64px + .ledger__menu-button + width 30% + max-width 500px + &.ledger__menu--open + max-width 500px \ No newline at end of file