Commit 4014ead8 authored by TJHeeringa's avatar TJHeeringa

Various fixes

parent a937116f
......@@ -19,8 +19,7 @@ const useStyles = makeStyles(theme => ({
transition: "0.3s",
boxShadow: "0px 14px 80px rgba(34, 35, 58, 0.2)",
position: "relative",
minWidth: 304,
maxWidth: 600,
width: "100%",
marginLeft: "auto",
overflow: "initial",
background: theme.palette.background.paper,
......@@ -39,8 +38,7 @@ const useStyles = makeStyles(theme => ({
width: "88%",
marginLeft: 10,
marginRight: 10,
height: 0,
paddingBottom: "48%",
height: 200,
borderRadius: theme.spacing(2),
backgroundColor: theme.palette.background.paper,
position: "relative",
......
......@@ -254,13 +254,16 @@ const ProfileFormWithoutContainer = ({ update, profile, onSuccess, disabled, han
<Wrapper>
<SelectField
name={"Phase"}
value={profile.is_master}
onChange={(event) => handleProfileChange("is_master", event.target.value)}
value={profile.phase}
onChange={(event) => handleProfileChange("phase", event.target.value)}
disabled={disabled}
required
>
<MenuItem value={true}>Master</MenuItem>
<MenuItem value={false}>Bachelor</MenuItem>
<MenuItem value={"PhD"}>PhD</MenuItem>
<MenuItem value={"Master"}>Master</MenuItem>
<MenuItem value={"Premaster"}>Premaster</MenuItem>
<MenuItem value={"Bachelor"}>Bachelor</MenuItem>
<MenuItem value={"Other"}>Other</MenuItem>
</SelectField>
</Wrapper>
<Wrapper>
......
......@@ -25,7 +25,7 @@ const ProfileInfo = ({ profile }) => {
"IBAN:": profile.iban,
};
data["Education"] = {
"Phase:": profile.is_master ? "Master" : "Bachelor",
"Phase:": profile.phase,
"Study": profile.study ? profile.study.name_en : ""
};
return data;
......
......@@ -53,8 +53,8 @@ const ConfirmationModal = ({ onConfirm, onCancel, title, description, open }) =>
};
ConfirmationModal.propTypes = {
title: PropTypes.string,
description: PropTypes.string,
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
onConfirm: PropTypes.func,
onCancel: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
......@@ -62,7 +62,6 @@ ConfirmationModal.propTypes = {
ConfirmationModal.defaultProps = {
onConfirm: ()=>{},
description: "Are you sure?"
};
export default ConfirmationModal;
\ No newline at end of file
......@@ -111,37 +111,37 @@ const AssociationBoardDrawer = (props) => {
}
]
},
{
icon: <EmailIcon />,
primary: "Emails",
items: [
{
icon: <SettingsIcon />,
primary: "Settings",
to: url + "/emails/settings"
},
{
icon: <FeaturedVideoIcon />,
primary: "Templates",
to: url + "/emails/templates"
},
// {
// icon: <AlternateEmailIcon />,
// primary: "Send",
// to: url + "/emails/send"
// },
// {
// icon: <SubjectIcon />,
// primary: "Lists",
// to: url + "/emails/lists"
// },
// {
// icon: <PersonIcon />,
// primary: "Users",
// to: url + "/emails/users"
// },
]
},
// {
// icon: <EmailIcon />,
// primary: "Emails",
// items: [
// {
// icon: <SettingsIcon />,
// primary: "Settings",
// to: url + "/emails/settings"
// },
// // {
// // icon: <FeaturedVideoIcon />,
// // primary: "Templates",
// // to: url + "/emails/templates"
// // },
// // {
// // icon: <AlternateEmailIcon />,
// // primary: "Send",
// // to: url + "/emails/send"
// // },
// // {
// // icon: <SubjectIcon />,
// // primary: "Lists",
// // to: url + "/emails/lists"
// // },
// // {
// // icon: <PersonIcon />,
// // primary: "Users",
// // to: url + "/emails/users"
// // },
// ]
// },
{
icon: <EventIcon />,
primary: "Events",
......@@ -184,27 +184,27 @@ const AssociationBoardDrawer = (props) => {
}
]
},
{
icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "warehouse"]}/>,
primary: "Inventory",
items: [
{
icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "socks"]}/>,
primary: "Products",
to: url + "/inventory/products"
},
{
icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "shopping-cart"]}/>,
primary: "Purchases",
to: url + "/inventory/purchases"
},
// {
// icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "exchange-alt"]}/>,
// primary: "Rented",
// to: url + "/inventory/rented"
// }
]
},
// {
// icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "warehouse"]}/>,
// primary: "Inventory",
// items: [
// {
// icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "socks"]}/>,
// primary: "Products",
// to: url + "/inventory/products"
// },
// {
// icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "shopping-cart"]}/>,
// primary: "Purchases",
// to: url + "/inventory/purchases"
// },
// // {
// // icon: <FontAwesomeIcon className={"fa-lg"} icon={["fas", "exchange-alt"]}/>,
// // primary: "Rented",
// // to: url + "/inventory/rented"
// // }
// ]
// },
];
return (
<Drawer items={data}/>
......
......@@ -99,7 +99,7 @@ const API = ({ children }) => {
});
};
const api_call = (url, method, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, include = true) => {
const api_call = (url, method, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, include = true, headers= {}) => {
// console.log("API object:", object);
// make body
// -----------------
......@@ -119,7 +119,6 @@ const API = ({ children }) => {
// set headers
// -----------------
let headers = {};
if (json_or_form_data === "json") {
headers["Content-Type"] = "application/json";
}
......@@ -172,25 +171,25 @@ const API = ({ children }) => {
});
};
const api_callv2 = ({url, method, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false}={}) => {
return api_call(url, method, object, json_or_form_data, on_succes, on_failure, !external);
const api_callv2 = ({url, method, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false, headers = {}}={}) => {
return api_call(url, method, object, json_or_form_data, on_succes, on_failure, !external, headers);
};
const api_callv3 = ({url, method, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false}={}) => {
const api_callv3 = ({url, method, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false, headers = {}}={}) => {
// Every url starting with a '/' is a path, and the base url to the api should be prepended.
if (url[0] === "/") {
url = process.env.REACT_APP_API_URL + url;
}
return api_call(url, method, object, json_or_form_data, on_succes, on_failure, !external);
return api_call(url, method, object, json_or_form_data, on_succes, on_failure, !external, headers);
};
const api_callv4 = ({url, method, queryParams = {}, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false}={}) => {
const api_callv4 = ({url, method, queryParams = {}, object = undefined, json_or_form_data = "json", on_succes = undefined, on_failure = undefined, external = false, headers = {}}={}) => {
url += Object.entries(queryParams).reduce((queryParamString, queryParam)=>(
queryParamString
? queryParamString + "&" + queryParam.join("=")
: "?" + queryParam.join("=")),
"");
return api_callv3({url, method, object, json_or_form_data, on_succes, on_failure, external});
return api_callv3({url, method, object, json_or_form_data, on_succes, on_failure, external, headers});
};
const contextValue = {
......
......@@ -61,7 +61,7 @@ const BoardInfo = ({ association }) => {
<CardGrid
component={ContactCard}
card_grid={boardCards}
chunk_size={4}
chunk_size={1}
/>
</PageContent>
);
......
......@@ -19,6 +19,7 @@ import Block from "../../Components/PageLayout/Content/Block";
import {MemberTable2} from "../../Components/Tables/MemberTable";
import {useAPI} from "../../Contexts/API";
import {useDataFields} from "../../Contexts/Members";
import ConfirmationModal from "../../Components/Modals/ConfirmationModal";
const useStyles = makeStyles(theme => ({
......@@ -59,6 +60,7 @@ const Matchings = ({ association }) => {
const matches = MatchesAPI.list() || [];
const setMatches = MatchesAPI.set;
const [confirmationModal, setConfirmationModal] = useState(false);
const [show, setShowMatches] = useState(true);
const [selectedLeft, setLeft] = useState([]);
const [selectedRight, setRight] = useState([]);
......@@ -130,15 +132,16 @@ const Matchings = ({ association }) => {
singles = selectedRight;
to_be_matched_to_singles = selectedLeft;
}
// shuffle users to get rid of any accidental matching on name
singles = shuffle(singles);
to_be_matched_to_singles = shuffle(to_be_matched_to_singles);
console.log(singles);
console.log(to_be_matched_to_singles);
// create list of the to be made matches for everyone
let to_be_created_matches = [];
let index = 0;
const number_of_singles = singles.length;
// give every single a match, then every single a second match and so on
while (to_be_matched_to_singles.length > 0) {
let to_be_matched_to_single = to_be_matched_to_singles.pop();
......@@ -153,10 +156,24 @@ const Matchings = ({ association }) => {
index = 0;
}
}
// Do the API call
console.log(selectedRight, selectedLeft);
console.log(to_be_created_matches);
alertHandler.notImplemented();
API.callv4({
url: "/matchings",
method: "POST",
object: to_be_created_matches,
on_succes: (created_matches) => {
console.log(created_matches);
setMatches(created_matches);
setLeft([]);
setRight([]);
alertHandler.handleAlertHandler("green", "Successfully created " + created_matches.length + " matching(s).");
},
on_failure: () => {
alertHandler.handleAlertHandler("red", "Creation of matching failed.");
}}
);
};
const onDelete = (to_be_deleted_matches, remaining_matches) => {
......@@ -165,8 +182,9 @@ const Matchings = ({ association }) => {
url: "/matchings",
queryParams: {slug__in: to_be_deleted_matches_slugs, association__slug: association.slug},
method: "DELETE",
headers: {"X-BULK-OPERATION": true},
on_succes: ()=>{
alertHandler.handleAlertHandler("red", "Succesfully deleted " + to_be_deleted_matches.length + " matches.");
alertHandler.handleAlertHandler("green", "Succesfully deleted " + to_be_deleted_matches.length + " matches.");
setMatches(remaining_matches);
},
on_failure: ()=> {
......@@ -191,11 +209,40 @@ const Matchings = ({ association }) => {
}
const sentEmails = () => {
alertHandler.notImplemented();
API.callv4({
url: "/matchings/email",
method: "POST",
object: {sent_to_all: true, association: association.url},
on_succes: (response)=>{
alertHandler.handleAlertHandler("green", "Succesfully emailed " + response["emails send"] + " matches.");
setMatches(prevState => prevState.map(match=>({
...match,
email_send: true
})));
closeModal();
},
on_failure: ()=> {
alertHandler.handleAlertHandler("red", "Emailing of match(es) failed.");
closeModal();
}
});
};
const openModal = () => setConfirmationModal(true);
const closeModal = () => setConfirmationModal(false);
const numberOfMatchesStillNeededToBeEmailed = matches.filter(match=>!match.email_send).length;
const modalDescription = "Of the " + matches.length + " matches " + numberOfMatchesStillNeededToBeEmailed + " match(es) still need to " +
"have an email informing them. Do you want to sent them an email now?";
const allowEmailModal = numberOfMatchesStillNeededToBeEmailed > 0;
return (
<React.Fragment>
<ConfirmationModal
title={"Sent Emails"}
description={modalDescription}
onCancel={closeModal}
onConfirm={sentEmails}
open={confirmationModal}
/>
<Container>
<Block>
<Row>
......@@ -204,7 +251,7 @@ const Matchings = ({ association }) => {
</Col>
<Col>
<div className={"text-right"}>
<Button color={"secondary"} variant={"outlined"} onClick={sentEmails}>
<Button color={"secondary"} variant={"outlined"} onClick={openModal} disabled={!allowEmailModal}>
Email
</Button>
&nbsp;
......
......@@ -83,21 +83,21 @@ const Settings = ({ association: propAssociation }) => {
disabled
/>
</Wrapper>
<Wrapper>
<IconHolder Icon={ShareIcon}/>
<SelectField
name={"email_on_create_matching"}
value={emailSettings.email_on_create_matching}
onChange={(event) => handleChange("email_on_create_matching", event.target.value)}
helperText={
"When you set this to 'yes', then whenever you create a matching they will be informed directly. " +
"Otherwise you will have to email manually."
}
>
<MenuItem value={"True"}>Yes</MenuItem>
<MenuItem value={"False"}>No</MenuItem>
</SelectField>
</Wrapper>
{/*<Wrapper>*/}
{/* <IconHolder Icon={ShareIcon}/>*/}
{/* <SelectField*/}
{/* name={"email_on_create_matching"}*/}
{/* value={emailSettings.email_on_create_matching}*/}
{/* onChange={(event) => handleChange("email_on_create_matching", event.target.value)}*/}
{/* helperText={*/}
{/* "When you set this to 'yes', then whenever you create a matching they will be informed directly. " +*/}
{/* "Otherwise you will have to email manually."*/}
{/* }*/}
{/* >*/}
{/* <MenuItem value={"True"}>Yes</MenuItem>*/}
{/* <MenuItem value={"False"}>No</MenuItem>*/}
{/* </SelectField>*/}
{/*</Wrapper>*/}
<Wrapper>
<div/>
<Button variant={"contained"} color={"primary"} type={"submit"}>
......
......@@ -98,7 +98,7 @@ const GroupMemberManagement = ({ association }) => {
</Wrapper>
<hr className={"box-title-separator"}/>
<GroupMemberManagementGroupMemberList
current_board={group.board_group}
board_group={group.board_group}
association={association}
memberships={morphDataToGroupMemberList(memberships)}
updateRows={updateMembership}
......
......@@ -24,6 +24,7 @@ export const GroupMemberManagementGroupMemberList = ({ memberships: initRows, bo
if (board_group === true) {
columns.push({ name: "email", title: "Email"});
columns.push({ name: "order", title: "Order"});
columns.push({ name: "description", title: "Board text"});
}
const editingStateColumnExtensions = [
......@@ -51,6 +52,7 @@ export const GroupMemberManagementGroupMemberList = ({ memberships: initRows, bo
if (board_group === true) {
membership.email = edited_row.email;
membership.order = edited_row.order;
membership.description = edited_row.description;
}
API.callv4({
url: membership.url,
......
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