diff --git a/packages/next-common/components/charts/thresholdCurve/hooks/useInnerPoints.js b/packages/next-common/components/charts/thresholdCurve/hooks/useInnerPoints.js index 015519b834..2f966b64c4 100644 --- a/packages/next-common/components/charts/thresholdCurve/hooks/useInnerPoints.js +++ b/packages/next-common/components/charts/thresholdCurve/hooks/useInnerPoints.js @@ -15,6 +15,9 @@ import { useBlockSteps } from "next-common/utils/hooks/referenda/detail/useRefer import { useMemo } from "react"; import useChainOrScanHeight from "next-common/hooks/height"; import useReferendumCurveData from "next-common/utils/hooks/referenda/detail/useReferendumCurveData"; +import useLatestBlockTime from "next-common/utils/hooks/useBlockTime"; +import useDecisionStartedTime from "next-common/utils/hooks/referenda/detail/useDecisionStartedTime"; +import { useChainSettings } from "next-common/context/chain"; export default function useInnerPoints(labels) { const approvalThreshold = useApprovalThreshold(); @@ -42,13 +45,30 @@ export default function useInnerPoints(labels) { export function useCurrentHeightPoints() { const { supportData, approvalData, labels } = useReferendumCurveData(); const currentHeight = useChainOrScanHeight(); + const currentTime = useLatestBlockTime(); const steps = useBlockSteps(); const beginHeight = useBeginHeight(); + const startedTime = useDecisionStartedTime(); + const { assethubMigration } = useChainSettings(); + const useTimeAxis = assethubMigration?.migrated; const xValue = useMemo(() => { + if (useTimeAxis && startedTime && currentTime) { + const index = Math.floor((currentTime - startedTime) / (3600 * 1000)); + return Math.min(index, labels.length - 1); + } + const index = Math.floor((currentHeight - beginHeight) / steps); return Math.min(index, labels.length - 1); - }, [beginHeight, currentHeight, labels.length, steps]); + }, [ + useTimeAxis, + beginHeight, + currentHeight, + currentTime, + labels.length, + startedTime, + steps, + ]); const [, supportInnerPoint] = useSupportPoints( xValue, diff --git a/packages/next-common/components/charts/thresholdCurve/referendaCurveChart/approvalBubbleArea/index.jsx b/packages/next-common/components/charts/thresholdCurve/referendaCurveChart/approvalBubbleArea/index.jsx index 96c27223f6..b74ab7a891 100644 --- a/packages/next-common/components/charts/thresholdCurve/referendaCurveChart/approvalBubbleArea/index.jsx +++ b/packages/next-common/components/charts/thresholdCurve/referendaCurveChart/approvalBubbleArea/index.jsx @@ -8,19 +8,36 @@ import BubbleItem from "./bubbleItem"; import useShowVoteActions from "next-common/hooks/useShowVoteActions"; import { clamp, inRange, last } from "lodash-es"; import { cn } from "next-common/utils"; +import { useTimelineData } from "next-common/context/post"; +import { useChainSettings } from "next-common/context/chain"; export default function ApprovalBubbleArea(props) { const showVoteActions = useShowVoteActions(); - if (!showVoteActions || !props.chartArea) { + if ( + !showVoteActions || + !props.chartArea || + !props.historyApprovalData?.length + ) { return null; } return ; } +function useDecisionStartedIndexer() { + const timeline = useTimelineData(); + + return (timeline ?? []).find((item) => item.name === "DecisionStarted") + ?.indexer; +} + const useApprovalBubbleData = (rangeData, historyApprovalData) => { const labelXLength = rangeData[1] - rangeData[0]; const beginHeight = useBeginHeight(); const blockStep = useBlockSteps(); + const decisionStarted = useDecisionStartedIndexer(); + const startedTime = decisionStarted?.blockTime; + const { assethubMigration } = useChainSettings(); + const useTimeAxis = assethubMigration?.migrated; const { loading, voteActions } = useReferendumActions(); @@ -36,11 +53,16 @@ const useApprovalBubbleData = (rangeData, historyApprovalData) => { } }; return voteActions - .sort((a, b) => a.indexer.blockHeight - b.indexer.blockHeight) + .sort((a, b) => + useTimeAxis + ? a.indexer.blockTime - b.indexer.blockTime + : a.indexer.blockHeight - b.indexer.blockHeight, + ) .map((item) => { const { data, type, who } = item; - const blockHeight = item.indexer.blockHeight; - const currentStep = (blockHeight - beginHeight) / blockStep; + const currentStep = useTimeAxis + ? (item.indexer.blockTime - startedTime) / (3600 * 1000) + : (item.indexer.blockHeight - beginHeight) / blockStep; return { data, @@ -55,13 +77,15 @@ const useApprovalBubbleData = (rangeData, historyApprovalData) => { }; }); }, [ - beginHeight, - blockStep, historyApprovalData, loading, labelXLength, rangeData, voteActions, + startedTime, + beginHeight, + blockStep, + useTimeAxis, ]); }; diff --git a/packages/next-common/components/charts/thresholdCurve/useHistoryTallyValueData.js b/packages/next-common/components/charts/thresholdCurve/useHistoryTallyValueData.js index 59cf25a406..a3397762ac 100644 --- a/packages/next-common/components/charts/thresholdCurve/useHistoryTallyValueData.js +++ b/packages/next-common/components/charts/thresholdCurve/useHistoryTallyValueData.js @@ -7,7 +7,12 @@ import { import { useMemo } from "react"; import { useReferendaTallyHistory } from "next-common/store/reducers/referenda/thresholdCurves"; import { isEmpty } from "lodash-es"; +import useLatestBlockTime from "next-common/utils/hooks/useBlockTime"; +import useDecisionStartedTime from "next-common/utils/hooks/referenda/detail/useDecisionStartedTime"; import useChainOrScanHeight from "next-common/hooks/height"; +import { useChainSettings } from "next-common/context/chain"; + +const oneHour = 3600 * 1000; function calcFromOneTallyData(tally) { const { ayes, nays, support, issuance } = tally; @@ -50,7 +55,8 @@ export function calcDataFromTallyHistory( const tally = tallyHistory.findLast( (tally) => tally.indexer.blockHeight <= iterHeight, - ) || last(tallyHistory); + ) || + last(tallyHistory); let { currentSupport, currentApprove } = calcFromOneTallyData(tally.tally); historySupportData.push(currentSupport); @@ -68,14 +74,71 @@ export function calcDataFromTallyHistory( }; } +export function calcDataFromTallyHistoryByTime( + tallyHistory, + startedTime, + latestTime, + rangeEndTime, +) { + let historySupportData = []; + let historyApprovalData = []; + let historyAyesData = []; + let historyNaysData = []; + if (!tallyHistory || !startedTime || !latestTime || isEmpty(tallyHistory)) { + return { + historySupportData, + historyApprovalData, + historyAyesData, + historyNaysData, + }; + } + + const endTime = Math.min(latestTime, rangeEndTime); + + let iterTime = startedTime; + while (iterTime <= endTime) { + const tally = + tallyHistory.findLast((item) => item.indexer.blockTime <= iterTime) || + last(tallyHistory); + + let { currentSupport, currentApprove } = calcFromOneTallyData(tally.tally); + historySupportData.push(currentSupport); + historyApprovalData.push(currentApprove); + historyAyesData.push(tally.tally.ayes); + historyNaysData.push(tally.tally.nays); + iterTime += oneHour; + } + + return { + historySupportData, + historyApprovalData, + historyAyesData, + historyNaysData, + }; +} + export default function useHistoryTallyValueData(totalHours) { const tallyHistory = useReferendaTallyHistory(); const latestHeight = useChainOrScanHeight(); + const latestTime = useLatestBlockTime(); const blockStep = useBlockSteps(); const beginHeight = useBeginHeight(); + const startedTime = useDecisionStartedTime(); + const { assethubMigration } = useChainSettings(); + const useTimeAxis = assethubMigration?.migrated; const rangeEndHeight = beginHeight + blockStep * totalHours; + const rangeEndTime = startedTime + totalHours * oneHour; return useMemo(() => { + if (useTimeAxis) { + return calcDataFromTallyHistoryByTime( + tallyHistory, + startedTime, + latestTime, + rangeEndTime, + ); + } + return calcDataFromTallyHistory( tallyHistory, beginHeight, @@ -83,5 +146,15 @@ export default function useHistoryTallyValueData(totalHours) { blockStep, rangeEndHeight, ); - }, [tallyHistory, beginHeight, latestHeight, blockStep, rangeEndHeight]); + }, [ + useTimeAxis, + tallyHistory, + startedTime, + latestTime, + rangeEndTime, + beginHeight, + latestHeight, + blockStep, + rangeEndHeight, + ]); } diff --git a/packages/next-common/utils/hooks/referenda/detail/useDecisionStartedTime.js b/packages/next-common/utils/hooks/referenda/detail/useDecisionStartedTime.js new file mode 100644 index 0000000000..8b8876cfb9 --- /dev/null +++ b/packages/next-common/utils/hooks/referenda/detail/useDecisionStartedTime.js @@ -0,0 +1,11 @@ +import { useMemo } from "react"; +import { useTimelineData } from "next-common/context/post"; + +export default function useDecisionStartedTime() { + const timeline = useTimelineData(); + + return useMemo(() => { + return (timeline ?? []).find((item) => item.name === "DecisionStarted") + ?.indexer?.blockTime; + }, [timeline]); +}