-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add indicator for pending proposal #1998
Conversation
✅ Deploy Preview for decent-interface-dev ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
@DarksightKellar are you thinking that this would be a new card added to the top of the list that communicates "this is temporary until your actual proposal is visible"? |
@nicolaus-sherrill Yep, I had 2 options in mind:
This PR's set up for both, so that won't be an issue, just need to decide which is better UX |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a few minor comments
.filter(proposal => filters.includes(proposal.state!)) | ||
return (proposals || []) | ||
.filter(proposal => { | ||
removeTemporaryProposal(proposal.transactionHash!); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, at first glance it feels weird to have this state-changing code within a filter
....
I wouldn't expect a filter
to have side effects like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeahhh I was trying to avoid having run yet another loop over the proposals just to remove potentially 1 (if ever) pending proposal. Besides filter
is just a fancy way of doing map
plus manually adding to a pre-declared array based on the predicate
. I'm totally fine with it in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just don't think this code belongs here. We're way to far up at the presentation layer to be fucking around with cleaning up our localstorage state.
Could this go into the the reducer actions for when saving actual proposals into state?
const temporaryProposals = (getValue(CacheKeys.TEMP_PROPOSALS, chain.id) || | ||
[]) as TempProposalData[]; | ||
const updatedProposals = [...temporaryProposals, tempProposal]; | ||
setValue(CacheKeys.TEMP_PROPOSALS, updatedProposals, CacheExpiry.ONE_DAY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, but actually, how was the decision made to store these "temporary pending" proposals in local storage?
I understand that these will persist through a refresh, but do we really need that?
imo seems a bit overkill to utilize localstorage for this functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DarksightKellar this is probably my most important and biggest-picture question about this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I suppose this could all be implemented with "simpler" app state. But I've tested (and tasted) the ability to refresh and still seeing that persistent pending toast. I like it and don't wanna go back.
Besides, won't the logic largely be the same? The only real difference feels like it'd be where the temp data is coming from (+ the tiny extra ms needed to read/write to storage).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could go crazy and make it slightly more 'complex' and use netlify/functions and the store? though probably not worth the lift to show all viewers of pending proposals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It wouldn't make sense to show anyone other than the creator of the proposal, anything about that proposal before their RPC node picked up the block and added it to the official in-memory list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do still think localstorage is a bit excessive for this implementation, but that's on me for not being clearer on upfront on what I was expecting.
I'll need to go look at the code again that manages adding/removing from this "pending transaction" datastore in localstorage...
transactionHash: multiSigTransaction.transactionHash, | ||
transactionHash: | ||
multiSigTransaction.transactionHash || | ||
(transaction as SafeMultisigTransactionWithTransfersResponse).safeTxHash, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed? The code builds for me without this change.
Logically, I suppose the reason why it would needed is if transactionHash
is the empty string (Typescript says it's type is simply string
).
empty string is falsey
, so safeTxHash
will be used in the ||
conditional.
Smells to me like maybe this is an opportunity to tighten up some typing.
Do you follow where my head's at? and if so do you agree? If so, Please add a TODO
comment here for someone searching the codebase later for things to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is needed, yep. The typing in that case is misleading, and multiSigTransaction.transactionHash
turns out to always be an empty string (or was it undefined
?). I chose not to replace the line with transactionHash: (transaction as SafeMultisigTransactionWithTransfersResponse).safeTxHash
in case there's some legacy reasoning behind the choice in the first place.
I'll add the todo
for the team to revisit this.
@DarksightKellar - I maybe missing something but I couldn't replicate this and get the toaster to show up. I tried 4 proposals here - https://deploy-preview-1998.app.dev.decentdao.org/proposals?dao=sep:0x40C6E5eFCE3b1f101bFB59e876F14aa5455D3E19 Video here - https://decentdao.slack.com/archives/C06QZTUTKRC/p1718379588738149?thread_ts=1718379569.781799&cid=C06QZTUTKRC |
This reverts commit 266653e.
@tomstuart123 Yikes, one of the newer cleanup commits broke the cache. I've reverted -- should be working now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides some @adamgall comments - looks good! Straight to prod! 🚀
} else { | ||
transactionHash = createdEvent.transactionHash; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And then I guess I do have an outstanding question at the moment... what is going on here with finding a new use for this transactionHash
property with a brand new createdEvent
object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just a few comments and questions
Awesome, this works so smoothly for 'Create Proposal'. Thanks @DarksightKellar Last question, pre approval --> which other types of proposals should this work with? I tried it with SendAssets and it worked but not when I tried a change Safename proposal |
This is a great question and makes me question whether where else in the codebase can it go to capture all proposal creation, or does that place not exist (yet)? edit: @tomstuart123 i'm not asking you of course, just thinking out loud |
b608532
to
7a0c587
Compare
c9f86f1
to
197a3d8
Compare
ok @decentdao/engineering and @decentdao/product, this is ready for a full code re-review and UX re-test |
08c020a
to
f81788d
Compare
Nice, this works for all of the below:
Approved. Great work |
Suspect IssuesThis pull request was deployed and Sentry observed the following issues:
Did you find this useful? React with a 👍 or 👎 |
This PR temporarily caches recently created proposal data (transaction hash and metadata). The application can then read this cache and indicate to the user that there are pending proposals waiting to be shown on the UI when ready.
The cached proposal is removed when proposals are loaded and any of them has a transaction hash that matches its transaction hash.
Pending toast:

Toast dismissed when proposal shows up:

Note: the toast is a temporary workaround while waiting on @decentdao/design to finalise the actual look for pending proposal(s) UI.
closes #1983