Add system editing

This commit is contained in:
Spectralitree 2020-12-11 16:35:25 +01:00
parent d30136fba2
commit e421222002
11 changed files with 251 additions and 49 deletions

View File

@ -1 +1 @@
[{"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js":"1","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js":"2","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js":"3","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js":"4","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js":"5","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js":"6","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Navigation.js":"7","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js":"8","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js":"9","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js":"10","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js":"11"},{"size":329,"mtime":1607554515255,"results":"12","hashOfConfig":"13"},{"size":87,"mtime":1607504507181,"results":"14","hashOfConfig":"13"},{"size":3584,"mtime":1607633174709,"results":"15","hashOfConfig":"13"},{"size":297,"mtime":1607504507172,"results":"16","hashOfConfig":"13"},{"size":73,"mtime":1607504507180,"results":"17","hashOfConfig":"13"},{"size":231,"mtime":1607504507174,"results":"18","hashOfConfig":"13"},{"size":1184,"mtime":1607611170429,"results":"19","hashOfConfig":"13"},{"size":1745,"mtime":1607611132497,"results":"20","hashOfConfig":"13"},{"size":2160,"mtime":1607534877891,"results":"21","hashOfConfig":"13"},{"size":11973,"mtime":1607644188505,"results":"22","hashOfConfig":"13"},{"size":10382,"mtime":1607549930730,"results":"23","hashOfConfig":"13"},{"filePath":"24","messages":"25","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},"1uc84gl",{"filePath":"27","messages":"28","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"29","messages":"30","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"31","messages":"32","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"33","messages":"34","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"35","messages":"36","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"37","messages":"38","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"39","messages":"40","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"41","messages":"42","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},{"filePath":"43","messages":"44","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"45","messages":"46","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"26"},"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js",[],["47","48"],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Navigation.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js",["49","50"],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js",[],{"ruleId":"51","replacedBy":"52"},{"ruleId":"53","replacedBy":"54"},{"ruleId":"55","severity":1,"message":"56","line":7,"column":8,"nodeType":"57","messageId":"58","endLine":7,"endColumn":15},{"ruleId":"55","severity":1,"message":"59","line":15,"column":37,"nodeType":"57","messageId":"58","endLine":15,"endColumn":43},"no-native-reassign",["60"],"no-negated-in-lhs",["61"],"no-unused-vars","'Loading' is defined but never used.","Identifier","unusedVar","'errors' is assigned a value but never used.","no-global-assign","no-unsafe-negation"]
[{"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js":"1","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js":"2","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js":"3","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js":"4","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js":"5","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js":"6","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Navigation.js":"7","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js":"8","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js":"9","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js":"10","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js":"11"},{"size":329,"mtime":1607554515255,"results":"12","hashOfConfig":"13"},{"size":87,"mtime":1607504507181,"results":"14","hashOfConfig":"13"},{"size":3538,"mtime":1607700904518,"results":"15","hashOfConfig":"13"},{"size":243,"mtime":1607696817140,"results":"16","hashOfConfig":"13"},{"size":73,"mtime":1607504507180,"results":"17","hashOfConfig":"13"},{"size":231,"mtime":1607504507174,"results":"18","hashOfConfig":"13"},{"size":1217,"mtime":1607697726792,"results":"19","hashOfConfig":"13"},{"size":9718,"mtime":1607700749075,"results":"20","hashOfConfig":"13"},{"size":2165,"mtime":1607696817853,"results":"21","hashOfConfig":"13"},{"size":12296,"mtime":1607700619400,"results":"22","hashOfConfig":"13"},{"size":10382,"mtime":1607549930730,"results":"23","hashOfConfig":"13"},{"filePath":"24","messages":"25","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1uc84gl",{"filePath":"26","messages":"27","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"28","messages":"29","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"30","messages":"31","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"32","messages":"33","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"34","messages":"35","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"38","messages":"39","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"40","messages":"41","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"45","messages":"46","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Navigation.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js",[],["47","48"],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js",[],{"ruleId":"49","replacedBy":"50"},{"ruleId":"51","replacedBy":"52"},"no-native-reassign",["53"],"no-negated-in-lhs",["54"],"no-global-assign","no-unsafe-negation"]

8
package-lock.json generated
View File

@ -9719,6 +9719,14 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"moment-timezone": {
"version": "0.5.32",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.32.tgz",
"integrity": "sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA==",
"requires": {
"moment": ">= 2.9.0"
}
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",

View File

@ -12,6 +12,7 @@
"bootstrap": "^4.5.3",
"discord-markdown": "^2.4.1",
"moment": "^2.29.1",
"moment-timezone": "^0.5.32",
"node-fetch": "^2.6.1",
"node-sass": "^4.14.1",
"react": "^17.0.1",

View File

@ -6,9 +6,14 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="A web interface for pluralkit."
content="(This is still a work in progress)"
name="application-name"
content="pk-webs"
/>
<meta
name="description"
content="A web interface for pluralkit. (This is still a work in progress)"
/>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/

View File

@ -61,11 +61,11 @@ export default function App() {
return (
<Router history={history} basename="/pk-webs">
<Navigation isSubmit={isSubmit} setIsSubmit={setIsSubmit} />
<Navigation/>
<BS.Container>
<Switch>
<Route path="/pk-webs/dash" >
{ !localStorage.getItem('token') || isInvalid ? <Redirect to="/pk-webs"/> : <Dash/>
{ !localStorage.getItem('token') || isInvalid ? <Redirect to="/pk-webs"/> : <Dash />
}
</Route>
<Route exact path="/pk-webs">

View File

@ -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 />
</>
);

View File

@ -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>

View File

@ -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>
);

View File

@ -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 (

View File

@ -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>
)

View File

@ -69,6 +69,40 @@
color: $gray-100;
}
.card-header .btn-link {
color: $gray-900;
}
.card-header .btn-link:focus {
color: $gray-900;
text-decoration: none;
}
.card-header .btn-link:hover {
color: $gray-900;
text-decoration: none;
}
.card-header .btn-link {
font-size: 1.25rem !important;
font-weight: 500;
}
.dark-mode .btn-link {
color: $white;
}
.dark-mode .btn-link:focus {
color: $white;
text-decoration: none;
}
.dark-mode .btn-link:hover {
color: $white;
text-decoration: none;
}
.dark-mode .alert-danger {
color: $white;
background-color: $danger;