Cleaner code with prettier.

This commit is contained in:
Daniel
2022-06-16 13:43:44 +04:30
parent e2db7e71ac
commit 10d3a05c1d
32 changed files with 1021 additions and 754 deletions
+40 -22
View File
@@ -1,15 +1,15 @@
import { useState } from 'react';
import '../styles/SendItem.css';
import TagSelection from './TagSelection';
import addItem from '../modules/send';
import { useState } from "react";
import "../styles/SendItem.css";
import TagSelection from "./TagSelection";
import addItem from "../modules/send";
const AddItem = ({onExit, reFetch, tags, SetLoader, lightMode}) => {
const [name, setName] = useState('');
const [link, setLink] = useState('');
const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
const [name, setName] = useState("");
const [link, setLink] = useState("");
const [tag, setTag] = useState([]);
function newItem() {
SetLoader(true)
SetLoader(true);
addItem(name, link, tag, reFetch, onExit, SetLoader, "POST");
}
@@ -23,7 +23,7 @@ const AddItem = ({onExit, reFetch, tags, SetLoader, lightMode}) => {
function SetTags(value) {
setTag(value);
setTag(value.map(e => e.value.toLowerCase()));
setTag(value.map((e) => e.value.toLowerCase()));
}
function abort(e) {
@@ -34,23 +34,41 @@ const AddItem = ({onExit, reFetch, tags, SetLoader, lightMode}) => {
return (
<>
<div className='add-overlay' onClick={abort}></div>
<div className='send-box'>
<fieldset className='box'>
<div className="add-overlay" onClick={abort}></div>
<div className="send-box">
<fieldset className="box">
<legend>New bookmark</legend>
<div className='AddItem-content'>
<h3><span style={{color:"red"}}>* </span>Link:</h3>
<input onChange={SetLink} className="AddItem-input" type="search" placeholder="e.g. https://example.com/"/>
<h3>Name: <span className='optional'>(Optional)</span></h3>
<input onChange={SetName} className="AddItem-input" type="search" placeholder="e.g. Example Tutorial"/>
<h3>Tags: <span className='optional'>(Optional)</span></h3>
<div className="AddItem-content">
<h3>
<span style={{ color: "red" }}>* </span>Link:
</h3>
<input
onChange={SetLink}
className="AddItem-input"
type="search"
placeholder="e.g. https://example.com/"
/>
<h3>
Name: <span className="optional">(Optional)</span>
</h3>
<input
onChange={SetName}
className="AddItem-input"
type="search"
placeholder="e.g. Example Tutorial"
/>
<h3>
Tags: <span className="optional">(Optional)</span>
</h3>
<TagSelection setTags={SetTags} tags={tags} lightMode={lightMode} />
<button onClick={newItem} className="send-btn">Add &#xf067;</button>
<button onClick={newItem} className="send-btn">
Add &#xf067;
</button>
</div>
</fieldset>
</div>
</>
)
}
);
};
export default AddItem;
+66 -25
View File
@@ -1,16 +1,26 @@
import { useState } from 'react';
import deleteEntity from '../modules/deleteEntity';
import '../styles/SendItem.css';
import TagSelection from './TagSelection';
import editItem from '../modules/send';
import { useState } from "react";
import deleteEntity from "../modules/deleteEntity";
import "../styles/SendItem.css";
import TagSelection from "./TagSelection";
import editItem from "../modules/send";
const EditItem = ({tags, item, onExit, SetLoader, reFetch, lightMode }) => {
const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
const [name, setName] = useState(item.name);
const [tag, setTag] = useState(item.tag);
function EditItem() {
SetLoader(true);
editItem(name, item.link, tag, reFetch, onExit, SetLoader, "PUT", item._id, item.title);
editItem(
name,
item.link,
tag,
reFetch,
onExit,
SetLoader,
"PUT",
item._id,
item.title
);
}
function deleteItem() {
@@ -24,7 +34,7 @@ const EditItem = ({tags, item, onExit, SetLoader, reFetch, lightMode }) => {
function SetTags(value) {
setTag(value);
setTag(value.map(e => e.value.toLowerCase()));
setTag(value.map((e) => e.value.toLowerCase()));
}
function abort(e) {
@@ -37,25 +47,56 @@ const EditItem = ({tags, item, onExit, SetLoader, reFetch, lightMode }) => {
return (
<>
<div className='add-overlay' onClick={abort}></div>
<div className='send-box'>
<fieldset className='box'>
<legend >Edit bookmark</legend>
<button className="delete" onClick={deleteItem}>&#xf2ed;</button>
<div className='AddItem-content'>
<h3>Link: <a className='link' target="_blank" rel="noreferrer" href={item.link}>{url.hostname}</a></h3>
<h3 className='title'><b>{item.title}</b></h3>
<h3>Name: <span className='optional'>(Optional)</span></h3>
<input onChange={SetName} className="AddItem-input" type="search" value={name} placeholder={"e.g. Example Tutorial"} />
<h3>Tags: <span className='optional'>(Optional)</span></h3>
<TagSelection setTags={SetTags} tags={tags} tag={tag} lightMode={lightMode} />
<button onClick={EditItem} className="send-btn">Update &#xf303;</button>
<div className="add-overlay" onClick={abort}></div>
<div className="send-box">
<fieldset className="box">
<legend>Edit bookmark</legend>
<button className="delete" onClick={deleteItem}>
&#xf2ed;
</button>
<div className="AddItem-content">
<h3>
Link:{" "}
<a
className="link"
target="_blank"
rel="noreferrer"
href={item.link}
>
{url.hostname}
</a>
</h3>
<h3 className="title">
<b>{item.title}</b>
</h3>
<h3>
Name: <span className="optional">(Optional)</span>
</h3>
<input
onChange={SetName}
className="AddItem-input"
type="search"
value={name}
placeholder={"e.g. Example Tutorial"}
/>
<h3>
Tags: <span className="optional">(Optional)</span>
</h3>
<TagSelection
setTags={SetTags}
tags={tags}
tag={tag}
lightMode={lightMode}
/>
<button onClick={EditItem} className="send-btn">
Update &#xf303;
</button>
</div>
</fieldset>
</div>
</>
)
}
);
};
export default EditItem
export default EditItem;
+48 -19
View File
@@ -1,25 +1,54 @@
import '../styles/Filters.css'
import "../styles/Filters.css";
const Filters = ({nameChecked, handleNameCheckbox, descriptionChecked, handleDescriptionCheckbox, tagsChecked, handleTagsCheckbox, onExit}) => {
function abort(e) {
if (e.target.className === "filter-overlay") {
onExit();
}
const Filters = ({
nameChecked,
handleNameCheckbox,
descriptionChecked,
handleDescriptionCheckbox,
tagsChecked,
handleTagsCheckbox,
onExit,
}) => {
function abort(e) {
if (e.target.className === "filter-overlay") {
onExit();
}
}
return (
<>
<div className='filter-overlay' onClick={abort}></div>
<div className='filter-box'>
<fieldset className='filter'>
<legend >Filter by</legend>
<label><input type="checkbox" checked={nameChecked} onChange={handleNameCheckbox} />Name</label>
<label><input type="checkbox" checked={descriptionChecked} onChange={handleDescriptionCheckbox} />Website title</label>
<label><input type="checkbox" checked={tagsChecked} onChange={handleTagsCheckbox} />Tags</label>
</fieldset>
</div>
<>
<div className="filter-overlay" onClick={abort}></div>
<div className="filter-box">
<fieldset className="filter">
<legend>Filter by</legend>
<label>
<input
type="checkbox"
checked={nameChecked}
onChange={handleNameCheckbox}
/>
Name
</label>
<label>
<input
type="checkbox"
checked={descriptionChecked}
onChange={handleDescriptionCheckbox}
/>
Website title
</label>
<label>
<input
type="checkbox"
checked={tagsChecked}
onChange={handleTagsCheckbox}
/>
Tags
</label>
</fieldset>
</div>
</>
)
}
);
};
export default Filters
export default Filters;
+84 -71
View File
@@ -1,77 +1,90 @@
import '../styles/List.css';
import LazyLoad from 'react-lazyload';
import ViewArchived from './ViewArchived';
import EditItem from './EditItem';
import { useState } from 'react'
import "../styles/List.css";
import LazyLoad from "react-lazyload";
import ViewArchived from "./ViewArchived";
import EditItem from "./EditItem";
import { useState } from "react";
import { Link } from "react-router-dom";
const List = ({data, tags, reFetch, SetLoader, lightMode}) => {
const [editBox, setEditBox] = useState(false)
const [editIndex, setEditIndex] = useState(0)
const List = ({ data, tags, reFetch, SetLoader, lightMode }) => {
const [editBox, setEditBox] = useState(false);
const [editIndex, setEditIndex] = useState(0);
function edit(index) {
setEditBox(true);
setEditIndex(index);
}
function edit(index) {
setEditBox(true);
setEditIndex(index);
}
function exitEditing() {
setEditBox(false);
}
function exitEditing() {
setEditBox(false);
}
return (
<div className="list">
{editBox ? <EditItem
lightMode={lightMode}
tags={() => tags}
onExit={exitEditing}
SetLoader={SetLoader}
reFetch={reFetch}
item={data[editIndex]}
/> : null}
{/* eslint-disable-next-line */}
{data.map((e, i, array) => {
try {
const url = new URL(e.link);
const favicon = 'https://www.google.com/s2/favicons?domain=' + url.hostname;
return (<LazyLoad key={i} height={200} offset={200}>
<div className="list-row">
<div className="img-content-grp">
<img alt='' src={favicon} />
<div className="list-entity-content">
<div className='row-name'>
<span className="num">{i + 1}.</span>
{e.name}
<a
className='link'
target="_blank"
rel="noreferrer"
href={e.link}
>
({url.hostname})
</a>
</div>
<div className='title'>{e.title}</div>
<div className="tags">
{e.tag.map((e, i) => {
const tagPath = `/tags/${e}`;
return (<Link to={tagPath} key={i}>{e}</Link>)
})}
</div>
<div className='date'>{new Date(e.date).toDateString()}</div>
</div>
</div>
<div className='etc'>
<ViewArchived className='view-archived' id={e._id} />
<button className="btn edit-btn" onClick={() => edit(i)}>&#xf303;</button>
</div>
</div>
</LazyLoad>)
} catch (e) {
console.log(e);
}
})}
</div>
)
}
return (
<div className="list">
{editBox ? (
<EditItem
lightMode={lightMode}
tags={() => tags}
onExit={exitEditing}
SetLoader={SetLoader}
reFetch={reFetch}
item={data[editIndex]}
/>
) : null}
{/* eslint-disable-next-line */}
{data.map((e, i, array) => {
try {
const url = new URL(e.link);
const favicon =
"https://www.google.com/s2/favicons?domain=" + url.hostname;
return (
<LazyLoad key={i} height={200} offset={200}>
<div className="list-row">
<div className="img-content-grp">
<img alt="" src={favicon} />
<div className="list-entity-content">
<div className="row-name">
<span className="num">{i + 1}.</span>
{e.name}
<a
className="link"
target="_blank"
rel="noreferrer"
href={e.link}
>
({url.hostname})
</a>
</div>
<div className="title">{e.title}</div>
<div className="tags">
{e.tag.map((e, i) => {
const tagPath = `/tags/${e}`;
return (
<Link to={tagPath} key={i}>
{e}
</Link>
);
})}
</div>
<div className="date">
{new Date(e.date).toDateString()}
</div>
</div>
</div>
<div className="etc">
<ViewArchived className="view-archived" id={e._id} />
<button className="btn edit-btn" onClick={() => edit(i)}>
&#xf303;
</button>
</div>
</div>
</LazyLoad>
);
} catch (e) {
console.log(e);
}
})}
</div>
);
};
export default List
export default List;
+6 -7
View File
@@ -1,13 +1,12 @@
import '../styles/Loader.css';
import { InfinitySpin } from 'react-loader-spinner'
import "../styles/Loader.css";
import { InfinitySpin } from "react-loader-spinner";
const Loader = ({ lightMode }) => {
return (
<div className='loader'>
<div className="loader">
<InfinitySpin color={lightMode ? "Black" : "White"} />
</div>
)
}
);
};
export default Loader
export default Loader;
+7 -7
View File
@@ -1,12 +1,12 @@
import React from 'react'
import React from "react";
const NoResults = () => {
return (
<div className='no-results'>
<h1>¯\_()_/¯</h1>
<p>Nothing found.</p>
<div className="no-results">
<h1>¯\_()_/¯</h1>
<p>Nothing found.</p>
</div>
)
}
);
};
export default NoResults;
export default NoResults;
+55 -40
View File
@@ -1,47 +1,62 @@
import { ProSidebar, SidebarHeader, SidebarFooter, SidebarContent, Menu, MenuItem, SubMenu } from 'react-pro-sidebar';
import 'react-pro-sidebar/dist/css/styles.css';
import '../styles/SideBar.css';
import {
ProSidebar,
SidebarHeader,
SidebarFooter,
SidebarContent,
Menu,
MenuItem,
SubMenu,
} from "react-pro-sidebar";
import "react-pro-sidebar/dist/css/styles.css";
import "../styles/SideBar.css";
import { Link } from "react-router-dom";
const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
const sortedTags = tags.sort((a, b) => {
const A = a.toLowerCase(), B = b.toLowerCase();
if (A < B)
return -1;
if (A > B)
return 1;
return 0;
});
const sortedTags = tags.sort((a, b) => {
const A = a.toLowerCase(),
B = b.toLowerCase();
if (A < B) return -1;
if (A > B) return 1;
return 0;
});
return (
<ProSidebar
toggled={toggle}
breakPoint="lg"
onToggle={handleToggleSidebar}
className='sidebar'>
<SidebarHeader>
<ProSidebar
toggled={toggle}
breakPoint="lg"
onToggle={handleToggleSidebar}
className="sidebar"
>
<SidebarHeader>
<h1>LinkWarden</h1>
</SidebarHeader>
<SidebarContent className='sidebar-content'>
</SidebarHeader>
<SidebarContent className="sidebar-content">
<Menu iconShape="circle">
<MenuItem><Link to="/"><h3>Show Everything</h3></Link></MenuItem>
<SubMenu icon='#' defaultOpen={true} title='Tags'>
{sortedTags.map((e, i) => {
const path = `/tags/${e}`;
return <MenuItem key={i}><Link to={path}>{e}</Link></MenuItem>
})}
</SubMenu>
</Menu>
</SidebarContent>
<SidebarFooter>
<p className='credits'>©{new Date().getFullYear()} Made with 💙 by <a href='https://github.com/Daniel31x13'>Daniel 31X13</a></p>
</SidebarFooter>
</ProSidebar>
)
}
<MenuItem>
<Link to="/">
<h3>Show Everything</h3>
</Link>
</MenuItem>
export default SideBar
<SubMenu icon="#" defaultOpen={true} title="Tags">
{sortedTags.map((e, i) => {
const path = `/tags/${e}`;
return (
<MenuItem key={i}>
<Link to={path}>{e}</Link>
</MenuItem>
);
})}
</SubMenu>
</Menu>
</SidebarContent>
<SidebarFooter>
<p className="credits">
©{new Date().getFullYear()} Made with 💙 by{" "}
<a href="https://github.com/Daniel31x13">Daniel 31X13</a>
</p>
</SidebarFooter>
</ProSidebar>
);
};
export default SideBar;
+35 -23
View File
@@ -1,32 +1,44 @@
import '../styles/Sort.css'
import "../styles/Sort.css";
const Sort = ({ sortBy, onExit }) => {
function abort(e) {
if (e.target.className === "sort-overlay") {
onExit();
}
function abort(e) {
if (e.target.className === "sort-overlay") {
onExit();
}
}
function sort(e) {
sortBy(e.target.value);
}
function sort(e) {
sortBy(e.target.value);
}
return (
<>
<div className='sort-overlay' onClick={abort}></div>
<div className='sort-box'>
<fieldset className='sort' onClick={sort}>
<legend>Sort by</legend>
<button className='sort-by-btn' value='Default'>&#xf271; Date (Newest first)</button>
<button className='sort-by-btn' value='Date (Oldest first)'>&#xf272; Date (Oldest first)</button>
<button className='sort-by-btn' value='Name (A-Z)'>&#xf15d; Name (A-Z)</button>
<button className='sort-by-btn' value='Name (Z-A)'>&#xf15e; Name (Z-A)</button>
<button className='sort-by-btn' value='Title (A-Z)'>&#xf15d; Website title (A-Z)</button>
<button className='sort-by-btn' value='Title (Z-A)'>&#xf15e; Website title (Z-A)</button>
</fieldset>
</div>
<div className="sort-overlay" onClick={abort}></div>
<div className="sort-box">
<fieldset className="sort" onClick={sort}>
<legend>Sort by</legend>
<button className="sort-by-btn" value="Default">
&#xf271; Date (Newest first)
</button>
<button className="sort-by-btn" value="Date (Oldest first)">
&#xf272; Date (Oldest first)
</button>
<button className="sort-by-btn" value="Name (A-Z)">
&#xf15d; Name (A-Z)
</button>
<button className="sort-by-btn" value="Name (Z-A)">
&#xf15e; Name (Z-A)
</button>
<button className="sort-by-btn" value="Title (A-Z)">
&#xf15d; Website title (A-Z)
</button>
<button className="sort-by-btn" value="Title (Z-A)">
&#xf15e; Website title (Z-A)
</button>
</fieldset>
</div>
</>
)
}
);
};
export default Sort
export default Sort;
+35 -32
View File
@@ -1,68 +1,71 @@
import CreatableSelect from "react-select/creatable";
// lightMode ? "Black" : "White"
export default function TagSelection({setTags, tags, tag=[], lightMode}) {
export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
const customStyles = {
container: (provided) => ({
...provided,
textShadow: 'none',
textShadow: "none",
}),
placeholder: (provided) => ({
...provided,
color: '#a9a9a9',
color: "#a9a9a9",
}),
multiValueRemove: (provided) => ({
...provided,
color: 'gray',
color: "gray",
}),
indicatorSeparator: (provided) => ({
...provided,
display: 'none',
display: "none",
}),
menu: (provided) => ({
...provided,
border: 'solid',
borderWidth: '1px',
borderRadius: '0px',
borderColor: 'rgb(141, 141, 141)',
opacity: '90%',
color: 'gray',
border: "solid",
borderWidth: "1px",
borderRadius: "0px",
borderColor: "rgb(141, 141, 141)",
opacity: "90%",
color: "gray",
background: lightMode ? "lightyellow" : "#273949",
boxShadow: 'rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px',
boxShadow:
"rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px",
}),
input: (provided) => ({
...provided,
color: lightMode ? "rgb(64, 64, 64)" : "white",
}),
}),
control: (provided, state) => ({
...provided,
background: lightMode ? "lightyellow" : "#273949",
border: 'none',
borderRadius: '0px',
boxShadow: state.isFocused ? 'rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px' : 'rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset',
border: "none",
borderRadius: "0px",
boxShadow: state.isFocused
? "rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px"
: "rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset",
}),
}
};
const data = tags().map((e) => {
return { value: e, label: e }
})
return { value: e, label: e };
});
const defaultTags = tag.map((e) => {
return { value: e, label: e }
})
return { value: e, label: e };
});
return (
<CreatableSelect
defaultValue={defaultTags}
styles={customStyles}
isMulti
onChange={setTags}
options={data}
defaultValue={defaultTags}
styles={customStyles}
isMulti
onChange={setTags}
options={data}
/>
);
}
+22 -11
View File
@@ -1,17 +1,28 @@
import '../styles/ViewArchived.css';
import config from '../config';
import "../styles/ViewArchived.css";
import config from "../config";
const ViewArchived = ({ id }) => {
const screenshotPath = config.API.ADDRESS + ":" + config.API.PORT + '/screenshots/' + id + '.png';
const pdfPath = config.API.ADDRESS + ":" + config.API.PORT + '/pdfs/' + id + '.pdf';
const screenshotPath =
config.API.ADDRESS + ":" + config.API.PORT + "/screenshots/" + id + ".png";
const pdfPath =
config.API.ADDRESS + ":" + config.API.PORT + "/pdfs/" + id + ".pdf";
return (
<div className='view-archived'>
<a className='link' href={screenshotPath} target='_blank' rel="noreferrer">Screenshot</a>
<hr className='seperator' />
<a className='link' href={pdfPath} target='_blank' rel="noreferrer">PDF</a>
<div className="view-archived">
<a
className="link"
href={screenshotPath}
target="_blank"
rel="noreferrer"
>
Screenshot
</a>
<hr className="seperator" />
<a className="link" href={pdfPath} target="_blank" rel="noreferrer">
PDF
</a>
</div>
)
}
);
};
export default ViewArchived;
export default ViewArchived;