Skip to content

Commit

Permalink
WIP for #967
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Oct 20, 2023
1 parent a33a259 commit f0963f5
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 12 deletions.
1 change: 1 addition & 0 deletions client/src/components/EmailField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default function EmailField({
if (isEmpty(e.key) && isEmpty(e.target.value)) {
return;
}
debugger; // eslint-disable-line no-debugger
const email = e.target.value;
const invalidEmails = [];
const delimiters = [",", " ", ";", "\n", "\t"];
Expand Down
136 changes: 136 additions & 0 deletions client/src/components/OrganisationUnits.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React, {useEffect, useRef, useState} from "react";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {Tooltip} from "@surfnet/sds";
import "./OrganisationUnits.scss";
import {isEmpty, stopEvent} from "../utils/Utils";
import I18n from "../locale/I18n";
import {validEmailRegExp} from "../validations/regExps";

export const OrganisationUnits = ({units, setUnits, readOnly}) => {

const [duplicate, setDuplicate] = useState(false);
const [value, setValue] = useState("");

const inputRef = useRef(null);

useEffect(() => {
inputRef.current && inputRef.current.focus();
});

const internalOnChange = e => {
const name = e.target.value;
if (e.key === "Enter" || e.key === "Tab") {
if (units.some(unit => unit.name.toLowerCase() === name.toLowerCase())) {
setDuplicate(true);
return stopEvent(e);
} else {

}
} else {
setValue(name);
}

}

const displayEmail = email => {
const indexOf = email.indexOf("<");
if (indexOf > -1) {
return <Tooltip tip={email.substring(indexOf + 1, email.length - 1)}
standalone={true}
children={<span>{email.substring(0, indexOf).trim()}</span>}/>;
}
return <span>{email}</span>;
}

const validateEmail = (part, invalidEmails) => {
const hasLength = part.trim().length > 0;
const valid = hasLength && validEmailRegExp.test(part);
if (!valid && hasLength) {
invalidEmails.push(part.trim());
}
return valid;
}

const internalAddEmail = e => {
if (isEmpty(e.key) && isEmpty(e.target.value)) {
return;
}
const email = e.target.value;
const invalidEmails = [];
const delimiters = [",", " ", ";", "\n", "\t"];
let emails;
if (!isEmpty(email) && email.indexOf("<") > -1) {
emails = email.split(/[,\n\t;]/)
.map(e => e.trim())
.filter(part => {
const indexOf = part.indexOf("<");
part = indexOf > -1 ? part.substring(indexOf + 1, part.length - 1) : part;
return validateEmail(part, invalidEmails);
});
} else if (!isEmpty(email) && delimiters.some(delimiter => email.indexOf(delimiter) > -1)) {
const replacedEmails = email.replace(/[;\s]/g, ",");
const splitEmails = replacedEmails.split(",");
emails = splitEmails
.filter(part => validateEmail(part, invalidEmails));
} else if (!isEmpty(email)) {
const valid = validEmailRegExp.test(email.trim());
if (valid) {
emails = [email];
} else {
invalidEmails.push(email.trim());
}
}
setEmailErrors((!isEmpty(e.target.value) && !isEmpty(invalidEmails)) ? invalidEmails : []);
const uniqueEmails = [...new Set(emails)];
if (!isEmpty(uniqueEmails)) {
addEmails(uniqueEmails);
}
setValue("");
};

const internalRemoveMail = mail => e => {
setEmailErrors([]);
removeMail(mail)(e);
}

return (
<div className={`email-field ${error ? "error" : ""}`}>
<label htmlFor={name}>{name}
<Tooltip
tip={`${I18n.t("invitation.inviteesMessagesTooltip")}${isAdmin ? I18n.t("invitation.appendAdminNote") : ""}`}/>
</label>
<div className={`inner-email-field ${error ? "error" : ""}`}>
{emails.map((mail, index) =>
<div key={index} className="email-tag">
{displayEmail(mail)}
{pinnedEmails.includes(mail) ?
<span className="disabled icon"><FontAwesomeIcon icon="envelope"/></span> :
<span className="icon" onClick={internalRemoveMail(mail)}>
<FontAwesomeIcon icon="times"/>
</span>}

</div>)}
<textarea id="email-field"
value={value}
onChange={internalOnChange}
onBlur={internalAddEmail}
onKeyDown={e => {
if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
internalAddEmail(e);
setTimeout(() => document.getElementById("email-field").focus(), 50);
return stopEvent(e);
} else if (e.key === "Backspace" && isEmpty(value) && emails.length > 0) {
const mail = emails[emails.length - 1];
if (!pinnedEmails.includes(mail)) {
internalRemoveMail(mail)();
}
}
}}
placeholder={emails.length === 0 ? I18n.t("invitation.inviteesPlaceholder") : ""} cols={3}/>
</div>
{(!isEmpty(emailErrors) && value === "") && <p className="error">
{I18n.t("invitation.invalidEmails", {emails: Array.from(new Set(emailErrors)).join(", ")})}
</p>}
</div>
);
}
9 changes: 9 additions & 0 deletions client/src/components/OrganisationUnits.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import "../stylesheets/vars.scss";

div.organisation-units {
display: flex;
position: relative;
flex-direction: column;


}
Loading

0 comments on commit f0963f5

Please sign in to comment.