Commit f6596764 authored by TJHeeringa's avatar TJHeeringa

Fix for members/incoming

parent a0305f5d
import React, {Component} from "react";
import { Col, Row } from "reactstrap";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import PropTypes from "prop-types";
import React from "react";
export class ShortProfile extends Component {
render() {
const {profile} = this.props;
return (
<div className={"ShortProfile"}>
<p>
<Row>
<Col>{ profile.first_names } { profile.surname }</Col>
<Col>{ profile.email }</Col>
</Row>
</p>
</div>
);
}
}
export const ShortProfile = ({ profile }) => {
return (
<Grid container spacing={3}>
<Grid item>
<Typography>{ profile.first_names } { profile.surname }</Typography>
</Grid>
<Grid item>
<Typography>{ profile.email }</Typography>
</Grid>
</Grid>
);
};
ShortProfile.propTypes = {
profile: PropTypes.object.isRequired
};
\ No newline at end of file
......@@ -186,7 +186,7 @@ const API = ({ children }) => {
const api_callv4 = ({url, method, queryParams = {}, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false}={}) => {
url += Object.entries(queryParams).reduce((queryParamString, queryParam)=>(
queryParamString
? queryParams + "&" + queryParam.join("=")
? queryParamString + "&" + queryParam.join("=")
: "?" + queryParam.join("=")),
"");
return api_callv3({url, method, object, json_or_form_data, on_succes, on_failure, external});
......
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import { ShortProfile } from "App/Components/Info/ShortProfile";
import { Helper } from "App/Helper";
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { useEffect, useState } from "react";
import Container from "react-bootstrap/Container";
import { CSVLink } from "react-csv";
import { withRouter } from "react-router-dom";
import { Button, Col, Row, Spinner } from "reactstrap";
import { v4 as uuidv4 } from "uuid";
import Block from "../../Components/PageLayout/Content/Block";
import {useAlertHandler} from "../../Contexts/AlertHandler";
import {useAPI} from "../../Contexts/API";
class MembersIncoming extends Component {
constructor(props) {
super(props);
this.state = {
pendingMemberships: []
};
}
const MembersIncoming = ({ association }) => {
const API = useAPI();
componentDidMount = () => {
this.refreshPendingMemberships();
};
const [pendingMemberships, setPendingMemberships] = useState([]);
refreshPendingMemberships = () => {
return Helper.api_call(
process.env.REACT_APP_API_URL + "/memberships?status=pending?limit=5000&association__slug=" + this.props.association.slug,
"GET",
undefined,
"json",
(memberships) => {this.setState({pendingMemberships: memberships.results});}
);
const refreshPendingMemberships = () => {
API.callv4({
url: "/memberships",
queryParams: {
association__slug: association.slug,
limit: 5000,
status: "Pending"
},
method: "GET",
on_succes: (data) => {setPendingMemberships(data.results);},
on_failure: () => {}
});
};
generateCSVData = (memberships) => {
let csvData = [[]];
let headers = ["Name", "Surname", "Email"];
let data = (memberships.map(membership=>[membership.profile.first_names, membership.profile.surname, membership.profile.email]));
// run refreshPendingMemberships once on mount
useEffect(()=>refreshPendingMemberships(), []); // eslint-disable-line react-hooks/exhaustive-deps
csvData[0] = headers;
if (data !== undefined){
csvData.push(...data);
}
return csvData;
};
render() {
const { show_csv } = this.props;
return (
<Container>
<Block>
<Typography variant={"h5"}>Incoming Requests</Typography>
<hr className={"box-title-separator"}/>
<Grid>
{ pendingMemberships.map((pendingMembership, id) => (
<IncomingRequest
key={id}
membership={pendingMembership}
postPatch={refreshPendingMemberships}
/>
)) }
</Grid>
</Block>
</Container>
);
};
MembersIncoming.propTypes = {
association: PropTypes.object.isRequired
};
export default MembersIncoming;
return (
<Container>
<Block>
<div className={"RequestsNavbar"}>
<h4>INCOMING REQUESTS</h4>
</div>
<hr className={"box-title-separator"}/>
{ this.state.pendingMemberships.map((pendingMembership) => {
return <IncomingRequest
key={uuidv4()}
pendingMembership={pendingMembership}
refreshPendingMemberships={this.refreshPendingMemberships}
/>;
}) }
{ show_csv &&
<div className={"align-btn-right"}>
<CSVLink
data={this.generateCSVData(this.state.pendingMemberships)}
filename={"members_incoming_download.csv"}
>
<Button color={"primary"} outline className={"button-mt-20"}>Download as CSV</Button>
</CSVLink>
</div>
}
</Block>
</Container>
);
}
}
class IncomingRequest extends Component {
const IncomingRequest = ({ membership, postPatch }) => {
const API = useAPI();
const alerthandler = useAlertHandler();
updateStatus = (status) => {
let membership = this.props.pendingMembership;
return Helper.api_call(membership.url, "PATCH",
{"slug": membership.slug,"status": status},
"json",
()=>{this.props.refreshPendingMemberships();}
);
const updateStatus = (status) => {
API.callv4({
url: membership.url,
method: "PATCH",
object: {"slug": membership.slug, "status": status},
on_succes: () => {
alerthandler.handleAlertHandler("success", status+": "+membership.profile.given_name);
postPatch();
},
on_failure: () => {
alerthandler.handleAlertHandler("Action failed");
}
});
};
render() {
const {pendingMembership: {profile}} = this.props;
return (
<div className={"IncomingRequest"}>
<Row style={{width: "100%"}}>
<Col>
<ShortProfile
profile={profile}
/>
</Col>
<Col>
<div style={{float: "right"}}>
<Button className={"acceptbutton"} onClick={()=> this.updateStatus("Accepted")} color={"success"}><FontAwesomeIcon icon={"check"}/></Button>
<Button onClick= {()=> this.updateStatus("Rejected")} color={"danger"}><FontAwesomeIcon icon={"times"}/></Button>
</div>
</Col>
</Row>
</div>
);
}
}
const reject = () => updateStatus("Rejected");
const accept = () => updateStatus("Accepted");
export const MembersIncomingWithRouter = withRouter(MembersIncoming);
return (
<Grid container justify={"space-between"}>
<Grid item>
<ShortProfile
profile={membership.profile}
/>
</Grid>
<Grid item>
<Button onClick={accept} color={"success"}><FontAwesomeIcon icon={"check"}/></Button>
&nbsp;
<Button onClick= {reject} color={"danger"}><FontAwesomeIcon icon={"times"}/></Button>
</Grid>
</Grid>
);
};
IncomingRequest.propTypes = {
membership: PropTypes.object.isRequired,
postPatch: PropTypes.func.isRequired
};
......@@ -14,7 +14,7 @@ import { BoardsWithRouter } from "App/Pages/Groups/Board/Boards";
import { CommitteesWithRouter } from "App/Pages/Groups/Board/Committees";
import { MembersCurrentWithRouter } from "App/Pages/Members/MembersCurrent";
import { MembersDisputedWithRouter } from "App/Pages/Members/MembersDisputed";
import { MembersIncomingWithRouter } from "App/Pages/Members/MembersIncoming";
import MembersIncoming from "App/Pages/Members/MembersIncoming";
import { MembersLeavingWithRouter } from "App/Pages/Members/MembersLeaving";
import MembershipEnd from "App/Pages/Profile/MembershipEnd";
import PropTypes from "prop-types";
......@@ -178,10 +178,8 @@ const BoardMemberRoutes = (props) => {
<Route
path={path+"/members/incoming"}
render={() =>
<MembersIncomingWithRouter
<MembersIncoming
association={association}
show_csv={true}
/>
}
/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment