Skip to content

Commit

Permalink
feat: view proposals (#40)
Browse files Browse the repository at this point in the history
* test(proposals): status formatting

* test(proposal): e2e

* chore: move page

* feat(proposal): basic page

* chore: install `dotenv`

* feat(vote-list): position `load more` button

* feat(proposal): layout changes

* feat(proposal): handle no votes

* feat(proposal): `<hr />`

* chore: change dev-container default URL
  • Loading branch information
colbr authored Sep 19, 2023
1 parent 500f697 commit c6f2d32
Show file tree
Hide file tree
Showing 52 changed files with 679 additions and 81 deletions.
2 changes: 1 addition & 1 deletion dev-environment/src/components/DevApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const DevApp = () => {
)}
/>
<Route>
<Redirect to={'/0.wilder/dao'} />
<Redirect to={'/0.wilder/daos'} />
</Route>
</Switch>
</>
Expand Down
4 changes: 1 addition & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ module.exports = {
// maxWorkers: "50%",

// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
moduleDirectories: ['node_modules', 'src'],

// An array of file extensions your modules use
// moduleFileExtensions: [
Expand Down
48 changes: 26 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"babel-plugin-transform-rename-import": "^2.3.0",
"concurrently": "^7.4.0",
"copyfiles": "^2.4.1",
"dotenv": "^16.3.1",
"enzyme": "^3.11.0",
"eslint": "^8.45.0",
"eslint-config-prettier": "^8.8.0",
Expand Down Expand Up @@ -103,9 +104,9 @@
"moment": "^2.29.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.3.0",
"react-query": "^3.39.1",
"react-resize-detector": "7.0.0",
"react-router-dom": "^5.3.0 || ^6.0.0",
"viem": "^1.6.4",
"wagmi": "^1.3.10",
"yup": "^0.32.11"
Expand Down
1 change: 1 addition & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ config();
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: 'tests/e2e',
timeout: 30 * 1000,
expect: {
timeout: 5000,
Expand Down
118 changes: 118 additions & 0 deletions src/features/view-dao-proposals/lib/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { getProposalStatus } from './helpers';
import { ProposalState } from '@zero-tech/zdao-sdk';

describe('getProposalStatus', () => {
describe('when proposal is not compatible', () => {
it('returns "-"', () => {
const result = getProposalStatus(
true,
true,
false,
[1, 2],
ProposalState.ACTIVE,
);
expect(result).toEqual('-');
});
});

describe('when proposal is compatible', () => {
it('returns "No Votes" when proposal is closed and has no votes', () => {
const result = getProposalStatus(
true,
false,
true,
[1, 2],
ProposalState.CLOSED,
);
expect(result).toEqual('No Votes');
});

it('returns "No Votes Yet" when proposal is active and has no votes', () => {
const result = getProposalStatus(
true,
false,
true,
[1, 2],
ProposalState.ACTIVE,
);
expect(result).toEqual('No Votes Yet');
});

it('returns "Expired" when proposal is closed and has no scores', () => {
const result = getProposalStatus(
true,
true,
true,
[],
ProposalState.CLOSED,
);
expect(result).toEqual('Expired');
});

it('returns "More Votes Needed" when proposal is active and has no scores', () => {
const result = getProposalStatus(
true,
true,
true,
[],
ProposalState.ACTIVE,
);
expect(result).toEqual('More Votes Needed');
});

it('returns "Approved" when proposal is closed, can be executed and has more votes in favor', () => {
const result = getProposalStatus(
true,
true,
true,
[2, 1],
ProposalState.CLOSED,
);
expect(result).toEqual('Approved');
});

it('returns "Denied" when proposal is closed, cannot be executed and has more votes against', () => {
const result = getProposalStatus(
false,
true,
true,
[1, 2],
ProposalState.CLOSED,
);
expect(result).toEqual('Denied');
});

it('returns "Approval Favoured" when proposal is active and has more votes in favor', () => {
const result = getProposalStatus(
true,
true,
true,
[2, 1],
ProposalState.ACTIVE,
);
expect(result).toEqual('Approval Favoured');
});

it('returns "Denial Favoured" when proposal is active and has more votes against', () => {
const result = getProposalStatus(
true,
true,
true,
[1, 2],
ProposalState.ACTIVE,
);
expect(result).toEqual('Denial Favoured');
});

it('returns "More Votes Needed" when proposal has equal votes for and against', () => {
const result = getProposalStatus(
true,
true,
true,
[1, 1],
ProposalState.ACTIVE,
);
expect(result).toEqual('More Votes Needed');
});
});
});
92 changes: 52 additions & 40 deletions src/features/view-dao-proposals/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,60 +108,72 @@ export const getSnapshotProposalLink = (
return `https://snapshot.org/#/${dao.ens}/proposal/${proposal.id}`;
};

/**
* Format proposal status
* @param proposal to format
* @returns formatted proposal status string
*/
export const formatProposalStatus = (proposal?: Proposal): string => {
if (proposal) {
if (isFromSnapshotWithMultipleChoices(proposal)) {
return '-';
}
export const getProposalStatus = (
canExecute: boolean,
hasVotes: boolean,
isCompatible: boolean,
scores: number[],
state: ProposalState,
): string => {
if (!isCompatible) {
return '-';
}

const isClosed = proposal.state === ProposalState.CLOSED;
const isClosed = state === ProposalState.CLOSED;

if (!proposal.votes) {
if (isClosed) {
return 'No Votes';
} else {
return 'No Votes Yet';
}
if (!hasVotes) {
if (isClosed) {
return 'No Votes';
} else {
return 'No Votes Yet';
}
}

if (isEmpty(proposal.scores)) {
if (isClosed) {
return 'Expired';
} else {
return 'More Votes Needed';
}
if (isEmpty(scores)) {
if (isClosed) {
return 'Expired';
} else {
return 'More Votes Needed';
}
}

if (isClosed) {
if (canExecute) {
return 'Approved';
} else {
return 'Denied';
}
}

if (scores[0] > scores[1]) {
if (isClosed) {
if (proposal.canExecute()) {
if (canExecute) {
return 'Approved';
} else {
return 'Denied';
}
}

if (proposal.scores[0] > proposal.scores[1]) {
if (isClosed) {
if (proposal.canExecute()) {
return 'Approved';
} else {
return 'Denied';
}
}
return isClosed ? 'Approved' : 'Approval Favoured';
} else if (proposal.scores[0] < proposal.scores[1]) {
return isClosed ? 'Denied' : 'Denial Favoured';
} else {
return 'More Votes Needed';
}
return isClosed ? 'Approved' : 'Approval Favoured';
} else if (scores[0] < scores[1]) {
return isClosed ? 'Denied' : 'Denial Favoured';
} else {
return 'More Votes Needed';
}
};

return '';
/**
* Format proposal status
* @param proposal to format
* @returns formatted proposal status string
*/
export const formatProposalStatus = (proposal: Proposal): string => {
return getProposalStatus(
proposal.canExecute(),
Boolean(proposal.votes),
Boolean(proposal.metadata),
proposal.scores,
proposal.state,
);
};

/**
Expand Down
Loading

0 comments on commit c6f2d32

Please sign in to comment.