Merge pull request #9 from Daniel31x13/Add-folder-support-(to-sidebar)

Added collections support (to sidebar)
This commit is contained in:
Daniel 2022-06-24 01:05:21 +04:30 committed by GitHub
commit 9cac04eb7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 380 additions and 101 deletions

View File

@ -38,6 +38,8 @@ The objective is to have a self-hosted place to keep useful links in one place,
* 🏷 Set multiple tags to each link.
* 🗂 Assign each link to a collection where we can further group links.
**Also take a look at our planned features in the [project roadmap section](https://github.com/Daniel31x13/link-warden/wiki#project-roadmap).**
## Installation

View File

@ -7,6 +7,8 @@ services:
image: mongo
volumes:
- ./mongo:/data/db
ports:
- 27017:27017
restart: unless-stopped
link-warden-api:

37
package-lock.json generated
View File

@ -20,6 +20,7 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"react-select": "^5.3.2",
"sass": "^1.53.0",
"web-vitals": "^2.1.4"
}
},
@ -8448,6 +8449,11 @@
"url": "https://opencollective.com/immer"
}
},
"node_modules/immutable": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
"integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -14030,6 +14036,22 @@
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz",
"integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA=="
},
"node_modules/sass": {
"version": "1.53.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz",
"integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==",
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/sass-loader": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
@ -22432,6 +22454,11 @@
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz",
"integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA=="
},
"immutable": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
"integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
},
"import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -26292,6 +26319,16 @@
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz",
"integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA=="
},
"sass": {
"version": "1.53.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz",
"integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==",
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
}
},
"sass-loader": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",

View File

@ -16,6 +16,7 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"react-select": "^5.3.2",
"sass": "^1.53.0",
"web-vitals": "^2.1.4"
},
"scripts": {

View File

@ -7,10 +7,11 @@ import Filters from "./componets/Filters";
import sortList from "./modules/sortList";
import filter from "./modules/filterData";
import concatTags from "./modules/concatTags";
import NoResults from "./componets/NoResults";
import concatCollections from "./modules/concatCollections";
import Loader from "./componets/Loader";
import SideBar from "./componets/SideBar";
import Tags from "./routes/Tags.js";
import Collections from "./routes/Collections.js";
import { Route, Routes } from "react-router-dom";
function App() {
@ -18,7 +19,6 @@ function App() {
[newBox, setNewBox] = useState(false),
[filterBox, setFilterBox] = useState(false),
[searchQuery, setSearchQuery] = useState(""),
[numberOfResults, setNumberOfResults] = useState(0),
[filterCheckbox, setFilterCheckbox] = useState([true, true, true]),
[sortBy, setSortBy] = useState(1),
[loader, setLoader] = useState(false),
@ -57,8 +57,6 @@ function App() {
const filteredData = filter(data, searchQuery, filterCheckbox);
const tags = concatTags(data);
async function fetchData() {
const res = await fetch(API_HOST + "/api");
const resJSON = await res.json();
@ -78,10 +76,6 @@ function App() {
// eslint-disable-next-line
}, []);
useEffect(() => {
setNumberOfResults(filteredData.length);
}, [filteredData]);
useEffect(() => {
if (lightMode) {
document.body.classList.add("light");
@ -95,7 +89,8 @@ function App() {
return (
<div className="App">
<SideBar
tags={tags}
tags={concatTags(data)}
collections={concatCollections(data)}
handleToggleSidebar={handleToggleSidebar}
toggle={toggle}
/>
@ -132,10 +127,6 @@ function App() {
></button>
</div>
{numberOfResults > 0 ? (
<p className="results">{numberOfResults} Bookmarks found</p>
) : null}
{filterBox ? (
<Filters
filterCheckbox={filterCheckbox}
@ -152,11 +143,12 @@ function App() {
onExit={exitAdding}
reFetch={fetchData}
lightMode={lightMode}
tags={() => tags}
tags={() => concatTags(data)}
collections={() => concatCollections(data)}
/>
) : null}
{numberOfResults === 0 ? <NoResults /> : null}
{loader ? <Loader lightMode={lightMode} /> : null}
</div>
@ -170,7 +162,8 @@ function App() {
lightMode={lightMode}
SetLoader={SetLoader}
data={filteredData}
tags={tags}
tags={concatTags(data)}
collections={concatCollections(data)}
reFetch={fetchData}
/>
</div>
@ -184,7 +177,22 @@ function App() {
lightMode={lightMode}
SetLoader={SetLoader}
data={filteredData}
tags={tags}
tags={concatTags(data)}
collections={concatCollections(data)}
reFetch={fetchData}
/>
}
/>
<Route
path="collections/:collectionId"
element={
<Collections
lightMode={lightMode}
SetLoader={SetLoader}
data={filteredData}
tags={concatTags(data)}
collections={concatCollections(data)}
reFetch={fetchData}
/>
}

View File

@ -2,15 +2,24 @@ import { useState } from "react";
import "../styles/SendItem.css";
import TagSelection from "./TagSelection";
import addItem from "../modules/send";
import CollectionSelection from "./CollectionSelection";
const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
const [name, setName] = useState("");
const [link, setLink] = useState("");
const [tag, setTag] = useState([]);
const AddItem = ({
onExit,
reFetch,
tags,
collections,
SetLoader,
lightMode,
}) => {
const [name, setName] = useState(""),
[link, setLink] = useState(""),
[tag, setTag] = useState([]),
[collection, setCollection] = useState("Unsorted");
function newItem() {
SetLoader(true);
addItem(name, link, tag, reFetch, onExit, SetLoader, "POST");
addItem(name, link, tag, collection, reFetch, onExit, SetLoader, "POST");
}
function SetName(e) {
@ -22,10 +31,13 @@ const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
}
function SetTags(value) {
setTag(value);
setTag(value.map((e) => e.value.toLowerCase()));
}
function SetCollection(value) {
setCollection(value.value);
}
function abort(e) {
if (e.target.className === "add-overlay") {
onExit();
@ -61,6 +73,14 @@ const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
Tags: <span className="optional">(Optional)</span>
</h3>
<TagSelection setTags={SetTags} tags={tags} lightMode={lightMode} />
<h3>
Collections: <span className="optional">(Optional)</span>
</h3>
<CollectionSelection
setCollection={SetCollection}
collections={collections}
lightMode={lightMode}
/>
<button onClick={newItem} className="send-btn">
Add &#xf067;
</button>

View File

@ -0,0 +1,82 @@
import CreatableSelect from "react-select/creatable";
export default function CollectionSelection({
setCollection,
collections,
collection = "Unsorted",
lightMode,
}) {
const customStyles = {
container: (provided) => ({
...provided,
textShadow: "none",
}),
placeholder: (provided) => ({
...provided,
color: "#a9a9a9",
}),
option: (provided) => ({
...provided,
':before': {
content: '""',
marginRight: 8,
},
}),
menu: (provided) => ({
...provided,
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",
}),
input: (provided) => ({
...provided,
color: lightMode ? "rgb(64, 64, 64)" : "white",
}),
singleValue: (provided) => ({
...provided,
':before': {
content: '""',
marginRight: 8,
},
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",
}),
};
const data = collections().map((e) => {
return { value: e, label: e };
});
const defaultCollection = { value: collection, label: collection };
return (
<CreatableSelect
className="select"
defaultValue={defaultCollection}
styles={customStyles}
onChange={setCollection}
options={data}
/>
);
}

View File

@ -3,10 +3,20 @@ import deleteEntity from "../modules/deleteEntity";
import "../styles/SendItem.css";
import TagSelection from "./TagSelection";
import editItem from "../modules/send";
import CollectionSelection from "./CollectionSelection";
const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
const [name, setName] = useState(item.name);
const [tag, setTag] = useState(item.tag);
const EditItem = ({
tags,
collections,
item,
onExit,
SetLoader,
reFetch,
lightMode,
}) => {
const [name, setName] = useState(item.name),
[tag, setTag] = useState(item.tag),
[collection, setCollection] = useState(item.collection);
function EditItem() {
SetLoader(true);
@ -14,6 +24,7 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
name,
item.link,
tag,
collection,
reFetch,
onExit,
SetLoader,
@ -33,10 +44,13 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
}
function SetTags(value) {
setTag(value);
setTag(value.map((e) => e.value.toLowerCase()));
}
function SetCollection(value) {
setCollection(value.value);
}
function abort(e) {
if (e.target.className === "add-overlay") {
onExit();
@ -50,10 +64,12 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
<div className="add-overlay" onClick={abort}></div>
<div className="send-box">
<div className="box">
<h2>Edit bookmark</h2>
<div className="title-delete-group">
<h2 className="edit-title">Edit bookmark</h2>
<button className="delete" onClick={deleteItem}>
&#xf2ed;
</button>
</div>
<div className="AddItem-content">
<h3>
Link:{" "}
@ -89,6 +105,15 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
tag={tag}
lightMode={lightMode}
/>
<h3>
Collection: <span className="optional">(Optional)</span>
</h3>
<CollectionSelection
setCollection={SetCollection}
collections={collections}
collection={collection}
lightMode={lightMode}
/>
<button onClick={EditItem} className="send-btn">
Update &#xf303;
</button>

View File

@ -2,12 +2,14 @@ import "../styles/List.css";
import LazyLoad from "react-lazyload";
import ViewArchived from "./ViewArchived";
import EditItem from "./EditItem";
import { useState } from "react";
import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import NoResults from "./NoResults";
const List = ({ data, tags, reFetch, SetLoader, lightMode }) => {
const [editBox, setEditBox] = useState(false);
const [editIndex, setEditIndex] = useState(0);
const List = ({ data, tags, collections, reFetch, SetLoader, lightMode }) => {
const [editBox, setEditBox] = useState(false),
[editIndex, setEditIndex] = useState(0),
[numberOfResults, setNumberOfResults] = useState(0);
function edit(index) {
setEditBox(true);
@ -18,12 +20,23 @@ const List = ({ data, tags, reFetch, SetLoader, lightMode }) => {
setEditBox(false);
}
useEffect(() => {
setNumberOfResults(data.length);
}, [data]);
return (
<div className="list">
{numberOfResults > 0 ? (
<p className="results">{numberOfResults} Bookmarks found</p>
) : null}
{numberOfResults === 0 ? <NoResults /> : null}
{editBox ? (
<EditItem
lightMode={lightMode}
tags={() => tags}
collections={() => collections}
onExit={exitEditing}
SetLoader={SetLoader}
reFetch={reFetch}

View File

@ -7,11 +7,12 @@ import {
MenuItem,
SubMenu,
} from "react-pro-sidebar";
import "react-pro-sidebar/dist/css/styles.css";
// import "react-pro-sidebar/dist/css/styles.css";
import "../styles/SideBar_S.scss";
import "../styles/SideBar.css";
import { Link } from "react-router-dom";
const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
const SideBar = ({ tags, collections, handleToggleSidebar, toggle }) => {
const sortedTags = tags.sort((a, b) => {
const A = a.toLowerCase(),
B = b.toLowerCase();
@ -19,6 +20,19 @@ const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
if (A > B) return 1;
return 0;
});
const sortedCollections = collections
.sort((a, b) => {
const A = a.toLowerCase(),
B = b.toLowerCase();
if (A < B) return -1;
if (A > B) return 1;
return 0;
})
.filter((e) => {
return e !== "Unsorted";
});
return (
<ProSidebar
toggled={toggle}
@ -27,26 +41,47 @@ const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
className="sidebar"
>
<SidebarHeader>
<h1>LinkWarden</h1>
<h3>LinkWarden</h3>
</SidebarHeader>
<SidebarContent className="sidebar-content">
<Menu iconShape="circle">
<MenuItem icon={<h2 className="sidebar-icon">&#xf015;</h2>}>
<MenuItem icon={<h2 className="sidebar-icon">&#xf49e;</h2>}>
<Link to="/">
<h3 className="menu-item">All</h3>
<div className="menu-item">All</div>
</Link>
</MenuItem>
<MenuItem icon={<h2 className="sidebar-icon">&#xf01c;</h2>}>
<Link to="/collections/Unsorted">
<div className="menu-item">Unsorted</div>
</Link>
</MenuItem>
<SubMenu
icon={<h2 className="sidebar-icon">&#xf5fd;</h2>}
suffix={<span className="badge">{sortedCollections.length}</span>}
title={<div className="menu-item">Collections</div>}
>
{sortedCollections.map((e, i) => {
const path = `/collections/${e}`;
return (
<MenuItem prefix={<div className="sidebar-item-prefix">&#xf07b;</div>} key={i}>
<Link className="sidebar-entity" to={path}>{e}</Link>
</MenuItem>
);
})}
</SubMenu>
<SubMenu
icon={<h2 className="sidebar-icon">&#xf02c;</h2>}
suffix={<span className="badge">{sortedTags.length}</span>}
title={<h3 className="menu-item">Tags</h3>}
title={<div className="menu-item">Tags</div>}
>
{sortedTags.map((e, i) => {
const path = `/tags/${e}`;
return (
<MenuItem prefix={"#"} key={i}>
<Link to={path}>{e}</Link>
<MenuItem prefix={<div className="sidebar-item-prefix">&#x23;</div>} key={i}>
<Link className="sidebar-entity" to={path}>{e}</Link>
</MenuItem>
);
})}

View File

@ -1,6 +1,5 @@
import CreatableSelect from "react-select/creatable";
// lightMode ? "Black" : "White"
export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
const customStyles = {
container: (provided) => ({
@ -13,16 +12,19 @@ export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
color: "#a9a9a9",
}),
option: (provided) => ({
...provided,
':before': {
content: '"#"',
marginRight: 8,
},
}),
multiValueRemove: (provided) => ({
...provided,
color: "gray",
}),
indicatorSeparator: (provided) => ({
...provided,
display: "none",
}),
menu: (provided) => ({
...provided,
border: "solid",
@ -41,6 +43,14 @@ export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
color: lightMode ? "rgb(64, 64, 64)" : "white",
}),
multiValueLabel: (provided) => ({
...provided,
':before': {
content: '"#"',
marginRight: 4,
},
}),
control: (provided, state) => ({
...provided,
background: lightMode ? "lightyellow" : "#273949",
@ -61,6 +71,7 @@ export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
return (
<CreatableSelect
className="select"
defaultValue={defaultTags}
styles={customStyles}
isMulti

View File

@ -0,0 +1,13 @@
const concatCollections = (data) => {
let collections = [];
for (let i = 0; i < data.length; i++) {
collections = collections.concat(data[i].collection);
}
collections = collections.filter((v, i, a) => a.indexOf(v) === i);
return collections;
};
export default concatCollections;

View File

@ -4,24 +4,24 @@ const filteredData = (
filterCheckbox
) => {
return data.filter((e) => {
const name = e.name.toLowerCase().includes(searchQuery.toLowerCase());
const title = e.title.toLowerCase().includes(searchQuery.toLowerCase());
const linkName = e.name.toLowerCase().includes(searchQuery.toLowerCase());
const websiteTitle = e.title.toLowerCase().includes(searchQuery.toLowerCase());
const tags = e.tag.some((e) => e.includes(searchQuery.toLowerCase()));
if (filterCheckbox === [true, true, true]) {
return name || title || tags;
if (filterCheckbox.every(e => e === true)) {
return linkName || websiteTitle || tags;
} else if (filterCheckbox[0] && filterCheckbox[2]) {
return name || tags;
return linkName || tags;
} else if (filterCheckbox[0] && filterCheckbox[1]) {
return name || title;
return linkName || websiteTitle;
} else if (filterCheckbox[2] && filterCheckbox[1]) {
return tags || title;
return tags || websiteTitle;
} else if (filterCheckbox[0]) {
return name;
return linkName;
} else if (filterCheckbox[1]) {
return tags;
return websiteTitle;
} else if (filterCheckbox[2]) {
return title;
return tags;
}
});
};

View File

@ -5,6 +5,7 @@ const addItem = async (
name,
link,
tag,
collection,
reFetch,
onExit,
SetLoader,
@ -36,6 +37,7 @@ const addItem = async (
title: title,
link: link,
tag: tag,
collection: collection,
date: dateCreated,
}),
headers: {

24
src/routes/Collections.js Normal file
View File

@ -0,0 +1,24 @@
import { useParams } from "react-router-dom";
import List from "../componets/List";
const Collections = ({ data, tags, collections, SetLoader, lightMode, reFetch }) => {
const { collectionId } = useParams();
const dataWithMatchingTag = data.filter((e) => {
return e.collection.includes(collectionId);
});
return (
<div className="content">
<List
lightMode={lightMode}
data={dataWithMatchingTag}
tags={tags}
collections={collections}
SetLoader={SetLoader}
reFetch={reFetch}
/>
</div>
);
};
export default Collections;

View File

@ -1,7 +1,7 @@
import { useParams } from "react-router-dom";
import List from "../componets/List";
const Tags = ({ data, tags, SetLoader, lightMode, reFetch }) => {
const Tags = ({ data, tags, collections, SetLoader, lightMode, reFetch }) => {
const { tagId } = useParams();
const dataWithMatchingTag = data.filter((e) => {
return e.tag.includes(tagId);
@ -13,6 +13,7 @@ const Tags = ({ data, tags, SetLoader, lightMode, reFetch }) => {
lightMode={lightMode}
data={dataWithMatchingTag}
tags={tags}
collections={collections}
SetLoader={SetLoader}
reFetch={reFetch}
/>

View File

@ -32,7 +32,7 @@
}
.content {
padding: 0px 20px 20px 20px;
padding: 0px 20px 0 20px;
}
.head {
@ -86,21 +86,11 @@ input:focus {
outline: none;
}
.results {
margin: 20px 20px 0px 0px;
display: inline-block;
}
.no-results {
text-align: center;
padding-top: 5%;
padding-bottom: 5%;
box-shadow: 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;
margin-top: 10px;
}
.dark-light-btn {
margin-left: 10px;
font-size: 1.2em;
}
.select {
font-family: "Font Awesome 5 Free"
}

View File

@ -172,9 +172,9 @@
}
.delete {
margin: 20px 20px 20px 0px;
background-color: #273949;
float: right;
margin-top: 20px;
margin-left: 10px;
display: inline;
font-size: 1.1rem;
width: 40px;
height: 40px;
@ -188,17 +188,13 @@
cursor: pointer;
box-shadow: 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;
background-color: #273949;
background-color: rgba(255, 75, 75, 0.8);
color: white;
border: none;
transition: background-color 0.1s;
transition: box-shadow 0.1s;
}
.delete:hover {
background-color: rgba(255, 75, 75, 0.8);
color: #d8d8d8;
}
.delete:active {
box-shadow: 0px 0px 10px rgb(255, 83, 140);
}
@ -208,3 +204,20 @@
opacity: 80%;
margin-right: auto;
}
.no-results {
text-align: center;
padding-top: 5%;
padding-bottom: 5%;
box-shadow: 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;
margin-top: 10px;
}
.edit-title {
display: inline;
}
.title-delete-group {
text-align: center;
}

View File

@ -3,7 +3,7 @@
position: fixed;
}
.sidebar h1 {
.sidebar h3 {
text-align: center;
}
@ -17,18 +17,11 @@
text-decoration: underline;
}
.pro-sidebar-layout {
background: #384952;
text-shadow: none;
color: white;
}
.badge {
padding: 3px 10px;
font-size: 0.8rem;
letter-spacing: 1px;
border-radius: 14px;
background-color: rgb(52, 121, 181);
}
.sidebar-icon {
@ -47,3 +40,16 @@
.pro-inner-item {
margin-bottom: 10px;
}
.sidebar-entity {
font-size: 1.2rem;
}
.sidebar-item-prefix {
font-family: "Font Awesome 5 Free";
}
.pro-sidebar-layout * {
color: white;
text-shadow: none;
}

View File

@ -0,0 +1,4 @@
$sidebar-bg-color: #373737;
$submenu-bg-color: #373737;
@import '~react-pro-sidebar/dist/scss/styles.scss';

View File

@ -23,11 +23,6 @@ body {
content: "";
}
.delete {
background-color: #1f2c38;
color: #ffffffb6;
}
.no-results {
background-color: #1f2c38;
}
@ -111,11 +106,6 @@ body {
color: gray;
}
.light .delete {
background-color: lightyellow;
color: rgb(176, 176, 176);
}
.light input {
background-color: lightyellow;
color: black;