Add system editing
This commit is contained in:
@@ -6,7 +6,7 @@ import Memberlist from './Memberlist.js'
|
||||
export default function Dash(props) {
|
||||
|
||||
return (<>
|
||||
<System user submit={props.submit} setSubmit={props.setSubmit}/>
|
||||
<System />
|
||||
<Memberlist />
|
||||
</>
|
||||
);
|
||||
|
@@ -4,7 +4,6 @@ import { useForm, Controller } from "react-hook-form";
|
||||
import autosize from 'autosize';
|
||||
import moment from 'moment';
|
||||
|
||||
import Loading from "./Loading.js";
|
||||
import API_URL from "../Constants/constants.js";
|
||||
|
||||
import defaultAvatar from '../default_discord_avatar.png'
|
||||
@@ -12,7 +11,7 @@ import { FaUser } from "react-icons/fa";
|
||||
|
||||
export default function MemberCard(props) {
|
||||
|
||||
const { register, handleSubmit, errors, control } = useForm();
|
||||
const { register, handleSubmit, control } = useForm();
|
||||
|
||||
const [member, setMember] = useState(props.member);
|
||||
|
||||
@@ -28,6 +27,8 @@ export default function MemberCard(props) {
|
||||
const [ editMode, setEditMode ] = useState(false);
|
||||
const [ privacyMode, setPrivacyMode ] = useState(false);
|
||||
const [ privacyView, setPrivacyView ] = useState(false);
|
||||
|
||||
const [ errorAlert, setErrorAlert ] = useState(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
@@ -41,10 +42,10 @@ export default function MemberCard(props) {
|
||||
setBirthdate(member.birthday)
|
||||
if (member.birthday.startsWith('0004-')) {
|
||||
var bday = member.birthday.replace('0004-','');
|
||||
var bdaymoment = moment(bday, 'MM DD').format('MMM D');
|
||||
var bdaymoment = moment(bday, 'MM-DD').format('MMM D');
|
||||
setBirthday(bdaymoment);
|
||||
} else {
|
||||
var birthdaymoment = moment(bday, 'YYYY MM DD').format('MMM D, YYYY');
|
||||
var birthdaymoment = moment(member.birthday, 'YYYY-MM-DD').format('MMM D, YYYY');
|
||||
setBirthday(birthdaymoment);
|
||||
}
|
||||
} else { setBirthday('');
|
||||
@@ -61,8 +62,7 @@ export default function MemberCard(props) {
|
||||
|
||||
if (member.color) {
|
||||
setColor(member.color);
|
||||
} else { setColor('');
|
||||
}
|
||||
} else setColor('');
|
||||
|
||||
if (member.description) {
|
||||
setDesc(toHTML(member.description));
|
||||
@@ -78,7 +78,6 @@ export default function MemberCard(props) {
|
||||
})
|
||||
|
||||
const submitEdit = data => {
|
||||
|
||||
fetch(`${API_URL}m/${member.id}`,{
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data),
|
||||
@@ -86,14 +85,14 @@ export default function MemberCard(props) {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': JSON.stringify(localStorage.getItem("token")).slice(1, -1)
|
||||
}}).then (res => res.json()
|
||||
).then (data => setMember(data), setEditMode(false)
|
||||
).catch (error => {
|
||||
console.error(error);
|
||||
})
|
||||
).then (data => { setMember(prevState => {return {...prevState, ...data}}); setEditMode(false)}
|
||||
).catch (error => {
|
||||
console.error(error);
|
||||
setErrorAlert(true);
|
||||
});
|
||||
}
|
||||
|
||||
const submitPrivacy = data => {
|
||||
|
||||
fetch(`${API_URL}m/${member.id}`,{
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data),
|
||||
@@ -101,49 +100,50 @@ export default function MemberCard(props) {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': JSON.stringify(localStorage.getItem("token")).slice(1, -1)
|
||||
}}).then (res => res.json()
|
||||
).then (data => setMember(data),
|
||||
setPrivacyMode(false)
|
||||
).catch (error => {
|
||||
console.error(error);
|
||||
})
|
||||
).then (data => { setMember(prevState => {return {...prevState, ...data}}); setPrivacyMode(false)}
|
||||
).catch (error => {
|
||||
console.error(error);
|
||||
setErrorAlert(true);
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<BS.Accordion.Toggle className="d-flex align-items-center justify-content-between" as={BS.Card.Header} eventKey={member.id}>
|
||||
<BS.Card.Title className="float-left"><FaUser className="mr-4" /> <b>{member.name}</b> ({member.id})</BS.Card.Title>
|
||||
<>
|
||||
<BS.Card.Header className="d-flex align-items-center justify-content-between">
|
||||
<BS.Accordion.Toggle as={BS.Button} variant="link" eventKey={member.id} className="float-left"><FaUser className="mr-4" /> <b>{member.name}</b> ({member.id})</BS.Accordion.Toggle>
|
||||
{ member.avatar_url ? <BS.Image src={`${member.avatar_url}`} style={{width: 50, height: 50}} className="float-right" roundedCircle /> :
|
||||
<BS.Image src={defaultAvatar} style={{width: 50, height: 50}} className="float-right" roundedCircle />}
|
||||
</BS.Accordion.Toggle>
|
||||
<BS.Image src={defaultAvatar} style={{width: 50, height: 50}} className="float-right" roundedCircle />}
|
||||
</BS.Card.Header>
|
||||
<BS.Accordion.Collapse eventKey={member.id}>
|
||||
<BS.Card.Body style={{borderLeft: `5px solid #${color}` }}>
|
||||
{ errorAlert ? <BS.Alert variant="danger">Something went wrong, please try logging in and out again.</BS.Alert> : "" }
|
||||
{ editMode ?
|
||||
<BS.Form onSubmit={handleSubmit(submitEdit)}>
|
||||
<BS.Form.Row>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Name:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control placeholder={member.name}/>} name="name" control={control}/>
|
||||
<Controller as={<BS.Form.Control />} name="name" control={control} defaultValue={member.name} />
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>AKA: </BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control placeholder={displayName}/>} name="display_name" control={control}/>
|
||||
<Controller as={<BS.Form.Control />} name="display_name" control={control} defaultValue={displayName} />
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Birthday:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control placeholder={birthdate} pattern="/^\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/g"/>} name="birthday" control={control}/>
|
||||
<Controller as={<BS.Form.Control pattern="^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$"/>} name="birthday" control={control} defaultValue={birthdate}/>
|
||||
<BS.Form.Text>(YYYY-MM-DD)</BS.Form.Text>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Pronouns:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control placeholder={pronouns}/>} name="pronouns" control={control}/>
|
||||
<Controller as={<BS.Form.Control/>} name="pronouns" control={control} defaultValue={pronouns} />
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Avatar url:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control type="url" placeholder={avatar}/>} name="avatar_url" control={control} />
|
||||
<Controller as={<BS.Form.Control type="url"/>} name="avatar_url" control={control} defaultValue={avatar} />
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Color:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control placeholder={color} pattern="/[A-Fa-f0-9]{6}$/g"/>} name="color" control={control}/>
|
||||
<Controller as={<BS.Form.Control pattern="[A-Fa-f0-9]{6}"/>} name="color" control={control} defaultValue={color} />
|
||||
<BS.Form.Text>(hexcode)</BS.Form.Text>
|
||||
</BS.Col>
|
||||
</BS.Form.Row>
|
||||
@@ -203,7 +203,7 @@ export default function MemberCard(props) {
|
||||
<option>private</option>
|
||||
</BS.Form.Control>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Col className="mb-3" xs={12} lg={3}>
|
||||
<BS.Form.Label>Meta:</BS.Form.Label>
|
||||
<BS.Form.Control name="metadata_privacy" as="select" ref={register}>
|
||||
<option>public</option>
|
||||
@@ -221,9 +221,9 @@ export default function MemberCard(props) {
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Description:</b> {member.description_privacy}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Birthday:</b> {member.birthday_privacy}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Pronouns:</b> {member.pronoun_privacy}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Meta:</b> {member.metadata_privacy}</BS.Col>
|
||||
<BS.Col className="mb-3" xs={12} lg={3}><b>Meta:</b> {member.metadata_privacy}</BS.Col>
|
||||
</BS.Row>
|
||||
<BS.Button variant="light" onClick={() => setPrivacyView(false)}>Cancel</BS.Button> <BS.Button variant="primary" onClick={() => setPrivacyMode(true)}>Edit</BS.Button>
|
||||
<BS.Button variant="light" onClick={() => setPrivacyView(false)}>Exit</BS.Button> <BS.Button variant="primary" onClick={() => setPrivacyMode(true)}>Edit</BS.Button>
|
||||
<hr/></> : "" }
|
||||
<p><b>Description:</b></p>
|
||||
<p dangerouslySetInnerHTML={{__html: desc}}></p>
|
||||
|
@@ -5,7 +5,7 @@ import MemberCard from './MemberCard.js'
|
||||
import Loading from "./Loading.js";
|
||||
import API_URL from "../Constants/constants.js";
|
||||
|
||||
export default function Memberlist() {
|
||||
export default function Memberlist(props) {
|
||||
|
||||
const user = JSON.parse(localStorage.getItem('user'));
|
||||
const userId = user.id;
|
||||
@@ -44,8 +44,8 @@ export default function Memberlist() {
|
||||
}
|
||||
return false;
|
||||
}).sort((a, b) => a.name.localeCompare(b.name)).map((member) => <BS.Card key={member.id}>
|
||||
<MemberCard
|
||||
member={member}
|
||||
<MemberCard
|
||||
member={member}
|
||||
/>
|
||||
</BS.Card>
|
||||
);
|
||||
|
@@ -4,15 +4,16 @@ import Toggle from 'react-toggle'
|
||||
import { FaSun, FaMoon } from "react-icons/fa";
|
||||
|
||||
import "react-toggle/style.css"
|
||||
import history from "../History.js";
|
||||
|
||||
export default function Navigation(props) {
|
||||
export default function Navigation() {
|
||||
|
||||
const darkMode = useDarkMode(false);
|
||||
|
||||
function logOut() {
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("user");
|
||||
props.setIsSubmit(false);
|
||||
history.push('/pk-webs');
|
||||
}
|
||||
|
||||
return (
|
||||
|
@@ -1,21 +1,98 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import * as BS from 'react-bootstrap'
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import autosize from 'autosize';
|
||||
import moment from 'moment';
|
||||
import 'moment-timezone';
|
||||
|
||||
import API_URL from "../Constants/constants.js";
|
||||
|
||||
import { FaAddressCard } from "react-icons/fa";
|
||||
import defaultAvatar from '../default_discord_avatar.png'
|
||||
import { FaAddressCard } from "react-icons/fa";
|
||||
|
||||
export default function System(props) {
|
||||
|
||||
const { register, handleSubmit,control } = useForm();
|
||||
|
||||
const [ user, setUser ] = useState(JSON.parse(localStorage.getItem('user')));
|
||||
|
||||
const [ tag, setTag ] = useState("");
|
||||
const [ timezone, setTimezone ] = useState("");
|
||||
const [ avatar, setAvatar ] = useState("");
|
||||
const [ desc, setDesc ] = useState("");
|
||||
const user = JSON.parse(localStorage.getItem("user"));
|
||||
const [ editDesc, setEditDesc ] = useState("");
|
||||
|
||||
const [ editMode, setEditMode ] = useState(false);
|
||||
const [ privacyMode, setPrivacyMode ] = useState(false);
|
||||
const [ privacyView, setPrivacyView ] = useState(false);
|
||||
|
||||
const [ invalidTimezone, setInvalidTimezone ] = useState(false);
|
||||
const [ errorAlert, setErrorAlert ] = useState(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const { toHTML } = require('../Functions/discord-parser.js');
|
||||
|
||||
if (user.tag) {
|
||||
setTag(user.tag);
|
||||
} else setTag('');
|
||||
|
||||
if (user.tz) {
|
||||
setTimezone(user.tz);
|
||||
} else setTimezone('');
|
||||
|
||||
if (user.avatar_url) {
|
||||
setAvatar(user.avatar_url)
|
||||
} else setAvatar('')
|
||||
|
||||
if (user.description) {
|
||||
setDesc(toHTML(user.description));
|
||||
} else setDesc("(no description)");
|
||||
}, [user.description]);
|
||||
setEditDesc(user.description);
|
||||
} else { setDesc("(no description)");
|
||||
setEditDesc("");
|
||||
}}, [user.description, user.tag, user.avatar_url, user.tz]);
|
||||
|
||||
useEffect(() => {
|
||||
autosize(document.querySelector('textarea'));
|
||||
})
|
||||
|
||||
const submitEdit = data => {
|
||||
if (data.tz) {
|
||||
if (!moment.tz.zone(data.tz)) {
|
||||
setInvalidTimezone(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fetch(`${API_URL}s`,{
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': JSON.stringify(localStorage.getItem("token")).slice(1, -1)
|
||||
}}).then (res => res.json()
|
||||
).then ( data => { setUser(prevState => {return {...prevState, ...data}}); localStorage.setItem('user', JSON.stringify(user)); setEditMode(false)}
|
||||
).catch (error => {
|
||||
console.error(error);
|
||||
setErrorAlert(true);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const submitPrivacy = data => {
|
||||
fetch(`${API_URL}s`,{
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': JSON.stringify(localStorage.getItem("token")).slice(1, -1)
|
||||
}}).then (res => res.json()
|
||||
).then (data => { setUser(prevState => {return {...prevState, ...data}}); localStorage.setItem('user', JSON.stringify(user)); setPrivacyMode(false)}
|
||||
).catch (error => {
|
||||
console.error(error);
|
||||
setErrorAlert(true);
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<BS.Card className="mb-3 mt-3 w-100" >
|
||||
@@ -25,13 +102,89 @@ export default function System(props) {
|
||||
<BS.Image src={defaultAvatar} style={{width: 50, height: 50}} className="float-right" roundedCircle />}
|
||||
</BS.Card.Header>
|
||||
<BS.Card.Body>
|
||||
<BS.Row>
|
||||
{ errorAlert ? <BS.Alert variant="danger">Something went wrong, please try logging in and out again.</BS.Alert> : "" }
|
||||
{ editMode ?
|
||||
<BS.Form onSubmit={handleSubmit(submitEdit)}>
|
||||
{/* <BS.Form.Text className='mb-4'>Note: changes here may take a while to be reflected on the bot. This is due to the bot caching data.<br/> Try editing a member after to make the changes show up.</BS.Form.Text> */}
|
||||
<BS.Form.Row>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Name:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control/>} name="name" control={control} defaultValue={user.name}/>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Tag:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control/>} name="y" control={control} defaultValue={tag}/>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Timezone:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control/>} name="tz" control={control} defaultValue={timezone}/>
|
||||
{ invalidTimezone ? <BS.Form.Text>Please enter a valid <a href='https://xske.github.io/tz/' rel="noreferrer" target="_blank">timezone</a></BS.Form.Text> : "" }
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Avatar url:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control/>} name="avatar_url" control={control} defaultValue={avatar}/>
|
||||
</BS.Col>
|
||||
</BS.Form.Row>
|
||||
<BS.Form.Group className="mt-3">
|
||||
<BS.Form.Label>Description:</BS.Form.Label>
|
||||
<Controller as={<BS.Form.Control maxLength="1000" as="textarea" />} name="description" control={control} defaultValue={editDesc}/>
|
||||
</BS.Form.Group>
|
||||
<BS.Button variant="light" onClick={() => setEditMode(false)}>Cancel</BS.Button> <BS.Button variant="primary" type="submit">Submit</BS.Button>
|
||||
</BS.Form> :
|
||||
<><BS.Row>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>ID:</b> {user.id}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Tag:</b> {user.tag}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Timezone:</b> {user.tz}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Tag:</b> {tag}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Timezone:</b> {timezone}</BS.Col>
|
||||
{ privacyView ? "" : <BS.Col className="mb-lg-3" xs={12} lg={3}><b>Privacy:</b> <BS.Button variant="light" size="sm" onClick={() => setPrivacyView(true)}>View</BS.Button></BS.Col> }
|
||||
</BS.Row>
|
||||
{ privacyMode ? <BS.Form onSubmit={handleSubmit(submitPrivacy)}>
|
||||
<hr/>
|
||||
<h5>Editing privacy settings</h5>
|
||||
<BS.Form.Row>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Description:</BS.Form.Label>
|
||||
<BS.Form.Control name="description_privacy" as="select" ref={register}>
|
||||
<option>public</option>
|
||||
<option>private</option>
|
||||
</BS.Form.Control>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Member list:</BS.Form.Label>
|
||||
<BS.Form.Control name="member_list_privacy" as="select" ref={register}>
|
||||
<option>public</option>
|
||||
<option>private</option>
|
||||
</BS.Form.Control>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Front:</BS.Form.Label>
|
||||
<BS.Form.Control name="front_privacy" as="select" ref={register}>
|
||||
<option>public</option>
|
||||
<option>private</option>
|
||||
</BS.Form.Control>
|
||||
</BS.Col>
|
||||
<BS.Col className="mb-lg-2" xs={12} lg={3}>
|
||||
<BS.Form.Label>Front history:</BS.Form.Label>
|
||||
<BS.Form.Control name="front_history_privacy" as="select" ref={register}>
|
||||
<option>public</option>
|
||||
<option>private</option>
|
||||
</BS.Form.Control>
|
||||
</BS.Col>
|
||||
</BS.Form.Row>
|
||||
<BS.Button variant="light" onClick={() => setPrivacyMode(false)}>Cancel</BS.Button> <BS.Button variant="primary" type="submit">Submit</BS.Button>
|
||||
<hr/>
|
||||
</BS.Form> : privacyView ? <><hr/>
|
||||
<h5>Viewing privacy settings</h5>
|
||||
<BS.Row>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Description:</b> {user.description_privacy}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Member list: </b>{user.member_list_privacy}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Front:</b> {user.front_privacy}</BS.Col>
|
||||
<BS.Col className="mb-lg-3" xs={12} lg={3}><b>Front history:</b> {user.front_history_privacy}</BS.Col>
|
||||
</BS.Row>
|
||||
<BS.Button variant="light" onClick={() => setPrivacyView(false)}>Exit</BS.Button> <BS.Button variant="primary" onClick={() => setPrivacyMode(true)}>Edit</BS.Button>
|
||||
<hr/></> : "" }
|
||||
<p><b>Description:</b></p>
|
||||
<p dangerouslySetInnerHTML={{__html: desc}}></p>
|
||||
{ privacyMode ? "" : privacyView ? "" : <BS.Button variant="light" onClick={() => setEditMode(true)}>Edit</BS.Button>}</> }
|
||||
</BS.Card.Body>
|
||||
</BS.Card>
|
||||
)
|
||||
|
Reference in New Issue
Block a user