Skip to content

Commit

Permalink
multi: Add proposal details page.
Browse files Browse the repository at this point in the history
  • Loading branch information
victorgcramos authored Apr 29, 2022
1 parent 0d0b411 commit 0fea662
Show file tree
Hide file tree
Showing 78 changed files with 1,984 additions and 208 deletions.
19 changes: 19 additions & 0 deletions plugins-structure/apps/politeia/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = {
env: {
test: {
plugins: [
"@babel/plugin-transform-runtime",
[
"module-resolver",
{
alias: {
"@politeiagui/core": "../../packages/core/src",
"@politeiagui/core/client": "../../packages/core/src/client",
},
},
],
],
presets: ["@babel/preset-react", "@babel/preset-env"],
},
},
};
17 changes: 5 additions & 12 deletions plugins-structure/apps/politeia/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@
"main": "dist/main.js",
"module": "src/index.js",
"license": "MIT",
"babel": {
"env": {
"test": {
"plugins": [
"@babel/plugin-transform-modules-commonjs"
]
}
}
},
"scripts": {
"prettier": "prettier \"src/**/*.js\"",
"format": "yarn prettier --write",
Expand All @@ -28,15 +19,17 @@
"start": "webpack serve --config webpack.dev.js --open"
},
"dependencies": {
"@politeiagui/comments": "1.0.0",
"@politeiagui/common-ui": "1.0.0",
"@politeiagui/core": "1.0.0",
"@politeiagui/statistics": "1.0.0",
"@politeiagui/ticketvote": "1.0.0",
"@politeiagui/common-ui": "1.0.0"
"js-file-download": "^0.4.12"
},
"devDependencies": {
"webpack-bundle-analyzer": "^4.4.2",
"@babel/plugin-transform-modules-commonjs": "^7.15.4",
"@testing-library/jest-dom": "^5.14.1",
"jest-extended": "^1.0.0"
"jest-extended": "^1.0.0",
"webpack-bundle-analyzer": "^4.4.2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { Card, Modal } from "pi-ui";
import { MarkdownDiffHTML } from "@politeiagui/common-ui";

function ModalProposalDiff({ oldBody, show, newBody, onClose }) {
return (
<Modal show={show} onClose={onClose}>
<Card paddingSize="small">
<MarkdownDiffHTML oldText={oldBody} newText={newBody} />
</Card>
</Modal>
);
}

export default ModalProposalDiff;
Original file line number Diff line number Diff line change
@@ -1,47 +1,30 @@
import React from "react";
import { Button, Link, StatusTag, Text } from "pi-ui";
import { Event, Join, RecordCard } from "@politeiagui/common-ui";
import { TicketvoteRecordVoteStatusBar } from "@politeiagui/ticketvote/ui";
import {
decodeProposalRecord,
getProposalStatusTagProps,
showVoteStatusBar,
} from "./utils";
import { Button, StatusTag } from "pi-ui";
import { RecordCard } from "@politeiagui/common-ui";
import { getShortToken } from "@politeiagui/core/records/utils";
import { decodeProposalRecord, getLegacyProposalStatusTagProps } from "./utils";
import { ProposalStatusBar, ProposalSubtitle } from "./common";

const ProposalCard = ({ record, voteSummary, commentsCount = 0 }) => {
const proposal = decodeProposalRecord(record);
const statusTagProps = getProposalStatusTagProps(record, voteSummary);
const statusTagProps = getLegacyProposalStatusTagProps(record, voteSummary);
return (
<div>
<RecordCard
token={proposal.token}
titleLink={`/record/${getShortToken(proposal.token)}`}
title={proposal.name}
subtitle={
<Join>
<Link href={`user/${proposal.author.userid}`}>
{proposal.author.username}
</Link>
{proposal.timestamps.publishedat && (
<Event
event="published"
timestamp={proposal.timestamps.publishedat}
/>
)}
{proposal.timestamps.editedat && (
<Event event="edited" timestamp={proposal.timestamps.editedat} />
)}
<Text
id={`proposal-${proposal.token}-version`}
truncate
>{`version ${proposal.version}`}</Text>
</Join>
<ProposalSubtitle
userid={proposal.author.userid}
username={proposal.author.username}
publishedat={proposal.timestamps.publishedat}
editedat={proposal.timestamps.editedat}
token={proposal.token}
version={proposal.version}
/>
}
rightHeader={<StatusTag {...statusTagProps} />}
secondRow={
showVoteStatusBar(voteSummary) && (
<TicketvoteRecordVoteStatusBar ticketvoteSummary={voteSummary} />
)
}
secondRow={<ProposalStatusBar voteSummary={voteSummary} />}
footer={
<>
<span>{commentsCount} Comments</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React from "react";
import {
MarkdownRenderer,
RecordCard,
RecordToken,
useModal,
} from "@politeiagui/common-ui";
import { decodeProposalRecord } from "./utils";
import {
ProposalDownloads,
ProposalMetadata,
ProposalStatusBar,
ProposalStatusTag,
ProposalSubtitle,
} from "./common";
import { Button, ButtonIcon } from "pi-ui";
import { getShortToken } from "@politeiagui/core/records/utils";
import styles from "./styles.module.css";
import ModalProposalDiff from "./ModalProposalDiff";

const ProposalDetails = ({
record,
voteSummary,
piSummary,
onFetchRecordTimestamps,
onFetchVersion,
}) => {
const [open] = useModal();

const proposalDetails = decodeProposalRecord(record);
function handleShowRawMarkdown() {
window.location.pathname = `/record/${getShortToken(
proposalDetails.token
)}/raw`;
}
async function handleFetchVersion(version) {
const proposalVersion = await onFetchVersion(version);
const { body: oldBody } = decodeProposalRecord(proposalVersion);
const { body: newBody } = proposalDetails;
open(ModalProposalDiff, { oldBody, newBody });
}

return (
<div>
<RecordCard
token={proposalDetails.token}
title={proposalDetails.name}
subtitle={
<ProposalSubtitle
userid={proposalDetails.author.userid}
username={proposalDetails.author.username}
publishedat={proposalDetails.timestamps.publishedat}
editedat={proposalDetails.timestamps.editedat}
token={proposalDetails.token}
version={proposalDetails.version}
onChangeVersion={handleFetchVersion}
/>
}
rightHeader={<ProposalStatusTag piSummary={piSummary} />}
secondRow={
<div className={styles.secondRow}>
<RecordToken token={proposalDetails.token} isCopyable={true} />
<ProposalStatusBar voteSummary={voteSummary} />
<ProposalMetadata metadata={proposalDetails.proposalMetadata} />
</div>
}
thirdRow={<MarkdownRenderer body={proposalDetails.body} />}
fourthRow={
<>
<Button>Click Me</Button>
<Button kind="secondary"> Click Again</Button>
</>
}
footer={
<>
<ProposalDownloads
record={record}
onFetchRecordTimestamps={onFetchRecordTimestamps}
/>
<div className={styles.footerButtons}>
<ButtonIcon
type="markdown"
onClick={handleShowRawMarkdown}
viewBox="0 0 208 128"
/>
<ButtonIcon type="link" onClick={handleShowRawMarkdown} />
</div>
</>
}
/>
</div>
);
};

export default ProposalDetails;
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@ import { RecordCard } from "@politeiagui/common-ui";
import styles from "./styles.module.css";

const Block = () => <div className={styles.block} />;
const BigBlock = () => (
<div style={{ height: "30rem" }} className={styles.block} />
);
const MediumBlock = () => (
<div style={{ height: "10rem", width: "50%" }} className={styles.block} />
);

function ProposalLoader() {
function ProposalLoader({ isDetails }) {
return (
<div className={styles.loaderWrapper}>
<RecordCard
title={<Block />}
titleWithoutLink
rightHeader={<Block />}
subtitle={<Block />}
thirdRow={<Block />}
secondRow={isDetails && <MediumBlock />}
thirdRow={isDetails ? <BigBlock /> : <Block />}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from "react";
import { Dropdown, DropdownItem } from "pi-ui";
import { getShortToken } from "@politeiagui/core/records/utils";
import {
DownloadCommentsBundle,
DownloadCommentsTimestamps,
} from "@politeiagui/comments/ui";
import fileDownload from "js-file-download";

const ProposalDownloads = ({ record, onFetchRecordTimestamps }) => {
if (!record) return null;

const { token } = record.censorshiprecord;
const version = record.version;
const shortToken = getShortToken(token);

function handleDownload(data, filename) {
return function onDownload() {
const dataString = JSON.stringify(data, null, 2);
fileDownload(dataString, `${filename}.json`);
};
}

async function handleFetchRecordTimestamps() {
const timestamps = await onFetchRecordTimestamps({ token, version });
return handleDownload(timestamps, `${shortToken}-v${version}-timestamps`)();
}

return (
<Dropdown title="Available Downloads" closeOnItemClick={false}>
<DropdownItem
onClick={handleDownload(record, `${shortToken}-v${version}`)}
>
Proposal Bundle
</DropdownItem>
<DropdownItem onClick={handleFetchRecordTimestamps}>
Proposal Timestamps
</DropdownItem>
<DropdownItem>
<DownloadCommentsBundle
token={token}
mode="text"
label="Comments Bundle"
/>
</DropdownItem>
<DropdownItem>
<DownloadCommentsTimestamps
token={token}
mode="text"
label="Comments Timestamps"
/>
</DropdownItem>
</Dropdown>
);
};

export default ProposalDownloads;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import { LabelValueList } from "@politeiagui/common-ui";
import {
formatDateToInternationalString,
formatUnixTimestampToObj,
usdFormatter,
} from "@politeiagui/common-ui/utils";

function getMetadataItems({ domain, amount, endDate, startDate }) {
return [
{ label: "Domain", value: domain },
{ label: "Amount", value: usdFormatter.format(amount / 100) },
{ label: "Start Date", value: startDate },
{ label: "End Date", value: endDate },
];
}

function ProposalMetadata({ metadata }) {
const { amount, startdate, enddate, domain } = metadata;
const metadataAvailable = !!amount || !!domain || !!startdate || !!enddate;
if (!metadataAvailable) return;

const startDate = formatDateToInternationalString(
(startdate && formatUnixTimestampToObj(startdate)) || {}
);
const endDate = formatDateToInternationalString(
(enddate && formatUnixTimestampToObj(enddate)) || {}
);
const items = getMetadataItems({ domain, amount, endDate, startDate });
return metadataAvailable && <LabelValueList items={items} />;
}

export default ProposalMetadata;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import { TicketvoteRecordVoteStatusBar } from "@politeiagui/ticketvote/ui";
import { showVoteStatusBar } from "../utils";

function ProposalStatusBar({ voteSummary }) {
return (
showVoteStatusBar(voteSummary) && (
<TicketvoteRecordVoteStatusBar ticketvoteSummary={voteSummary} />
)
);
}

export default ProposalStatusBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";
import { StatusTag } from "pi-ui";
import { getProposalStatusTagProps } from "../utils";

function ProposalStatusTag({ piSummary }) {
const statusTagProps = getProposalStatusTagProps(piSummary);
return <StatusTag {...statusTagProps} />;
}

export default ProposalStatusTag;
Loading

0 comments on commit 0fea662

Please sign in to comment.