From 6f1c9720aa5c397f111ec18d4b73f16e235cf8b3 Mon Sep 17 00:00:00 2001 From: Sam Kuhlmann Date: Wed, 31 Aug 2022 12:39:45 -0600 Subject: [PATCH] Feature/699 proposal details overview (#767) * Publish new lib versions. (#412) * fix/fix-table-types (#354) * removed the any types from hub * renamed Table to DaoTable and DataTable to DaoTable to be more consistent with DaoCard * removed commented out DaoData type * one more comment -- thought i got both before * Fix/355 summon params mixup (#356) * more ignore * fixes bad init params order in summon tx * Feature/tag component (#349) * Created basic tag component * Added dynamic color selections for tags * Bumped versions fixed filer * Added icon support to tag component Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Jonathan Prozzi * Feature/delegate play (#357) * more ignore * fixes bad init params order in summon tx * delegate testing and subgraph field updates * finishes mapping * update dao-data query and transformer * adds delegate tag to list view and hooks up delegate filtering * refactors filter into query helper * Spencer's Summon tooltip suggestions (#370) * Spencer's Summon tooltip suggestions - Summon portion of #365 * Delimiter references #368 For now, just referencing spaces. But if tabs, commas, or other delimiters are also supported, those should be references in the tooltips as well. * Address Jord's comments Co-authored-by: Sam Kuhlmann * Fix/summon poll (#375) * more ignore * fixes bad init params order in summon tx * delegate testing and subgraph field updates * finishes mapping * update dao-data query and transformer * adds delegate tag to list view and hooks up delegate filtering * adds schema field to tx entity * updates poll for tx entity made before dao entity * Feature/alpha baal update (#376) * new abis * updates summoner tx logic and contract addresses * fixes transaction entity creation location; * fixes some test * Feature/unit utils (#380) * create custom d.ts for human-format * type and convert unit fn from V2 * readableNumber util accepts number strings, throws error if string but number string * fix 0 to 1 utils, extend MaxDecimals to shorten decimal places * refine spacer and unit symbol placement * update new card to handle new params * update table * corrections * alter d.ts file * potential solutions to ts bug * implement keating's d.ts fix * fix comment * Fix/network switcher (#381) * better error handling * fix bug * remove log * get react-table TS to stop yelling (#382) Co-authored-by: Sam Kuhlmann * Feature/hub sort (#383) * wip * gets query working on dao entity after lots of subgraph updates * updates front end for sort * fixes type issue * fixes build issue * reviewing v3 monorepo and saw some networks missing (#399) * Feature/public profile (#384) * Add some stuff * Add public profile * Add ens * Get build to pass * Update apps/hub-app/src/pages/PublicProfilePage.tsx Co-authored-by: Rowdy Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy * fixing doc display name from <[object Object]> to displayName (#402) Co-authored-by: Sam Kuhlmann * adds search (#401) * adds search wip * correctly types the onChange for the input * cleans up unsed imports * naming * Feature/public profile (#384) * Add some stuff * Add public profile * Add ens * Get build to pass * Update apps/hub-app/src/pages/PublicProfilePage.tsx Co-authored-by: Rowdy Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy * fixing doc display name from <[object Object]> to displayName (#402) Co-authored-by: Sam Kuhlmann * conflicts * correctly types the onChange for the input * cleans up unsed imports * naming * fix build error Co-authored-by: Alexander Keating Co-authored-by: Rowdy Co-authored-by: Brian Rossetti * Release/12072022 (#411) * adds search wip * correctly types the onChange for the input * cleans up unsed imports * naming * conflicts * correctly types the onChange for the input * cleans up unsed imports * naming * fix build error * feature bump Co-authored-by: Jonathan Prozzi Co-authored-by: Rowdy Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti Co-authored-by: Alexander Keating * Revert "Publish new lib versions. (#412)" This reverts commit bab7077ded01a2e5e0e4cd8ef59c4fd0fb9e4b96. * develop to master (#482) * UI/layout cleanup (#438) * run generator * import connect, theme libs. Add eindow.global. Ensure main.tsx uses React 17 API. * deletes app test * updates favicon and title * remove nx defaults * rough in layout box, target DH connect nav with class * remove even more css. World's dubest layout component * switches to connect class padding for mobile * extract base layout component to storybook * hook export chain, change name to outerlayout * extract formSegment from summon-app; replace in all instances in summon * extract split-column, replace all instances in summon * document future changes in comments * fix exports * switch core-app to nx default project * fix spacing * Fix/split column bug (#444) - fix bug * Layouts/subnav (#447) * clear out extra app.t.tsx * build sub-nav * style sub-nav * test subnav * extract subNavLink into component * subnavlink story * build subnavlink story * fix broken as prop * add mobile view, icon button trigger * add tsc command to core-app * adds human-format, removes profanity * Fix summon (#446) * Fix summon * clear out extra app.t.tsx * build sub-nav * style sub-nav * test subnav * extract subNavLink into component * subnavlink story * build subnavlink story * fix broken as prop * Fix summon * add mobile view, icon button trigger * add tsc command to core-app * adds human-format, removes profanity * add human-format to dao-data * move dts file Co-authored-by: jordan Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> * Haus layout (#451) * Publish new lib versions. (#412) * fix/fix-table-types (#354) * removed the any types from hub * renamed Table to DaoTable and DataTable to DaoTable to be more consistent with DaoCard * removed commented out DaoData type * one more comment -- thought i got both before * Fix/355 summon params mixup (#356) * more ignore * fixes bad init params order in summon tx * Feature/tag component (#349) * Created basic tag component * Added dynamic color selections for tags * Bumped versions fixed filer * Added icon support to tag component Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Jonathan Prozzi * Feature/delegate play (#357) * more ignore * fixes bad init params order in summon tx * delegate testing and subgraph field updates * finishes mapping * update dao-data query and transformer * adds delegate tag to list view and hooks up delegate filtering * refactors filter into query helper * Spencer's Summon tooltip suggestions (#370) * Spencer's Summon tooltip suggestions - Summon portion of #365 * Delimiter references #368 For now, just referencing spaces. But if tabs, commas, or other delimiters are also supported, those should be references in the tooltips as well. * Address Jord's comments Co-authored-by: Sam Kuhlmann * Fix/summon poll (#375) * more ignore * fixes bad init params order in summon tx * delegate testing and subgraph field updates * finishes mapping * update dao-data query and transformer * adds delegate tag to list view and hooks up delegate filtering * adds schema field to tx entity * updates poll for tx entity made before dao entity * Feature/alpha baal update (#376) * new abis * updates summoner tx logic and contract addresses * fixes transaction entity creation location; * fixes some test * Feature/unit utils (#380) * create custom d.ts for human-format * type and convert unit fn from V2 * readableNumber util accepts number strings, throws error if string but number string * fix 0 to 1 utils, extend MaxDecimals to shorten decimal places * refine spacer and unit symbol placement * update new card to handle new params * update table * corrections * alter d.ts file * potential solutions to ts bug * implement keating's d.ts fix * fix comment * Fix/network switcher (#381) * better error handling * fix bug * remove log * get react-table TS to stop yelling (#382) Co-authored-by: Sam Kuhlmann * Feature/hub sort (#383) * wip * gets query working on dao entity after lots of subgraph updates * updates front end for sort * fixes type issue * fixes build issue * reviewing v3 monorepo and saw some networks missing (#399) * Feature/public profile (#384) * Add some stuff * Add public profile * Add ens * Get build to pass * Update apps/hub-app/src/pages/PublicProfilePage.tsx Co-authored-by: Rowdy Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy * fixing doc display name from <[object Object]> to displayName (#402) Co-authored-by: Sam Kuhlmann * adds search (#401) * adds search wip * correctly types the onChange for the input * cleans up unsed imports * naming * Feature/public profile (#384) * Add some stuff * Add public profile * Add ens * Get build to pass * Update apps/hub-app/src/pages/PublicProfilePage.tsx Co-authored-by: Rowdy Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy * fixing doc display name from <[object Object]> to displayName (#402) Co-authored-by: Sam Kuhlmann * conflicts * correctly types the onChange for the input * cleans up unsed imports * naming * fix build error Co-authored-by: Alexander Keating Co-authored-by: Rowdy Co-authored-by: Brian Rossetti * Release/12072022 (#411) * adds search wip * correctly types the onChange for the input * cleans up unsed imports * naming * conflicts * correctly types the onChange for the input * cleans up unsed imports * naming * fix build error * feature bump Co-authored-by: Jonathan Prozzi Co-authored-by: Rowdy Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti Co-authored-by: Alexander Keating * Revert "Publish new lib versions. (#412)" This reverts commit bab7077ded01a2e5e0e4cd8ef59c4fd0fb9e4b96. * build formLayout Component * type correction * build formLayout story * rough in bicolumn layout * handle bicolumn mobile switch, finish bicolumn * fix mainlayout naming * build story for bi-column layout * build dh layout one shot? * yes, one shot * fix import * change prop name Co-authored-by: Jonathan Prozzi Co-authored-by: Alexander Keating Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti * bumping packages that were published pre revert last week - causing fialures with package publishing (#460) * removing period from info content which casues confusing tooltip (#453) Co-authored-by: Sam Kuhlmann * Feature/hub profile menu fix (#480) * fixes profile link and layout * dao list style * adds toast to share link * Readme tables preferred (#483) * adjusting breakdown of apps and libs to tables * adding additoonal app references and libs * adding timestamp and address fields to many events (#468) * adding timestamps and address fields to many events * addressing code review * shortening naming convention on proposals, top level txHash defined as txHash going forward * update version * deploy subgraph and generate query types Co-authored-by: skuhlmann Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Alexander Keating Co-authored-by: jordan Co-authored-by: Jonathan Prozzi Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy Co-authored-by: Spencer Graham * Revert "develop to master (#482)" (#492) This reverts commit 5f7d121f9c49b9559d352bb17fce3c1ec598dfbe. Co-authored-by: Sam Kuhlmann * Develop into master (#577) * Feature/form builder (#553) * Publish new lib versions. (#412) * fix/fix-table-types (#354) * removed the any types from hub * renamed Table to DaoTable and DataTable to DaoTable to be more consistent with DaoCard * removed commented out DaoData type * one more comment -- thought i got both before * Fix/355 summon params mixup (#356) * more ignore * fixes bad init params order in summon tx * Feature/tag component (#349) * Created basic tag component * Added dynamic color selections for tags * Bumped versions fixed filer * Added icon support to tag component Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Jonathan Prozzi * Feature/delegate play (#357) * more ignore * fixes bad init params order in summon tx * delegate testing and subgraph field updates * finishes mapping * update dao-data query and transformer * adds delegate tag to list view and hooks up delegate filtering * refactors filter into query helper * Spencer's Summon tooltip suggestions (#370) * Spencer's Summon tooltip suggestions - Summon portion of #365 * Delimiter references #368 For now, just referencing spaces. But if tabs, commas, or other delimiters are also supported, those should be references in the tooltips as well. * Address Jord's comments Co-authored-by: Sam Kuhlmann * Fix/summon poll (#375) * more ignore * fixes bad init params order in summon tx * delegate testing and subgraph field updates * finishes mapping * update dao-data query and transformer * adds delegate tag to list view and hooks up delegate filtering * adds schema field to tx entity * updates poll for tx entity made before dao entity * Feature/alpha baal update (#376) * new abis * updates summoner tx logic and contract addresses * fixes transaction entity creation location; * fixes some test * Feature/unit utils (#380) * create custom d.ts for human-format * type and convert unit fn from V2 * readableNumber util accepts number strings, throws error if string but number string * fix 0 to 1 utils, extend MaxDecimals to shorten decimal places * refine spacer and unit symbol placement * update new card to handle new params * update table * corrections * alter d.ts file * potential solutions to ts bug * implement keating's d.ts fix * fix comment * Fix/network switcher (#381) * better error handling * fix bug * remove log * get react-table TS to stop yelling (#382) Co-authored-by: Sam Kuhlmann * Feature/hub sort (#383) * wip * gets query working on dao entity after lots of subgraph updates * updates front end for sort * fixes type issue * fixes build issue * reviewing v3 monorepo and saw some networks missing (#399) * Feature/public profile (#384) * Add some stuff * Add public profile * Add ens * Get build to pass * Update apps/hub-app/src/pages/PublicProfilePage.tsx Co-authored-by: Rowdy Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy * fixing doc display name from <[object Object]> to displayName (#402) Co-authored-by: Sam Kuhlmann * adds search (#401) * adds search wip * correctly types the onChange for the input * cleans up unsed imports * naming * Feature/public profile (#384) * Add some stuff * Add public profile * Add ens * Get build to pass * Update apps/hub-app/src/pages/PublicProfilePage.tsx Co-authored-by: Rowdy Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy * fixing doc display name from <[object Object]> to displayName (#402) Co-authored-by: Sam Kuhlmann * conflicts * correctly types the onChange for the input * cleans up unsed imports * naming * fix build error Co-authored-by: Alexander Keating Co-authored-by: Rowdy Co-authored-by: Brian Rossetti * Release/12072022 (#411) * adds search wip * correctly types the onChange for the input * cleans up unsed imports * naming * conflicts * correctly types the onChange for the input * cleans up unsed imports * naming * fix build error * feature bump Co-authored-by: Jonathan Prozzi Co-authored-by: Rowdy Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti Co-authored-by: Alexander Keating * Revert "Publish new lib versions. (#412)" This reverts commit bab7077ded01a2e5e0e4cd8ef59c4fd0fb9e4b96. * build formLayout Component * type correction * build formLayout story * rough in bicolumn layout * handle bicolumn mobile switch, finish bicolumn * fix mainlayout naming * build story for bi-column layout * scaffold formBuilder library * rough in formBuilder * restructure types * refactor component structure * test render inputs * add core fields to builder enum * add row layout to builder * built logger, fix logger bug * add disable all functionality * handle asynchronous callback as props to form builder * remove some comments * put submit button in form footer * fix code based on review * build validation pipeline * clean form and field types * revise types again, simplify rules API * commit after refactor carnage * roll back to react-hook-form v6, finally get some traction * found source of bug, trying new rhf version * ...and the bug was slain, returned to that cold, miserable shit heap from whence it came. * reintroduce devtool and logger * build metadata form, form segment subForm component * clean, add custom submit btn text * clean * build string validations * derive validation type from function obj * wrestled types into validation system * rebuild form builder as context * build formBuilder hook, use it in the factory * create sample test * update form placement * more post merge corrections * write validation updaters and add to pipeline, test required updaters, test validation, test pipeline * try jest testing * ensure field state updates on formState change * more cleaning * reorg files * build metadata form * tweak button styles, add defaultValues to formBuilder * good place to stop * remove comments * fix Jest errors * fix field wrapper stories, update lock * may have fixed jest errors Co-authored-by: Jonathan Prozzi Co-authored-by: Alexander Keating Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti * Fix build (#563) * Fix build * Almost * More changes Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Jonathan Prozzi Co-authored-by: Sam Kuhlmann Co-authored-by: Rowdy Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti * Revert "Develop into master (#577)" This reverts commit b8644d3afa3204e0e4275b62a8e360109aac11cd. * connectedAddress votes wip * adds vote queries * prevents double list items on dao change * debugging * address previous pr feedback * type issue * gets proposal loaded * updates some tx s with prop detail schema * adds proposal details overview * cleanup * fixes unsponsored state * fixes list sort * fixes test * cleanup Co-authored-by: Jonathan Prozzi Co-authored-by: Alexander Keating Co-authored-by: Rowdy Co-authored-by: Jord <53406838+jordanlesich@users.noreply.github.com> Co-authored-by: Spencer Graham Co-authored-by: Brian Rossetti Co-authored-by: jordan --- apps/core-app/src/Routes.tsx | 3 +- .../src/components/ProposalCardOverview.tsx | 19 +++- .../components/ProposalDetailsOverview.tsx | 79 ++++++++++++++++ apps/core-app/src/contexts/DaoContext.tsx | 13 +-- apps/core-app/src/legos/tx.ts | 42 ++++++--- apps/core-app/src/pages/ProposalDetails.tsx | 90 +++++++++++++++++++ apps/core-app/src/utils/constants.ts | 9 ++ apps/core-app/src/utils/dataFetchHelpers.ts | 50 ++++++++++- apps/v3-subgraph/schema.graphql | 16 ++-- apps/v3-subgraph/src/baal-mapping.ts | 8 +- apps/v3-subgraph/src/baal-summoner-mapping.ts | 2 +- apps/v3-subgraph/src/token-mapping.ts | 6 +- apps/v3-subgraph/src/util/parser.ts | 6 +- apps/v3-subgraph/src/util/transactions.ts | 2 +- libs/dao-data/src/Query.ts | 3 + .../subgraph/queries/proposals.generated.ts | 4 +- .../src/subgraph/queries/proposals.graphql | 14 +++ libs/dao-data/src/utils/proposalFilters.ts | 2 +- libs/dao-data/src/utils/proposalsStatus.ts | 17 ++-- libs/dao-data/test/ordering.spec.ts | 2 +- 20 files changed, 334 insertions(+), 53 deletions(-) create mode 100644 apps/core-app/src/components/ProposalDetailsOverview.tsx create mode 100644 apps/core-app/src/pages/ProposalDetails.tsx diff --git a/apps/core-app/src/Routes.tsx b/apps/core-app/src/Routes.tsx index e605604aa..357665905 100644 --- a/apps/core-app/src/Routes.tsx +++ b/apps/core-app/src/Routes.tsx @@ -13,6 +13,7 @@ import FormTest from './pages/FormTest'; import Settings from './pages/Settings'; import NewProposal from './pages/NewProposal'; import UpdateSettings from './pages/UpdateSettings'; +import ProposalDetails from './pages/ProposalDetails'; const Routes = () => { return ( @@ -30,7 +31,7 @@ const Routes = () => { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/apps/core-app/src/components/ProposalCardOverview.tsx b/apps/core-app/src/components/ProposalCardOverview.tsx index a54c15f30..be4f882b3 100644 --- a/apps/core-app/src/components/ProposalCardOverview.tsx +++ b/apps/core-app/src/components/ProposalCardOverview.tsx @@ -1,7 +1,8 @@ import { useParams } from 'react-router-dom'; import styled from 'styled-components'; -import { AddressDisplay, Button, ParLg, ParMd } from '@daohaus/ui'; +import { AddressDisplay, Button, ParLg, ParMd, Link } from '@daohaus/ui'; import { + charLimit, formatShortDateTimeFromSeconds, Keychain, } from '@daohaus/common-utilities'; @@ -27,6 +28,12 @@ const SubmittedContainer = styled.div` margin-top: 2.1rem; `; +const StyledLink = styled(Link)` + :hover { + text-decoration: none; + } +`; + type ProposalCardOverviewProps = { proposal: TProposals[number]; }; @@ -34,7 +41,7 @@ type ProposalCardOverviewProps = { export const ProposalCardOverview = ({ proposal, }: ProposalCardOverviewProps) => { - const { daochain } = useParams(); + const { daochain, daoid } = useParams(); return ( @@ -43,10 +50,14 @@ export const ProposalCardOverview = ({ {proposal.proposalType} |{' '} {formatShortDateTimeFromSeconds(proposal.createdAt)} - + + + {proposal.title} - {proposal.description} + {charLimit(proposal.description, 145)} Submitted by theme.card.border} solid; + background-color: ${({ theme }: { theme: Theme }) => theme.card.hoverBg}; +`; + +const DataContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + margin-top: 3rem; +`; + +const SpacedAddressDisplay = styled(AddressDisplay)` + margin-top: 1rem; +`; + +type ProposalDetailsOverviewProps = { + proposal: TProposals[number]; +}; + +export const ProposalDetailsOverview = ({ + proposal, +}: ProposalDetailsOverviewProps) => { + const { daochain } = useParams(); + + return ( + + {proposal.description} + {proposal.contentURI && ( + + Link + + )} + +
+ Submitted by + +
+ +
+
+ ); +}; diff --git a/apps/core-app/src/contexts/DaoContext.tsx b/apps/core-app/src/contexts/DaoContext.tsx index b35c59f26..d8f8b0df6 100644 --- a/apps/core-app/src/contexts/DaoContext.tsx +++ b/apps/core-app/src/contexts/DaoContext.tsx @@ -24,6 +24,11 @@ import { useRef, } from 'react'; import { useParams } from 'react-router-dom'; +import { + DEFAULT_MEMBERS_PAGE_SIZE, + DEFAULT_PROPOSAL_PAGE_SIZE, + DEFAULT_PROPOSAL_SORT, +} from '../utils/constants'; import { loadConnectedMemberVotesList, loadDao, @@ -69,7 +74,7 @@ export const defaultDaoData = { setMembersSort: () => { return; }, - membersPaging: { offset: 0, pageSize: 25 }, + membersPaging: { offset: 0, pageSize: DEFAULT_MEMBERS_PAGE_SIZE }, membersNextPaging: undefined, setMembersPaging: () => { return; @@ -86,11 +91,11 @@ export const defaultDaoData = { setProposalsFilter: () => { return; }, - proposalsSort: undefined, + proposalsSort: DEFAULT_PROPOSAL_SORT, setProposalsSort: () => { return; }, - proposalsPaging: { offset: 0, pageSize: 3 }, + proposalsPaging: { offset: 0, pageSize: DEFAULT_PROPOSAL_PAGE_SIZE }, proposalsNextPaging: undefined, setProposalsPaging: () => { return; @@ -289,8 +294,6 @@ export const DaoContextProvider = ({ children }: DaoContextProviderProps) => { const currentDaoProposals = useRef(null); useEffect(() => { let shouldUpdate = true; - - console.log('prop useeffect fired'); if (daochain && daoid) { if ( currentDaoProposals.current && diff --git a/apps/core-app/src/legos/tx.ts b/apps/core-app/src/legos/tx.ts index da9a3b94e..65dd8e35d 100644 --- a/apps/core-app/src/legos/tx.ts +++ b/apps/core-app/src/legos/tx.ts @@ -23,6 +23,16 @@ const nestInArray = (arg: ValidArgType | ValidArgType[]): NestedArray => { export const TX: Record = { POST_SIGNAL: buildMultiCallTX({ id: 'POST_SIGNAL', + JSONDetails: { + type: 'JSONDetails', + jsonSchema: { + title: `.formValues.title`, + description: `.formValues.description`, + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, + proposalType: { type: 'static', value: 'Signal Proposal' }, + }, + }, actions: [ { contract: CONTRACT.POSTER, @@ -33,7 +43,8 @@ export const TX: Record = { jsonSchema: { title: `.formValues.title`, description: `.formValues.description`, - link: `.formValues.link`, + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Signal Proposal' }, }, }, @@ -58,7 +69,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Issue Tokens Proposal' }, }, }, @@ -88,7 +100,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Add Shaman Proposal' }, }, }, @@ -110,7 +123,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Issue ERC20 Token Funding Proposal', @@ -132,7 +146,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Issue Network Token Funding Proposal', @@ -191,7 +206,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Governance Settings Proposal' }, }, }, @@ -230,7 +246,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, vTokenTransferable: '.formValues.vStake', nvTokenTransferable: '.formValues.nvStake', proposalType: { type: 'static', value: 'Token Settings Proposal' }, @@ -264,7 +281,8 @@ export const TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Shares X Token Proposal' }, }, }, @@ -278,6 +296,8 @@ export const TX: Record = { title: '.formValues.title', description: '.formValues.description', link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'GuildKick Proposal' }, }, }, @@ -322,7 +342,8 @@ export const TABULA_TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Create Publication Proposal' }, }, }, @@ -353,7 +374,8 @@ export const TABULA_TX: Record = { jsonSchema: { title: '.formValues.title', description: '.formValues.description', - link: '.formValues.link', + contentURI: `.formValues.link`, + contentURIType: { type: 'static', value: 'url' }, proposalType: { type: 'static', value: 'Create Article Proposal' }, }, }, diff --git a/apps/core-app/src/pages/ProposalDetails.tsx b/apps/core-app/src/pages/ProposalDetails.tsx new file mode 100644 index 000000000..22816f119 --- /dev/null +++ b/apps/core-app/src/pages/ProposalDetails.tsx @@ -0,0 +1,90 @@ +import { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { useParams } from 'react-router-dom'; + +import { + BiColumnLayout, + Card, + SingleColumnLayout, + Spinner, + widthQuery, +} from '@daohaus/ui'; +import { ITransformedProposalQuery } from '@daohaus/dao-data'; +import { Keychain } from '@daohaus/common-utilities'; +import { useHausConnect } from '@daohaus/daohaus-connect-feature'; + +import { loadProposal } from '../utils/dataFetchHelpers'; +import { ProposalDetailsOverview } from '../components/ProposalDetailsOverview'; + +const OverviewCard = styled(Card)` + width: 64rem; + padding: 2rem; + border: none; + margin-bottom: 3.4rem; + @media ${widthQuery.md} { + max-width: 100%; + min-width: 0; + } +`; + +const RightCard = styled(Card)` + width: 45.7rem; + padding: 2rem; + border: none; + margin-bottom: 3.4rem; + @media ${widthQuery.md} { + max-width: 100%; + min-width: 0; + } +`; + +export function ProposalDetails() { + const { daoid, daochain, proposalId } = useParams(); + const { address } = useHausConnect(); + + const [proposal, setProposal] = useState< + ITransformedProposalQuery['proposal'] | undefined + >(); + const [proposalLoading, setProposalLoading] = useState(false); + + useEffect(() => { + let shouldUpdate = true; + if (daochain && daoid && proposalId) { + loadProposal({ + daoid, + daochain: daochain as keyof Keychain, + proposalId, + setProposal, + setProposalLoading, + shouldUpdate, + connectedAddress: address, + }); + } + return () => { + shouldUpdate = false; + }; + }, [daochain, daoid, proposalId, address]); + + if (proposalLoading) { + return ( + + + + ); + } + + return ( + + {proposal && } + + } + right={actions} + /> + ); +} + +export default ProposalDetails; diff --git a/apps/core-app/src/utils/constants.ts b/apps/core-app/src/utils/constants.ts index 5469a7334..57c32ffe2 100644 --- a/apps/core-app/src/utils/constants.ts +++ b/apps/core-app/src/utils/constants.ts @@ -1,3 +1,5 @@ +import { Ordering, Proposal_OrderBy } from '@daohaus/dao-data'; + export const PROPOSAL_FILTERS: { [key: string]: string } = { unsponsored: 'Unsponsored', voting: 'In Voting', @@ -8,3 +10,10 @@ export const PROPOSAL_FILTERS: { [key: string]: string } = { failed: 'Defeated', expired: 'Expired', }; + +export const DEFAULT_PROPOSAL_PAGE_SIZE = 10; +export const DEFAULT_MEMBERS_PAGE_SIZE = 25; +export const DEFAULT_PROPOSAL_SORT: Ordering = { + orderBy: 'proposalId', + orderDirection: 'desc', +}; diff --git a/apps/core-app/src/utils/dataFetchHelpers.ts b/apps/core-app/src/utils/dataFetchHelpers.ts index 73c3459da..7b4dbe5fe 100644 --- a/apps/core-app/src/utils/dataFetchHelpers.ts +++ b/apps/core-app/src/utils/dataFetchHelpers.ts @@ -4,6 +4,7 @@ import { FindMemberQuery, Haus, ITransformedProposalListQuery, + ITransformedProposalQuery, ListConnectedMemberProposalsQuery, ListMembersQuery, Member_Filter, @@ -96,6 +97,48 @@ export const loadMember = async ({ } }; +export const loadProposal = async ({ + daoid, + daochain, + proposalId, + setProposal, + setProposalLoading, + shouldUpdate, + connectedAddress, +}: { + daoid: string; + daochain: keyof Keychain; + proposalId: string; + setProposal: ReactSetter; + setProposalLoading: ReactSetter; + shouldUpdate: boolean; + connectedAddress?: string | null; +}) => { + try { + setProposalLoading(true); + const haus = Haus.create(); + const res = await haus.query.findProposal({ + networkId: daochain, + dao: daoid, + proposalId: proposalId.toLowerCase(), + connectedAddress, + }); + + if (res?.data?.proposal && shouldUpdate) { + setProposal(res.data.proposal); + } else if (shouldUpdate) { + setProposal(undefined); + } + } catch (error) { + console.error(error); + setProposal(undefined); + } finally { + if (shouldUpdate) { + setProposalLoading(false); + } + } +}; + export const loadMembersList = async ({ filter, ordering, @@ -157,7 +200,7 @@ export const isActiveMember = async ({ daochain: keyof Keychain; address: string; setMemberLoading: ReactSetter; -}): Promise<{ member?: FindMemberQuery['member']; error?: ErrorMessage; }> => { +}): Promise<{ member?: FindMemberQuery['member']; error?: ErrorMessage }> => { try { setMemberLoading(true); const haus = Haus.create(); @@ -167,7 +210,10 @@ export const isActiveMember = async ({ memberAddress: address.toLowerCase(), }); - if (memberRes?.data?.member && Number(memberRes?.data?.member?.shares) > 0) { + if ( + memberRes?.data?.member && + Number(memberRes?.data?.member?.shares) > 0 + ) { return { member: memberRes?.data?.member, }; diff --git a/apps/v3-subgraph/schema.graphql b/apps/v3-subgraph/schema.graphql index af22e2f79..f80c69c9f 100644 --- a/apps/v3-subgraph/schema.graphql +++ b/apps/v3-subgraph/schema.graphql @@ -2,7 +2,7 @@ type Dao @entity { "unique identifier and primary key of the entity" id: ID! "timestamp of the block when the dao was summoned" - createdAt: String! + createdAt: BigInt! "address that created the dao" createdBy: Bytes! "transaction hash of the dao contract deployment" @@ -70,7 +70,7 @@ type Proposal @entity { "unique identifier and primary key of the entity" id: ID! "block timestamp when the proposal was submitted" - createdAt: String! + createdAt: BigInt! "address that submitted the proposal" createdBy: Bytes! "related DAO entity" @@ -177,7 +177,7 @@ type Vote @entity { "transaction hash of the vote" txHash: Bytes! "block timestamp when the vote was submitted" - createdAt: String! + createdAt: BigInt! "contract address of the DAO related to this vote" daoAddress: Bytes! "indicates yes vote/no vote" @@ -192,7 +192,7 @@ type Vote @entity { type Record @entity { id: ID! - createdAt: String! + createdAt: BigInt! createdBy: Bytes! dao: Dao! tag: Bytes! @@ -205,7 +205,7 @@ type Member @entity { "unique identifier and primary key of the entity" id: ID! "block timestamp when the member entity was created (when the address first recieved shares or loot)" - createdAt: String! + createdAt: BigInt! "transaction where the member was created" txHash: Bytes! "related dao" @@ -235,7 +235,7 @@ type RageQuit @entity { "unique identifier and primary key of the entity" id: ID! "block timestamp when the member rage quit" - createdAt: String! + createdAt: BigInt! "the transaction where the RageQuit occurred" txHash: Bytes! "related DAO" @@ -256,7 +256,7 @@ type Shaman @entity { "unique identifier and primary key of the entity" id: ID! "block timestamp when the shaman was added" - createdAt: String! + createdAt: BigInt! "related DAO" dao: Dao! "address of the shaman" @@ -269,7 +269,7 @@ type EventTransaction @entity { "unique identifier and primary key of the entity" id: ID! "block timestamp of the transaction" - createdAt: String! + createdAt: BigInt! "related DAO" dao: Dao daoAddress: Bytes diff --git a/apps/v3-subgraph/src/baal-mapping.ts b/apps/v3-subgraph/src/baal-mapping.ts index 69536110d..f10bad511 100644 --- a/apps/v3-subgraph/src/baal-mapping.ts +++ b/apps/v3-subgraph/src/baal-mapping.ts @@ -105,7 +105,7 @@ export function handleShamanSet(event: ShamanSet): void { let shaman = Shaman.load(shamanId); if (shaman === null) { shaman = new Shaman(shamanId); - shaman.createdAt = event.block.timestamp.toString(); + shaman.createdAt = event.block.timestamp; shaman.dao = event.address.toHexString(); shaman.shamanAddress = event.params.shaman; } @@ -155,7 +155,7 @@ export function handleSubmitProposal(event: SubmitProposal): void { .concat(event.params.proposal.toString()); let proposal = new Proposal(proposalId); - proposal.createdAt = event.block.timestamp.toString(); + proposal.createdAt = event.block.timestamp; proposal.createdBy = event.transaction.from; proposal.txHash = event.transaction.hash; proposal.dao = event.address.toHexString(); @@ -345,7 +345,7 @@ export function handleSubmitVote(event: SubmitVote): void { let vote = new Vote(voteId); - vote.createdAt = event.block.timestamp.toString(); + vote.createdAt = event.block.timestamp; vote.daoAddress = event.address; vote.approved = event.params.approved; vote.balance = event.params.balance; @@ -398,7 +398,7 @@ export function handleRageQuit(event: Ragequit): void { let rage = new RageQuit(rageId); - rage.createdAt = event.block.timestamp.toString(); + rage.createdAt = event.block.timestamp; rage.txHash = event.transaction.hash; rage.dao = dao.id; rage.member = memberId; diff --git a/apps/v3-subgraph/src/baal-summoner-mapping.ts b/apps/v3-subgraph/src/baal-summoner-mapping.ts index 62ffed67a..8c53745ec 100644 --- a/apps/v3-subgraph/src/baal-summoner-mapping.ts +++ b/apps/v3-subgraph/src/baal-summoner-mapping.ts @@ -18,7 +18,7 @@ export function handleSummonBaal(event: SummonBaal): void { return; } - dao.createdAt = event.block.timestamp.toString(); + dao.createdAt = event.block.timestamp; dao.createdBy = event.transaction.from; dao.txHash = event.transaction.hash; dao.lootAddress = event.params.loot; diff --git a/apps/v3-subgraph/src/token-mapping.ts b/apps/v3-subgraph/src/token-mapping.ts index 4f3d1fdb7..5309b0689 100644 --- a/apps/v3-subgraph/src/token-mapping.ts +++ b/apps/v3-subgraph/src/token-mapping.ts @@ -15,7 +15,7 @@ function mintShares(event: Transfer, dao: Dao, memberId: string): void { if (member === null) { member = new Member(memberId); - member.createdAt = event.block.timestamp.toString(); + member.createdAt = event.block.timestamp; member.txHash = event.transaction.hash; member.dao = dao.id; member.memberAddress = event.params.to; @@ -65,7 +65,7 @@ function mintLoot(event: LootTransfer, dao: Dao, memberId: string): void { if (member === null) { member = new Member(memberId); - member.createdAt = event.block.timestamp.toString(); + member.createdAt = event.block.timestamp; member.txHash = event.transaction.hash; member.dao = dao.id; member.memberAddress = event.params.to; @@ -269,7 +269,7 @@ export function handleDelegateVotesChanged(event: DelegateVotesChanged): void { let member = Member.load(memberId); if (member === null) { member = new Member(memberId); - member.createdAt = event.block.timestamp.toString(); + member.createdAt = event.block.timestamp; member.dao = dao.id; member.txHash = event.transaction.hash; member.memberAddress = event.params.delegate; diff --git a/apps/v3-subgraph/src/util/parser.ts b/apps/v3-subgraph/src/util/parser.ts index 425d44e1c..fe77b89ab 100644 --- a/apps/v3-subgraph/src/util/parser.ts +++ b/apps/v3-subgraph/src/util/parser.ts @@ -86,7 +86,7 @@ export namespace parser { return false; } - entity.createdAt = event.block.timestamp.toString(); + entity.createdAt = event.block.timestamp; entity.createdBy = daoAddress; entity.dao = daoAddress.toHexString(); entity.tag = event.params.tag; @@ -128,7 +128,7 @@ export namespace parser { let entity = new Record(entityId); - entity.createdAt = event.block.timestamp.toString(); + entity.createdAt = event.block.timestamp; entity.createdBy = event.params.user; entity.dao = daoAddress; entity.tag = event.params.tag; @@ -158,7 +158,7 @@ export namespace parser { let entity = new Record(entityId); - entity.createdAt = event.block.timestamp.toString(); + entity.createdAt = event.block.timestamp; entity.createdBy = event.params.user; entity.dao = daoAddress; entity.tag = event.params.tag; diff --git a/apps/v3-subgraph/src/util/transactions.ts b/apps/v3-subgraph/src/util/transactions.ts index 33e4c51bb..c38961e95 100644 --- a/apps/v3-subgraph/src/util/transactions.ts +++ b/apps/v3-subgraph/src/util/transactions.ts @@ -7,7 +7,7 @@ export function addTransaction( dao: Bytes ): void { let transaction = new EventTransaction(tx.hash.toHex()); - transaction.createdAt = block.timestamp.toString(); + transaction.createdAt = block.timestamp; transaction.dao = dao.toHexString(); transaction.daoAddress = dao; transaction.save(); diff --git a/libs/dao-data/src/Query.ts b/libs/dao-data/src/Query.ts index aff5d7647..1e691715c 100644 --- a/libs/dao-data/src/Query.ts +++ b/libs/dao-data/src/Query.ts @@ -456,10 +456,12 @@ export default class Query { networkId, dao, proposalId, + connectedAddress, }: { networkId: keyof Keychain; dao: string; proposalId: string; + connectedAddress?: string | null; }): Promise> { const url = this.endpoints['V3_SUBGRAPH'][networkId]; if (!url) { @@ -474,6 +476,7 @@ export default class Query { FindProposalQueryVariables >(FindProposalDocument, url, networkId, { id: `${dao}-proposal-${proposalId}`, + connectedAddress, }); return { diff --git a/libs/dao-data/src/subgraph/queries/proposals.generated.ts b/libs/dao-data/src/subgraph/queries/proposals.generated.ts index 0785419b2..f06ad09d1 100644 --- a/libs/dao-data/src/subgraph/queries/proposals.generated.ts +++ b/libs/dao-data/src/subgraph/queries/proposals.generated.ts @@ -32,9 +32,9 @@ export type FindProposalQueryVariables = Types.Exact<{ }>; -export type FindProposalQuery = { proposal?: { id: string, createdAt: string, createdBy: string, txHash: string, proposalId: string, prevProposalId: string, proposalDataHash: string, proposalData: string, actionGasEstimate: string, details: string, title?: string | undefined, description?: string | undefined, proposalType: string, contentURI?: string | undefined, contentURIType?: string | undefined, sponsorTxHash?: string | undefined, sponsored: boolean, selfSponsor: boolean, sponsor?: string | undefined, sponsorTxAt?: string | undefined, votingPeriod: string, votingStarts: string, votingEnds: string, gracePeriod: string, graceEnds: string, expiration: string, cancelledTxHash?: string | undefined, cancelledBy?: string | undefined, cancelled: boolean, cancelledTxAt?: string | undefined, yesBalance: string, noBalance: string, yesVotes: string, noVotes: string, processTxHash?: string | undefined, processedBy?: string | undefined, processed: boolean, processTxAt?: string | undefined, actionFailed: boolean, passed: boolean, proposalOffering: string, maxTotalSharesAndLootAtYesVote: string, tributeToken?: string | undefined, tributeOffered?: string | undefined, tributeTokenSymbol?: string | undefined, tributeTokenDecimals?: string | undefined, tributeEscrowRecipient?: string | undefined, dao: { totalShares: string, quorumPercent: string }, votes?: Array<{ id: string, txHash: string, createdAt: string, daoAddress: string, approved: boolean, balance: string, member: { id: string, memberAddress: string } }> | undefined } | undefined }; +export type FindProposalQuery = { proposal?: { id: string, createdAt: string, createdBy: string, txHash: string, proposalId: string, prevProposalId: string, proposalDataHash: string, proposalData: string, actionGasEstimate: string, details: string, title?: string | undefined, description?: string | undefined, proposalType: string, contentURI?: string | undefined, contentURIType?: string | undefined, sponsorTxHash?: string | undefined, sponsored: boolean, selfSponsor: boolean, sponsor?: string | undefined, sponsorTxAt?: string | undefined, votingPeriod: string, votingStarts: string, votingEnds: string, gracePeriod: string, graceEnds: string, expiration: string, cancelledTxHash?: string | undefined, cancelledBy?: string | undefined, cancelled: boolean, cancelledTxAt?: string | undefined, yesBalance: string, noBalance: string, yesVotes: string, noVotes: string, processTxHash?: string | undefined, processedBy?: string | undefined, processed: boolean, processTxAt?: string | undefined, actionFailed: boolean, passed: boolean, proposalOffering: string, maxTotalSharesAndLootAtYesVote: string, tributeToken?: string | undefined, tributeOffered?: string | undefined, tributeTokenSymbol?: string | undefined, tributeTokenDecimals?: string | undefined, tributeEscrowRecipient?: string | undefined, dao: { totalShares: string, quorumPercent: string }, votes?: Array<{ id: string, txHash: string, createdAt: string, daoAddress: string, approved: boolean, balance: string, member: { id: string, memberAddress: string } }> | undefined, connectedMemberVotes?: Array<{ id: string, txHash: string, createdAt: string, daoAddress: string, approved: boolean, balance: string, member: { id: string, memberAddress: string } }> | undefined } | undefined }; export const ListProposalsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"listProposals"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"where"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Proposal_filter"}}},"defaultValue":{"kind":"ObjectValue","fields":[]}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"skip"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"0"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"100"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Proposal_orderBy"}}},"defaultValue":{"kind":"EnumValue","value":"id"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderDirection"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderDirection"}}},"defaultValue":{"kind":"EnumValue","value":"asc"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"connectedAddress"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Bytes"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"proposals"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"where"},"value":{"kind":"Variable","name":{"kind":"Name","value":"where"}}},{"kind":"Argument","name":{"kind":"Name","value":"skip"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skip"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderDirection"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderDirection"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdBy"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"proposalId"}},{"kind":"Field","name":{"kind":"Name","value":"prevProposalId"}},{"kind":"Field","name":{"kind":"Name","value":"proposalDataHash"}},{"kind":"Field","name":{"kind":"Name","value":"proposalData"}},{"kind":"Field","name":{"kind":"Name","value":"actionGasEstimate"}},{"kind":"Field","name":{"kind":"Name","value":"details"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"proposalType"}},{"kind":"Field","name":{"kind":"Name","value":"contentURI"}},{"kind":"Field","name":{"kind":"Name","value":"contentURIType"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"sponsored"}},{"kind":"Field","name":{"kind":"Name","value":"selfSponsor"}},{"kind":"Field","name":{"kind":"Name","value":"sponsor"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"votingPeriod"}},{"kind":"Field","name":{"kind":"Name","value":"votingStarts"}},{"kind":"Field","name":{"kind":"Name","value":"votingEnds"}},{"kind":"Field","name":{"kind":"Name","value":"gracePeriod"}},{"kind":"Field","name":{"kind":"Name","value":"graceEnds"}},{"kind":"Field","name":{"kind":"Name","value":"expiration"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledBy"}},{"kind":"Field","name":{"kind":"Name","value":"cancelled"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"yesBalance"}},{"kind":"Field","name":{"kind":"Name","value":"noBalance"}},{"kind":"Field","name":{"kind":"Name","value":"yesVotes"}},{"kind":"Field","name":{"kind":"Name","value":"noVotes"}},{"kind":"Field","name":{"kind":"Name","value":"processTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"processedBy"}},{"kind":"Field","name":{"kind":"Name","value":"processed"}},{"kind":"Field","name":{"kind":"Name","value":"processTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"actionFailed"}},{"kind":"Field","name":{"kind":"Name","value":"passed"}},{"kind":"Field","name":{"kind":"Name","value":"proposalOffering"}},{"kind":"Field","name":{"kind":"Name","value":"maxTotalSharesAndLootAtYesVote"}},{"kind":"Field","name":{"kind":"Name","value":"tributeToken"}},{"kind":"Field","name":{"kind":"Name","value":"tributeOffered"}},{"kind":"Field","name":{"kind":"Name","value":"tributeTokenSymbol"}},{"kind":"Field","name":{"kind":"Name","value":"tributeTokenDecimals"}},{"kind":"Field","name":{"kind":"Name","value":"tributeEscrowRecipient"}},{"kind":"Field","name":{"kind":"Name","value":"dao"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalShares"}},{"kind":"Field","name":{"kind":"Name","value":"quorumPercent"}}]}},{"kind":"Field","name":{"kind":"Name","value":"votes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"daoAddress"}},{"kind":"Field","name":{"kind":"Name","value":"approved"}},{"kind":"Field","name":{"kind":"Name","value":"balance"}},{"kind":"Field","name":{"kind":"Name","value":"member"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"memberAddress"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const ListConnectedMemberProposalsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"listConnectedMemberProposals"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"where"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Proposal_filter"}}},"defaultValue":{"kind":"ObjectValue","fields":[]}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"memberWhere"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Member_filter"}}},"defaultValue":{"kind":"ObjectValue","fields":[]}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"skip"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"0"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"100"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Proposal_orderBy"}}},"defaultValue":{"kind":"EnumValue","value":"id"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderDirection"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderDirection"}}},"defaultValue":{"kind":"EnumValue","value":"asc"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"connectedAddress"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Bytes"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"proposals"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"where"},"value":{"kind":"Variable","name":{"kind":"Name","value":"where"}}},{"kind":"Argument","name":{"kind":"Name","value":"skip"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skip"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderDirection"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderDirection"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","alias":{"kind":"Name","value":"connectedMemberVotes"},"name":{"kind":"Name","value":"votes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"where"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"member_"},"value":{"kind":"Variable","name":{"kind":"Name","value":"memberWhere"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"daoAddress"}},{"kind":"Field","name":{"kind":"Name","value":"approved"}},{"kind":"Field","name":{"kind":"Name","value":"balance"}},{"kind":"Field","name":{"kind":"Name","value":"member"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"memberAddress"}}]}}]}}]}}]}}]} as unknown as DocumentNode; -export const FindProposalDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"findProposal"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"connectedAddress"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Bytes"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"proposal"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdBy"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"proposalId"}},{"kind":"Field","name":{"kind":"Name","value":"prevProposalId"}},{"kind":"Field","name":{"kind":"Name","value":"proposalDataHash"}},{"kind":"Field","name":{"kind":"Name","value":"proposalData"}},{"kind":"Field","name":{"kind":"Name","value":"actionGasEstimate"}},{"kind":"Field","name":{"kind":"Name","value":"details"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"proposalType"}},{"kind":"Field","name":{"kind":"Name","value":"contentURI"}},{"kind":"Field","name":{"kind":"Name","value":"contentURIType"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"sponsored"}},{"kind":"Field","name":{"kind":"Name","value":"selfSponsor"}},{"kind":"Field","name":{"kind":"Name","value":"sponsor"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"votingPeriod"}},{"kind":"Field","name":{"kind":"Name","value":"votingStarts"}},{"kind":"Field","name":{"kind":"Name","value":"votingEnds"}},{"kind":"Field","name":{"kind":"Name","value":"gracePeriod"}},{"kind":"Field","name":{"kind":"Name","value":"graceEnds"}},{"kind":"Field","name":{"kind":"Name","value":"expiration"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledBy"}},{"kind":"Field","name":{"kind":"Name","value":"cancelled"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"yesBalance"}},{"kind":"Field","name":{"kind":"Name","value":"noBalance"}},{"kind":"Field","name":{"kind":"Name","value":"yesVotes"}},{"kind":"Field","name":{"kind":"Name","value":"noVotes"}},{"kind":"Field","name":{"kind":"Name","value":"processTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"processedBy"}},{"kind":"Field","name":{"kind":"Name","value":"processed"}},{"kind":"Field","name":{"kind":"Name","value":"processTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"actionFailed"}},{"kind":"Field","name":{"kind":"Name","value":"passed"}},{"kind":"Field","name":{"kind":"Name","value":"proposalOffering"}},{"kind":"Field","name":{"kind":"Name","value":"maxTotalSharesAndLootAtYesVote"}},{"kind":"Field","name":{"kind":"Name","value":"tributeToken"}},{"kind":"Field","name":{"kind":"Name","value":"tributeOffered"}},{"kind":"Field","name":{"kind":"Name","value":"tributeTokenSymbol"}},{"kind":"Field","name":{"kind":"Name","value":"tributeTokenDecimals"}},{"kind":"Field","name":{"kind":"Name","value":"tributeEscrowRecipient"}},{"kind":"Field","name":{"kind":"Name","value":"dao"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalShares"}},{"kind":"Field","name":{"kind":"Name","value":"quorumPercent"}}]}},{"kind":"Field","name":{"kind":"Name","value":"votes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"daoAddress"}},{"kind":"Field","name":{"kind":"Name","value":"approved"}},{"kind":"Field","name":{"kind":"Name","value":"balance"}},{"kind":"Field","name":{"kind":"Name","value":"member"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"memberAddress"}}]}}]}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file +export const FindProposalDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"findProposal"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"connectedAddress"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Bytes"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"proposal"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdBy"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"proposalId"}},{"kind":"Field","name":{"kind":"Name","value":"prevProposalId"}},{"kind":"Field","name":{"kind":"Name","value":"proposalDataHash"}},{"kind":"Field","name":{"kind":"Name","value":"proposalData"}},{"kind":"Field","name":{"kind":"Name","value":"actionGasEstimate"}},{"kind":"Field","name":{"kind":"Name","value":"details"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"proposalType"}},{"kind":"Field","name":{"kind":"Name","value":"contentURI"}},{"kind":"Field","name":{"kind":"Name","value":"contentURIType"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"sponsored"}},{"kind":"Field","name":{"kind":"Name","value":"selfSponsor"}},{"kind":"Field","name":{"kind":"Name","value":"sponsor"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"votingPeriod"}},{"kind":"Field","name":{"kind":"Name","value":"votingStarts"}},{"kind":"Field","name":{"kind":"Name","value":"votingEnds"}},{"kind":"Field","name":{"kind":"Name","value":"gracePeriod"}},{"kind":"Field","name":{"kind":"Name","value":"graceEnds"}},{"kind":"Field","name":{"kind":"Name","value":"expiration"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledBy"}},{"kind":"Field","name":{"kind":"Name","value":"cancelled"}},{"kind":"Field","name":{"kind":"Name","value":"cancelledTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"yesBalance"}},{"kind":"Field","name":{"kind":"Name","value":"noBalance"}},{"kind":"Field","name":{"kind":"Name","value":"yesVotes"}},{"kind":"Field","name":{"kind":"Name","value":"noVotes"}},{"kind":"Field","name":{"kind":"Name","value":"processTxHash"}},{"kind":"Field","name":{"kind":"Name","value":"processedBy"}},{"kind":"Field","name":{"kind":"Name","value":"processed"}},{"kind":"Field","name":{"kind":"Name","value":"processTxAt"}},{"kind":"Field","name":{"kind":"Name","value":"actionFailed"}},{"kind":"Field","name":{"kind":"Name","value":"passed"}},{"kind":"Field","name":{"kind":"Name","value":"proposalOffering"}},{"kind":"Field","name":{"kind":"Name","value":"maxTotalSharesAndLootAtYesVote"}},{"kind":"Field","name":{"kind":"Name","value":"tributeToken"}},{"kind":"Field","name":{"kind":"Name","value":"tributeOffered"}},{"kind":"Field","name":{"kind":"Name","value":"tributeTokenSymbol"}},{"kind":"Field","name":{"kind":"Name","value":"tributeTokenDecimals"}},{"kind":"Field","name":{"kind":"Name","value":"tributeEscrowRecipient"}},{"kind":"Field","name":{"kind":"Name","value":"dao"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalShares"}},{"kind":"Field","name":{"kind":"Name","value":"quorumPercent"}}]}},{"kind":"Field","name":{"kind":"Name","value":"votes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"daoAddress"}},{"kind":"Field","name":{"kind":"Name","value":"approved"}},{"kind":"Field","name":{"kind":"Name","value":"balance"}},{"kind":"Field","name":{"kind":"Name","value":"member"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"memberAddress"}}]}}]}},{"kind":"Field","alias":{"kind":"Name","value":"connectedMemberVotes"},"name":{"kind":"Name","value":"votes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"where"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"member_"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"memberAddress"},"value":{"kind":"Variable","name":{"kind":"Name","value":"connectedAddress"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"txHash"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"daoAddress"}},{"kind":"Field","name":{"kind":"Name","value":"approved"}},{"kind":"Field","name":{"kind":"Name","value":"balance"}},{"kind":"Field","name":{"kind":"Name","value":"member"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"memberAddress"}}]}}]}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/libs/dao-data/src/subgraph/queries/proposals.graphql b/libs/dao-data/src/subgraph/queries/proposals.graphql index fab8b1921..4687867c5 100644 --- a/libs/dao-data/src/subgraph/queries/proposals.graphql +++ b/libs/dao-data/src/subgraph/queries/proposals.graphql @@ -52,6 +52,20 @@ query listConnectedMemberProposals( query findProposal($id: ID!, $connectedAddress: Bytes) { proposal: proposal(id: $id) { ...proposalFields + connectedMemberVotes: votes( + where: { member_: { memberAddress: $connectedAddress } } + ) { + id + txHash + createdAt + daoAddress + approved + balance + member { + id + memberAddress + } + } } } diff --git a/libs/dao-data/src/utils/proposalFilters.ts b/libs/dao-data/src/utils/proposalFilters.ts index 9854f135d..9c292e59a 100644 --- a/libs/dao-data/src/utils/proposalFilters.ts +++ b/libs/dao-data/src/utils/proposalFilters.ts @@ -5,7 +5,7 @@ export const statusFilter = ( status: string, votingPlusGraceDuration?: string | number ): Proposal_Filter | undefined => { - const now = `${nowInSeconds()}`; + const now = `${nowInSeconds().toFixed()}`; switch (status) { case PROPOSAL_STATUS['unsponsored']: { diff --git a/libs/dao-data/src/utils/proposalsStatus.ts b/libs/dao-data/src/utils/proposalsStatus.ts index 9e4b2c100..3a5432a08 100644 --- a/libs/dao-data/src/utils/proposalsStatus.ts +++ b/libs/dao-data/src/utils/proposalsStatus.ts @@ -5,13 +5,15 @@ import { } from '@daohaus/common-utilities'; import { QueryProposal } from '../types'; -export const isProposalUnsponsored = (proposal: QueryProposal): boolean => - !proposal.sponsored && - !proposal.cancelled && - Number(proposal.expiration) > - Number(proposal.votingPeriod) + - Number(proposal.gracePeriod) + - nowInSeconds(); +export const isProposalUnsponsored = (proposal: QueryProposal): boolean => { + const notExpired = + Number(proposal.expiration) > 0 || + Number(proposal.expiration) < + Number(proposal.votingPeriod) + + Number(proposal.gracePeriod) + + nowInSeconds(); + return !proposal.sponsored && !proposal.cancelled && notExpired; +}; export const isProposalCancelled = (proposal: QueryProposal): boolean => proposal.cancelled; @@ -49,6 +51,7 @@ export const proposalNeedsProcessing = (proposal: QueryProposal): boolean => !proposal.processed; export const isProposalFailed = (proposal: QueryProposal): boolean => + proposal.sponsored && nowInSeconds() > Number(proposal.graceEnds) && !proposal.cancelled && (!passedQuorum(proposal) || diff --git a/libs/dao-data/test/ordering.spec.ts b/libs/dao-data/test/ordering.spec.ts index 59f5a70a8..54f5c45f0 100644 --- a/libs/dao-data/test/ordering.spec.ts +++ b/libs/dao-data/test/ordering.spec.ts @@ -11,7 +11,7 @@ describe('haus', () => { const res = await haus.query.listDaos({ networkId, - ordering: { orderBy: 'id', orderDirection: 'desc' }, + ordering: { orderBy: 'createdAt', orderDirection: 'desc' }, paging: { pageSize: 2, offset: 0 }, });