From 3473d27a86741bbe678b3d3ccf142662617b64f9 Mon Sep 17 00:00:00 2001 From: GussevPM Date: Mon, 15 Sep 2025 01:37:06 +0200 Subject: [PATCH 01/34] Add serach by address through votes, handle "failed" status, fix voting shares calculation --- components/modals/RollupRankModal.vue | 2 +- .../modules/proposal/ProposalOverview.vue | 17 ++++++++++-- .../modules/proposal/ProposalTimeline.vue | 27 +++++++------------ components/modules/proposal/VotesTable.vue | 25 ++++++++++++++--- components/modules/proposal/VotingPower.vue | 6 ++--- components/ui/Input.vue | 4 +++ services/api/proposal.js | 4 ++- services/utils/general.js | 18 +++++++++++++ services/utils/states.js | 2 ++ 9 files changed, 77 insertions(+), 28 deletions(-) diff --git a/components/modals/RollupRankModal.vue b/components/modals/RollupRankModal.vue index 5b03b4cc..57e149e0 100644 --- a/components/modals/RollupRankModal.vue +++ b/components/modals/RollupRankModal.vue @@ -143,7 +143,7 @@ watch( + --> diff --git a/components/modules/proposal/ProposalOverview.vue b/components/modules/proposal/ProposalOverview.vue index feae18d3..bd83f0bd 100644 --- a/components/modules/proposal/ProposalOverview.vue +++ b/components/modules/proposal/ProposalOverview.vue @@ -19,10 +19,10 @@ import { getProposalIcon, getProposalIconColor, getProposalType, getProposalType import { fetchProposalVotes } from "@/services/api/proposal" /** Store */ -import { useModalsStore } from "@/store/modals.store" import { useCacheStore } from "@/store/cache.store" -const modalsStore = useModalsStore() +import { useModalsStore } from "@/store/modals.store" const cacheStore = useCacheStore() +const modalsStore = useModalsStore() const route = useRoute() const router = useRouter() @@ -48,6 +48,7 @@ const defaultFilters = { no_with_veto: false, abstain: false, }, + address: "", } const { filters, setFilter, resetFilter } = useFilters(defaultFilters) const handleUpdateFilter = (target, newFilter, withRefetch) => { @@ -55,6 +56,9 @@ const handleUpdateFilter = (target, newFilter, withRefetch) => { if (withRefetch) { getVotes() page.value = 1 + } else if (target === "address" && !newFilter) { + votes.value = [] + cacheStore.current.votes = [] } } const handleResetFilters = (target, withRefetch) => { @@ -85,6 +89,14 @@ const getVotes = async () => { .filter((opt) => filters.value.option[opt]) .join(","), voter: (activeTab.value === "validators_votes" && "validator") || (activeTab.value === "addresses_votes" && "address") || null, + ...(filters.value.address + ? activeTab.value === "validators_votes" + ? { validator: filters.value.address } + : activeTab.value === "addresses_votes" + ? { address: filters.value.address } + : {} + : {} + ) }) votes.value = data.value @@ -123,6 +135,7 @@ watch( page.value = 1 resetFilter("option") + resetFilter("address") getVotes() }, diff --git a/components/modules/proposal/ProposalTimeline.vue b/components/modules/proposal/ProposalTimeline.vue index 8c993619..472a6403 100644 --- a/components/modules/proposal/ProposalTimeline.vue +++ b/components/modules/proposal/ProposalTimeline.vue @@ -2,16 +2,9 @@ /** Vendor */ import { DateTime } from "luxon" -/** Services */ -import { isMainnet } from "@/services/utils" - /** UI */ import Badge from "@/components/ui/Badge.vue" -/** Store */ -import { useAppStore } from "@/store/app.store" -const appStore = useAppStore() - const props = defineProps({ proposal: { type: Object, @@ -24,7 +17,7 @@ const expand = ref(["inactive", "active"].includes(props.proposal.status)) const getStartDate = () => { let timeToFormat = null - if (["inactive", "applied", "rejected", "removed"].includes(props.proposal.status)) { + if (["inactive", "applied", "rejected", "removed", "failed"].includes(props.proposal.status)) { timeToFormat = props.proposal.created_at } else if (props.proposal.status === "active") { timeToFormat = props.proposal.activation_time @@ -37,7 +30,7 @@ const getEndDate = () => { if (["inactive", "removed"].includes(props.proposal.status)) { timeToFormat = props.proposal.deposit_time - } else if (["applied", "rejected", "active"].includes(props.proposal.status)) { + } else if (["applied", "rejected", "active", "failed"].includes(props.proposal.status)) { timeToFormat = props.proposal.end_time } @@ -48,7 +41,7 @@ const getTimelineDuration = () => { let timeToFormat = null let timeDiffToFormat = null - if (["inactive", "applied", "rejected", "removed"].includes(props.proposal.status)) { + if (["inactive", "applied", "rejected", "removed", "failed"].includes(props.proposal.status)) { timeDiffToFormat = props.proposal.created_at } else if (props.proposal.status === "active") { timeDiffToFormat = props.proposal.activation_time @@ -56,20 +49,20 @@ const getTimelineDuration = () => { if (["inactive", "removed"].includes(props.proposal.status)) { timeToFormat = props.proposal.deposit_time - } else if (["applied", "rejected", "active"].includes(props.proposal.status)) { + } else if (["applied", "rejected", "active", "failed"].includes(props.proposal.status)) { timeToFormat = props.proposal.end_time } - return DateTime.fromISO(timeToFormat).diff(DateTime.fromISO(timeDiffToFormat), "days").toObject().days.toFixed(0) + return DateTime.fromISO(timeToFormat).diff(DateTime.fromISO(timeDiffToFormat), "days").toObject().days?.toFixed(0) } const getStartLabel = () => { if (["inactive", "removed"].includes(props.proposal.status)) return "Created at" - if (["active", "applied", "rejected"].includes(props.proposal.status)) return "Voting start" + if (["active", "applied", "rejected", "failed"].includes(props.proposal.status)) return "Voting start" } const getEndLabel = () => { if (["inactive", "removed"].includes(props.proposal.status)) return "Deposit end" - if (["active", "applied", "rejected"].includes(props.proposal.status)) return "Voting end" + if (["active", "applied", "rejected", "failed"].includes(props.proposal.status)) return "Voting end" } @@ -119,21 +112,21 @@ const getEndLabel = () => { {{ DateTime.fromISO(proposal.created_at).toFormat("FF") }} - +
Deposit end {{ DateTime.fromISO(proposal.deposit_time).toFormat("FF") }} - +
Voting started {{ DateTime.fromISO(proposal.activation_time).toFormat("FF") }} - +
End of voting diff --git a/components/modules/proposal/VotesTable.vue b/components/modules/proposal/VotesTable.vue index 1aa50f1e..59a52b4a 100644 --- a/components/modules/proposal/VotesTable.vue +++ b/components/modules/proposal/VotesTable.vue @@ -3,15 +3,15 @@ import { DateTime } from "luxon" /** Services */ -import { space, comma } from "@/services/utils" +import { comma, space, validateCelestiaAddress } from "@/services/utils" import { getVoteIcon, getVoteIconColor } from "@/services/utils/states" /** UI */ import Button from "@/components/ui/Button.vue" -import Tooltip from "@/components/ui/Tooltip.vue" -import Popover from "@/components/ui/Popover.vue" -import Radio from "@/components/ui/Radio.vue" import Checkbox from "@/components/ui/Checkbox.vue" +import Input from "@/components/ui/Input.vue" +import Popover from "@/components/ui/Popover.vue" +import Tooltip from "@/components/ui/Tooltip.vue" /** Shared Components */ import TablePlaceholderView from "@/components/shared/TablePlaceholderView.vue" @@ -60,6 +60,8 @@ const setDefaultOptionFilter = () => { const optionFilter = reactive({}) setDefaultOptionFilter() +const searchTerm = ref("") + const cachedOptionFilter = ref() const hasActiveOptionFilters = computed(() => { @@ -117,11 +119,26 @@ watch( if (!props.filters.option) setDefaultOptionFilter() }, ) +watch( + () => searchTerm.value, + () => { + if (!searchTerm.value) { + emit("onFiltersReset", "address", true) + } else if (!validateCelestiaAddress(searchTerm.value)) { + emit("updateFilters", "address", "", false) + } else { + emit("updateFilters", "address", searchTerm.value, true) + } + } +) + +