FE: user profile arbitrations tab

This commit is contained in:
Aaron 2019-02-06 16:37:45 -06:00
parent 2b78a17973
commit 048cda8216
No known key found for this signature in database
GPG Key ID: 3B5B7597106F0A0E
7 changed files with 153 additions and 4 deletions

View File

@ -65,13 +65,15 @@ def get_me():
parameter("withProposals", type=bool, required=False),
parameter("withComments", type=bool, required=False),
parameter("withFunded", type=bool, required=False),
parameter("withPending", type=bool, required=False)
parameter("withPending", type=bool, required=False),
parameter("withArbitrated", type=bool, required=False)
)
def get_user(user_id, with_proposals, with_comments, with_funded, with_pending):
def get_user(user_id, with_proposals, with_comments, with_funded, with_pending, with_arbitrated):
user = User.get_by_id(user_id)
if user:
result = user_schema.dump(user)
authed_user = get_authed_user()
is_self = authed_user and authed_user.id == user.id
if with_proposals:
proposals = Proposal.get_by_user(user)
proposals_dump = user_proposals_schema.dump(proposals)
@ -86,7 +88,7 @@ def get_user(user_id, with_proposals, with_comments, with_funded, with_pending):
comments = Comment.get_by_user(user)
comments_dump = user_comments_schema.dump(comments)
result["comments"] = comments_dump
if with_pending and authed_user and authed_user.id == user.id:
if with_pending and is_self:
pending = Proposal.get_by_user(user, [
ProposalStatus.STAKING,
ProposalStatus.PENDING,
@ -95,6 +97,8 @@ def get_user(user_id, with_proposals, with_comments, with_funded, with_pending):
])
pending_dump = user_proposals_schema.dump(pending)
result["pendingProposals"] = pending_dump
if with_arbitrated and is_self:
result["arbitrated"] = user_proposals_schema.dump(user.arbitrated_proposals)
return result
else:
message = "User with id matching {} not found".format(user_id)

View File

@ -68,6 +68,7 @@ export function getUser(address: string): Promise<{ data: User }> {
withComments: true,
withFunded: true,
withPending: true,
withArbitrated: true,
},
})
.then(res => {

View File

@ -0,0 +1,71 @@
@import '~styles/variables.less';
@small-query: ~'(max-width: 640px)';
.ProfileArbitrated {
display: flex;
padding-bottom: 1.2rem;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
margin-bottom: 1rem;
&:last-child {
border-bottom: none;
padding-bottom: none;
}
@media @small-query {
flex-direction: column;
padding-bottom: 0.6rem;
}
&-title {
font-size: 1.2rem;
font-weight: 600;
color: inherit;
display: block;
margin-bottom: 0.1rem;
}
&-block {
flex: 1 0 0%;
&:last-child {
margin-left: 1.2rem;
flex: 0 0 0%;
min-width: 15rem;
@media @small-query {
margin-left: 0;
margin-top: 0.6rem;
}
}
&.is-actions {
display: flex;
justify-content: flex-end;
align-items: center;
& button + button,
a + button {
margin-left: 0.5rem;
}
}
}
.ant-tag {
vertical-align: text-top;
}
&-status {
margin-bottom: 0.6rem;
& q {
display: block;
margin: 0.5rem;
font-style: italic;
}
& small {
opacity: 0.6;
}
}
}

View File

@ -0,0 +1,43 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { UserProposal } from 'types';
import { connect } from 'react-redux';
import { AppState } from 'store/reducers';
import './ProfileArbitrated.less';
interface OwnProps {
proposal: UserProposal;
}
interface StateProps {
user: AppState['auth']['user'];
}
type Props = OwnProps & StateProps;
class ProfileArbitrated extends React.Component<Props, {}> {
render() {
const { title, proposalId } = this.props.proposal;
return (
<div className="ProfileArbitrated">
<div className="ProfileArbitrated-block">
<Link to={`/proposals/${proposalId}`} className="ProfileArbitrated-title">
{title}
</Link>
<div className={`ProfileArbitrated-info`}>
You are the arbiter for this proposal. You are responsible for reviewing
milestone payout requests.
</div>
</div>
<div className="ProfileArbitrated-block is-actions">
{/* TODO - review milestone button & etc. */}
</div>
</div>
);
}
}
export default connect<StateProps, {}, OwnProps, AppState>(state => ({
user: state.auth.user,
}))(ProfileArbitrated);

View File

@ -26,6 +26,7 @@ import ContributionModal from 'components/ContributionModal';
import LinkableTabs from 'components/LinkableTabs';
import './style.less';
import { UserContribution } from 'types';
import ProfileArbitrated from './ProfileArbitrated';
interface StateProps {
usersMap: AppState['users']['map'];
@ -86,11 +87,19 @@ class Profile extends React.Component<Props, State> {
return <ExceptionPage code="404" desc="No user could be found" />;
}
const { proposals, pendingProposals, contributions, comments, invites } = user;
const {
proposals,
pendingProposals,
contributions,
comments,
invites,
arbitrated,
} = user;
const nonePending = pendingProposals.length === 0;
const noneCreated = proposals.length === 0;
const noneFunded = contributions.length === 0;
const noneCommented = comments.length === 0;
const noneArbitrated = arbitrated.length === 0;
const noneInvites = user.hasFetchedInvites && invites.length === 0;
return (
@ -185,6 +194,22 @@ class Profile extends React.Component<Props, State> {
</div>
</Tabs.TabPane>
)}
{isAuthedUser && (
<Tabs.TabPane
tab={TabTitle('Arbitrations', arbitrated.length)}
key="arbitrations"
>
{noneArbitrated && (
<Placeholder
title="No arbitrations"
subtitle="You are not an arbiter of any proposals"
/>
)}
{arbitrated.map(arb => (
<ProfileArbitrated key={arb.proposalId} proposal={arb} />
))}
</Tabs.TabPane>
)}
</LinkableTabs>
</div>

View File

@ -20,6 +20,7 @@ export interface UserState extends User {
isUpdating: boolean;
updateError: string | null;
pendingProposals: UserProposal[];
arbitrated: UserProposal[];
proposals: UserProposal[];
contributions: UserContribution[];
comments: UserComment[];
@ -51,6 +52,7 @@ export const INITIAL_USER_STATE: UserState = {
isUpdating: false,
updateError: null,
pendingProposals: [],
arbitrated: [],
proposals: [],
contributions: [],
comments: [],

View File

@ -29,6 +29,9 @@ export function formatUserFromGet(user: UserState) {
if (user.pendingProposals) {
user.pendingProposals = user.pendingProposals.map(bnUserProp);
}
if (user.arbitrated) {
user.arbitrated = user.arbitrated.map(bnUserProp);
}
user.proposals = user.proposals.map(bnUserProp);
user.contributions = user.contributions.map(c => {
c.amount = toZat((c.amount as any) as string);