Merge pull request #9 from Daniel31x13/Add-folder-support-(to-sidebar)
Added collections support (to sidebar)
This commit is contained in:
commit
9cac04eb7b
|
@ -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.
|
* 🏷 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).**
|
**Also take a look at our planned features in the [project roadmap section](https://github.com/Daniel31x13/link-warden/wiki#project-roadmap).**
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
|
@ -7,6 +7,8 @@ services:
|
||||||
image: mongo
|
image: mongo
|
||||||
volumes:
|
volumes:
|
||||||
- ./mongo:/data/db
|
- ./mongo:/data/db
|
||||||
|
ports:
|
||||||
|
- 27017:27017
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
link-warden-api:
|
link-warden-api:
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"react-select": "^5.3.2",
|
"react-select": "^5.3.2",
|
||||||
|
"sass": "^1.53.0",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -8448,6 +8449,11 @@
|
||||||
"url": "https://opencollective.com/immer"
|
"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": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz",
|
||||||
"integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA=="
|
"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": {
|
"node_modules/sass-loader": {
|
||||||
"version": "12.6.0",
|
"version": "12.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz",
|
||||||
"integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA=="
|
"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": {
|
"import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz",
|
||||||
"integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA=="
|
"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": {
|
"sass-loader": {
|
||||||
"version": "12.6.0",
|
"version": "12.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"react-select": "^5.3.2",
|
"react-select": "^5.3.2",
|
||||||
|
"sass": "^1.53.0",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
42
src/App.js
42
src/App.js
|
@ -7,10 +7,11 @@ import Filters from "./componets/Filters";
|
||||||
import sortList from "./modules/sortList";
|
import sortList from "./modules/sortList";
|
||||||
import filter from "./modules/filterData";
|
import filter from "./modules/filterData";
|
||||||
import concatTags from "./modules/concatTags";
|
import concatTags from "./modules/concatTags";
|
||||||
import NoResults from "./componets/NoResults";
|
import concatCollections from "./modules/concatCollections";
|
||||||
import Loader from "./componets/Loader";
|
import Loader from "./componets/Loader";
|
||||||
import SideBar from "./componets/SideBar";
|
import SideBar from "./componets/SideBar";
|
||||||
import Tags from "./routes/Tags.js";
|
import Tags from "./routes/Tags.js";
|
||||||
|
import Collections from "./routes/Collections.js";
|
||||||
import { Route, Routes } from "react-router-dom";
|
import { Route, Routes } from "react-router-dom";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
@ -18,7 +19,6 @@ function App() {
|
||||||
[newBox, setNewBox] = useState(false),
|
[newBox, setNewBox] = useState(false),
|
||||||
[filterBox, setFilterBox] = useState(false),
|
[filterBox, setFilterBox] = useState(false),
|
||||||
[searchQuery, setSearchQuery] = useState(""),
|
[searchQuery, setSearchQuery] = useState(""),
|
||||||
[numberOfResults, setNumberOfResults] = useState(0),
|
|
||||||
[filterCheckbox, setFilterCheckbox] = useState([true, true, true]),
|
[filterCheckbox, setFilterCheckbox] = useState([true, true, true]),
|
||||||
[sortBy, setSortBy] = useState(1),
|
[sortBy, setSortBy] = useState(1),
|
||||||
[loader, setLoader] = useState(false),
|
[loader, setLoader] = useState(false),
|
||||||
|
@ -57,8 +57,6 @@ function App() {
|
||||||
|
|
||||||
const filteredData = filter(data, searchQuery, filterCheckbox);
|
const filteredData = filter(data, searchQuery, filterCheckbox);
|
||||||
|
|
||||||
const tags = concatTags(data);
|
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
const res = await fetch(API_HOST + "/api");
|
const res = await fetch(API_HOST + "/api");
|
||||||
const resJSON = await res.json();
|
const resJSON = await res.json();
|
||||||
|
@ -78,10 +76,6 @@ function App() {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setNumberOfResults(filteredData.length);
|
|
||||||
}, [filteredData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (lightMode) {
|
if (lightMode) {
|
||||||
document.body.classList.add("light");
|
document.body.classList.add("light");
|
||||||
|
@ -95,7 +89,8 @@ function App() {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<SideBar
|
<SideBar
|
||||||
tags={tags}
|
tags={concatTags(data)}
|
||||||
|
collections={concatCollections(data)}
|
||||||
handleToggleSidebar={handleToggleSidebar}
|
handleToggleSidebar={handleToggleSidebar}
|
||||||
toggle={toggle}
|
toggle={toggle}
|
||||||
/>
|
/>
|
||||||
|
@ -132,10 +127,6 @@ function App() {
|
||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{numberOfResults > 0 ? (
|
|
||||||
<p className="results">{numberOfResults} Bookmarks found</p>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{filterBox ? (
|
{filterBox ? (
|
||||||
<Filters
|
<Filters
|
||||||
filterCheckbox={filterCheckbox}
|
filterCheckbox={filterCheckbox}
|
||||||
|
@ -152,11 +143,12 @@ function App() {
|
||||||
onExit={exitAdding}
|
onExit={exitAdding}
|
||||||
reFetch={fetchData}
|
reFetch={fetchData}
|
||||||
lightMode={lightMode}
|
lightMode={lightMode}
|
||||||
tags={() => tags}
|
tags={() => concatTags(data)}
|
||||||
|
collections={() => concatCollections(data)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{numberOfResults === 0 ? <NoResults /> : null}
|
|
||||||
|
|
||||||
{loader ? <Loader lightMode={lightMode} /> : null}
|
{loader ? <Loader lightMode={lightMode} /> : null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -170,7 +162,8 @@ function App() {
|
||||||
lightMode={lightMode}
|
lightMode={lightMode}
|
||||||
SetLoader={SetLoader}
|
SetLoader={SetLoader}
|
||||||
data={filteredData}
|
data={filteredData}
|
||||||
tags={tags}
|
tags={concatTags(data)}
|
||||||
|
collections={concatCollections(data)}
|
||||||
reFetch={fetchData}
|
reFetch={fetchData}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -184,7 +177,22 @@ function App() {
|
||||||
lightMode={lightMode}
|
lightMode={lightMode}
|
||||||
SetLoader={SetLoader}
|
SetLoader={SetLoader}
|
||||||
data={filteredData}
|
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}
|
reFetch={fetchData}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,24 @@ import { useState } from "react";
|
||||||
import "../styles/SendItem.css";
|
import "../styles/SendItem.css";
|
||||||
import TagSelection from "./TagSelection";
|
import TagSelection from "./TagSelection";
|
||||||
import addItem from "../modules/send";
|
import addItem from "../modules/send";
|
||||||
|
import CollectionSelection from "./CollectionSelection";
|
||||||
|
|
||||||
const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
|
const AddItem = ({
|
||||||
const [name, setName] = useState("");
|
onExit,
|
||||||
const [link, setLink] = useState("");
|
reFetch,
|
||||||
const [tag, setTag] = useState([]);
|
tags,
|
||||||
|
collections,
|
||||||
|
SetLoader,
|
||||||
|
lightMode,
|
||||||
|
}) => {
|
||||||
|
const [name, setName] = useState(""),
|
||||||
|
[link, setLink] = useState(""),
|
||||||
|
[tag, setTag] = useState([]),
|
||||||
|
[collection, setCollection] = useState("Unsorted");
|
||||||
|
|
||||||
function newItem() {
|
function newItem() {
|
||||||
SetLoader(true);
|
SetLoader(true);
|
||||||
addItem(name, link, tag, reFetch, onExit, SetLoader, "POST");
|
addItem(name, link, tag, collection, reFetch, onExit, SetLoader, "POST");
|
||||||
}
|
}
|
||||||
|
|
||||||
function SetName(e) {
|
function SetName(e) {
|
||||||
|
@ -22,10 +31,13 @@ const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SetTags(value) {
|
function SetTags(value) {
|
||||||
setTag(value);
|
|
||||||
setTag(value.map((e) => e.value.toLowerCase()));
|
setTag(value.map((e) => e.value.toLowerCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SetCollection(value) {
|
||||||
|
setCollection(value.value);
|
||||||
|
}
|
||||||
|
|
||||||
function abort(e) {
|
function abort(e) {
|
||||||
if (e.target.className === "add-overlay") {
|
if (e.target.className === "add-overlay") {
|
||||||
onExit();
|
onExit();
|
||||||
|
@ -61,6 +73,14 @@ const AddItem = ({ onExit, reFetch, tags, SetLoader, lightMode }) => {
|
||||||
Tags: <span className="optional">(Optional)</span>
|
Tags: <span className="optional">(Optional)</span>
|
||||||
</h3>
|
</h3>
|
||||||
<TagSelection setTags={SetTags} tags={tags} lightMode={lightMode} />
|
<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">
|
<button onClick={newItem} className="send-btn">
|
||||||
Add 
|
Add 
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -3,10 +3,20 @@ import deleteEntity from "../modules/deleteEntity";
|
||||||
import "../styles/SendItem.css";
|
import "../styles/SendItem.css";
|
||||||
import TagSelection from "./TagSelection";
|
import TagSelection from "./TagSelection";
|
||||||
import editItem from "../modules/send";
|
import editItem from "../modules/send";
|
||||||
|
import CollectionSelection from "./CollectionSelection";
|
||||||
|
|
||||||
const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
|
const EditItem = ({
|
||||||
const [name, setName] = useState(item.name);
|
tags,
|
||||||
const [tag, setTag] = useState(item.tag);
|
collections,
|
||||||
|
item,
|
||||||
|
onExit,
|
||||||
|
SetLoader,
|
||||||
|
reFetch,
|
||||||
|
lightMode,
|
||||||
|
}) => {
|
||||||
|
const [name, setName] = useState(item.name),
|
||||||
|
[tag, setTag] = useState(item.tag),
|
||||||
|
[collection, setCollection] = useState(item.collection);
|
||||||
|
|
||||||
function EditItem() {
|
function EditItem() {
|
||||||
SetLoader(true);
|
SetLoader(true);
|
||||||
|
@ -14,6 +24,7 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
|
||||||
name,
|
name,
|
||||||
item.link,
|
item.link,
|
||||||
tag,
|
tag,
|
||||||
|
collection,
|
||||||
reFetch,
|
reFetch,
|
||||||
onExit,
|
onExit,
|
||||||
SetLoader,
|
SetLoader,
|
||||||
|
@ -33,10 +44,13 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SetTags(value) {
|
function SetTags(value) {
|
||||||
setTag(value);
|
|
||||||
setTag(value.map((e) => e.value.toLowerCase()));
|
setTag(value.map((e) => e.value.toLowerCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SetCollection(value) {
|
||||||
|
setCollection(value.value);
|
||||||
|
}
|
||||||
|
|
||||||
function abort(e) {
|
function abort(e) {
|
||||||
if (e.target.className === "add-overlay") {
|
if (e.target.className === "add-overlay") {
|
||||||
onExit();
|
onExit();
|
||||||
|
@ -50,10 +64,12 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
|
||||||
<div className="add-overlay" onClick={abort}></div>
|
<div className="add-overlay" onClick={abort}></div>
|
||||||
<div className="send-box">
|
<div className="send-box">
|
||||||
<div className="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}>
|
<button className="delete" onClick={deleteItem}>
|
||||||

|

|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
<div className="AddItem-content">
|
<div className="AddItem-content">
|
||||||
<h3>
|
<h3>
|
||||||
Link:{" "}
|
Link:{" "}
|
||||||
|
@ -89,6 +105,15 @@ const EditItem = ({ tags, item, onExit, SetLoader, reFetch, lightMode }) => {
|
||||||
tag={tag}
|
tag={tag}
|
||||||
lightMode={lightMode}
|
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">
|
<button onClick={EditItem} className="send-btn">
|
||||||
Update 
|
Update 
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -2,12 +2,14 @@ import "../styles/List.css";
|
||||||
import LazyLoad from "react-lazyload";
|
import LazyLoad from "react-lazyload";
|
||||||
import ViewArchived from "./ViewArchived";
|
import ViewArchived from "./ViewArchived";
|
||||||
import EditItem from "./EditItem";
|
import EditItem from "./EditItem";
|
||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import NoResults from "./NoResults";
|
||||||
|
|
||||||
const List = ({ data, tags, reFetch, SetLoader, lightMode }) => {
|
const List = ({ data, tags, collections, reFetch, SetLoader, lightMode }) => {
|
||||||
const [editBox, setEditBox] = useState(false);
|
const [editBox, setEditBox] = useState(false),
|
||||||
const [editIndex, setEditIndex] = useState(0);
|
[editIndex, setEditIndex] = useState(0),
|
||||||
|
[numberOfResults, setNumberOfResults] = useState(0);
|
||||||
|
|
||||||
function edit(index) {
|
function edit(index) {
|
||||||
setEditBox(true);
|
setEditBox(true);
|
||||||
|
@ -18,12 +20,23 @@ const List = ({ data, tags, reFetch, SetLoader, lightMode }) => {
|
||||||
setEditBox(false);
|
setEditBox(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNumberOfResults(data.length);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="list">
|
<div className="list">
|
||||||
|
{numberOfResults > 0 ? (
|
||||||
|
<p className="results">{numberOfResults} Bookmarks found</p>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{numberOfResults === 0 ? <NoResults /> : null}
|
||||||
|
|
||||||
{editBox ? (
|
{editBox ? (
|
||||||
<EditItem
|
<EditItem
|
||||||
lightMode={lightMode}
|
lightMode={lightMode}
|
||||||
tags={() => tags}
|
tags={() => tags}
|
||||||
|
collections={() => collections}
|
||||||
onExit={exitEditing}
|
onExit={exitEditing}
|
||||||
SetLoader={SetLoader}
|
SetLoader={SetLoader}
|
||||||
reFetch={reFetch}
|
reFetch={reFetch}
|
||||||
|
|
|
@ -7,11 +7,12 @@ import {
|
||||||
MenuItem,
|
MenuItem,
|
||||||
SubMenu,
|
SubMenu,
|
||||||
} from "react-pro-sidebar";
|
} 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 "../styles/SideBar.css";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
|
const SideBar = ({ tags, collections, handleToggleSidebar, toggle }) => {
|
||||||
const sortedTags = tags.sort((a, b) => {
|
const sortedTags = tags.sort((a, b) => {
|
||||||
const A = a.toLowerCase(),
|
const A = a.toLowerCase(),
|
||||||
B = b.toLowerCase();
|
B = b.toLowerCase();
|
||||||
|
@ -19,6 +20,19 @@ const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
|
||||||
if (A > B) return 1;
|
if (A > B) return 1;
|
||||||
return 0;
|
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 (
|
return (
|
||||||
<ProSidebar
|
<ProSidebar
|
||||||
toggled={toggle}
|
toggled={toggle}
|
||||||
|
@ -27,26 +41,47 @@ const SideBar = ({ tags, handleToggleSidebar, toggle }) => {
|
||||||
className="sidebar"
|
className="sidebar"
|
||||||
>
|
>
|
||||||
<SidebarHeader>
|
<SidebarHeader>
|
||||||
<h1>LinkWarden</h1>
|
<h3>LinkWarden</h3>
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<SidebarContent className="sidebar-content">
|
<SidebarContent className="sidebar-content">
|
||||||
<Menu iconShape="circle">
|
<Menu iconShape="circle">
|
||||||
<MenuItem icon={<h2 className="sidebar-icon"></h2>}>
|
<MenuItem icon={<h2 className="sidebar-icon"></h2>}>
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<h3 className="menu-item">All</h3>
|
<div className="menu-item">All</div>
|
||||||
|
</Link>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem icon={<h2 className="sidebar-icon"></h2>}>
|
||||||
|
<Link to="/collections/Unsorted">
|
||||||
|
<div className="menu-item">Unsorted</div>
|
||||||
</Link>
|
</Link>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
|
<SubMenu
|
||||||
|
icon={<h2 className="sidebar-icon"></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"></div>} key={i}>
|
||||||
|
<Link className="sidebar-entity" to={path}>{e}</Link>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SubMenu>
|
||||||
|
|
||||||
<SubMenu
|
<SubMenu
|
||||||
icon={<h2 className="sidebar-icon"></h2>}
|
icon={<h2 className="sidebar-icon"></h2>}
|
||||||
suffix={<span className="badge">{sortedTags.length}</span>}
|
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) => {
|
{sortedTags.map((e, i) => {
|
||||||
const path = `/tags/${e}`;
|
const path = `/tags/${e}`;
|
||||||
return (
|
return (
|
||||||
<MenuItem prefix={"#"} key={i}>
|
<MenuItem prefix={<div className="sidebar-item-prefix">#</div>} key={i}>
|
||||||
<Link to={path}>{e}</Link>
|
<Link className="sidebar-entity" to={path}>{e}</Link>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import CreatableSelect from "react-select/creatable";
|
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 = {
|
const customStyles = {
|
||||||
container: (provided) => ({
|
container: (provided) => ({
|
||||||
|
@ -13,16 +12,19 @@ export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
|
||||||
color: "#a9a9a9",
|
color: "#a9a9a9",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
option: (provided) => ({
|
||||||
|
...provided,
|
||||||
|
':before': {
|
||||||
|
content: '"#"',
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
multiValueRemove: (provided) => ({
|
multiValueRemove: (provided) => ({
|
||||||
...provided,
|
...provided,
|
||||||
color: "gray",
|
color: "gray",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
indicatorSeparator: (provided) => ({
|
|
||||||
...provided,
|
|
||||||
display: "none",
|
|
||||||
}),
|
|
||||||
|
|
||||||
menu: (provided) => ({
|
menu: (provided) => ({
|
||||||
...provided,
|
...provided,
|
||||||
border: "solid",
|
border: "solid",
|
||||||
|
@ -41,6 +43,14 @@ export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
|
||||||
color: lightMode ? "rgb(64, 64, 64)" : "white",
|
color: lightMode ? "rgb(64, 64, 64)" : "white",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
multiValueLabel: (provided) => ({
|
||||||
|
...provided,
|
||||||
|
':before': {
|
||||||
|
content: '"#"',
|
||||||
|
marginRight: 4,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
control: (provided, state) => ({
|
control: (provided, state) => ({
|
||||||
...provided,
|
...provided,
|
||||||
background: lightMode ? "lightyellow" : "#273949",
|
background: lightMode ? "lightyellow" : "#273949",
|
||||||
|
@ -61,6 +71,7 @@ export default function TagSelection({ setTags, tags, tag = [], lightMode }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CreatableSelect
|
<CreatableSelect
|
||||||
|
className="select"
|
||||||
defaultValue={defaultTags}
|
defaultValue={defaultTags}
|
||||||
styles={customStyles}
|
styles={customStyles}
|
||||||
isMulti
|
isMulti
|
||||||
|
|
|
@ -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;
|
|
@ -4,24 +4,24 @@ const filteredData = (
|
||||||
filterCheckbox
|
filterCheckbox
|
||||||
) => {
|
) => {
|
||||||
return data.filter((e) => {
|
return data.filter((e) => {
|
||||||
const name = e.name.toLowerCase().includes(searchQuery.toLowerCase());
|
const linkName = e.name.toLowerCase().includes(searchQuery.toLowerCase());
|
||||||
const title = e.title.toLowerCase().includes(searchQuery.toLowerCase());
|
const websiteTitle = e.title.toLowerCase().includes(searchQuery.toLowerCase());
|
||||||
const tags = e.tag.some((e) => e.includes(searchQuery.toLowerCase()));
|
const tags = e.tag.some((e) => e.includes(searchQuery.toLowerCase()));
|
||||||
|
|
||||||
if (filterCheckbox === [true, true, true]) {
|
if (filterCheckbox.every(e => e === true)) {
|
||||||
return name || title || tags;
|
return linkName || websiteTitle || tags;
|
||||||
} else if (filterCheckbox[0] && filterCheckbox[2]) {
|
} else if (filterCheckbox[0] && filterCheckbox[2]) {
|
||||||
return name || tags;
|
return linkName || tags;
|
||||||
} else if (filterCheckbox[0] && filterCheckbox[1]) {
|
} else if (filterCheckbox[0] && filterCheckbox[1]) {
|
||||||
return name || title;
|
return linkName || websiteTitle;
|
||||||
} else if (filterCheckbox[2] && filterCheckbox[1]) {
|
} else if (filterCheckbox[2] && filterCheckbox[1]) {
|
||||||
return tags || title;
|
return tags || websiteTitle;
|
||||||
} else if (filterCheckbox[0]) {
|
} else if (filterCheckbox[0]) {
|
||||||
return name;
|
return linkName;
|
||||||
} else if (filterCheckbox[1]) {
|
} else if (filterCheckbox[1]) {
|
||||||
return tags;
|
return websiteTitle;
|
||||||
} else if (filterCheckbox[2]) {
|
} else if (filterCheckbox[2]) {
|
||||||
return title;
|
return tags;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@ const addItem = async (
|
||||||
name,
|
name,
|
||||||
link,
|
link,
|
||||||
tag,
|
tag,
|
||||||
|
collection,
|
||||||
reFetch,
|
reFetch,
|
||||||
onExit,
|
onExit,
|
||||||
SetLoader,
|
SetLoader,
|
||||||
|
@ -36,6 +37,7 @@ const addItem = async (
|
||||||
title: title,
|
title: title,
|
||||||
link: link,
|
link: link,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
|
collection: collection,
|
||||||
date: dateCreated,
|
date: dateCreated,
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
@ -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;
|
|
@ -1,7 +1,7 @@
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import List from "../componets/List";
|
import List from "../componets/List";
|
||||||
|
|
||||||
const Tags = ({ data, tags, SetLoader, lightMode, reFetch }) => {
|
const Tags = ({ data, tags, collections, SetLoader, lightMode, reFetch }) => {
|
||||||
const { tagId } = useParams();
|
const { tagId } = useParams();
|
||||||
const dataWithMatchingTag = data.filter((e) => {
|
const dataWithMatchingTag = data.filter((e) => {
|
||||||
return e.tag.includes(tagId);
|
return e.tag.includes(tagId);
|
||||||
|
@ -13,6 +13,7 @@ const Tags = ({ data, tags, SetLoader, lightMode, reFetch }) => {
|
||||||
lightMode={lightMode}
|
lightMode={lightMode}
|
||||||
data={dataWithMatchingTag}
|
data={dataWithMatchingTag}
|
||||||
tags={tags}
|
tags={tags}
|
||||||
|
collections={collections}
|
||||||
SetLoader={SetLoader}
|
SetLoader={SetLoader}
|
||||||
reFetch={reFetch}
|
reFetch={reFetch}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding: 0px 20px 20px 20px;
|
padding: 0px 20px 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.head {
|
.head {
|
||||||
|
@ -86,21 +86,11 @@ input:focus {
|
||||||
outline: none;
|
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 {
|
.dark-light-btn {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select {
|
||||||
|
font-family: "Font Awesome 5 Free"
|
||||||
|
}
|
|
@ -172,9 +172,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete {
|
.delete {
|
||||||
margin: 20px 20px 20px 0px;
|
margin-top: 20px;
|
||||||
background-color: #273949;
|
margin-left: 10px;
|
||||||
float: right;
|
display: inline;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
@ -188,17 +188,13 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px,
|
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;
|
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;
|
border: none;
|
||||||
transition: background-color 0.1s;
|
transition: box-shadow 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete:hover {
|
.delete:hover {
|
||||||
background-color: rgba(255, 75, 75, 0.8);
|
|
||||||
color: #d8d8d8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete:active {
|
|
||||||
box-shadow: 0px 0px 10px rgb(255, 83, 140);
|
box-shadow: 0px 0px 10px rgb(255, 83, 140);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,3 +204,20 @@
|
||||||
opacity: 80%;
|
opacity: 80%;
|
||||||
margin-right: auto;
|
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;
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar h1 {
|
.sidebar h3 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,18 +17,11 @@
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pro-sidebar-layout {
|
|
||||||
background: #384952;
|
|
||||||
text-shadow: none;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
background-color: rgb(52, 121, 181);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-icon {
|
.sidebar-icon {
|
||||||
|
@ -47,3 +40,16 @@
|
||||||
.pro-inner-item {
|
.pro-inner-item {
|
||||||
margin-bottom: 10px;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
$sidebar-bg-color: #373737;
|
||||||
|
$submenu-bg-color: #373737;
|
||||||
|
|
||||||
|
@import '~react-pro-sidebar/dist/scss/styles.scss';
|
|
@ -23,11 +23,6 @@ body {
|
||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete {
|
|
||||||
background-color: #1f2c38;
|
|
||||||
color: #ffffffb6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-results {
|
.no-results {
|
||||||
background-color: #1f2c38;
|
background-color: #1f2c38;
|
||||||
}
|
}
|
||||||
|
@ -111,11 +106,6 @@ body {
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.light .delete {
|
|
||||||
background-color: lightyellow;
|
|
||||||
color: rgb(176, 176, 176);
|
|
||||||
}
|
|
||||||
|
|
||||||
.light input {
|
.light input {
|
||||||
background-color: lightyellow;
|
background-color: lightyellow;
|
||||||
color: black;
|
color: black;
|
||||||
|
|
Ŝarĝante…
Reference in New Issue