mirror of
https://github.com/Ravinou/borgwarehouse
synced 2024-06-08 00:42:11 +02:00
perf: displayDetails pref is now in LocalStorage
This commit is contained in:
parent
b96bfbff13
commit
045f1d1576
|
@ -1,15 +1,61 @@
|
|||
//Lib
|
||||
import React from 'react';
|
||||
import { useState } from 'react';
|
||||
import classes from './Repo.module.css';
|
||||
import { IconSettings, IconInfoCircle } from '@tabler/icons-react';
|
||||
import {
|
||||
IconSettings,
|
||||
IconInfoCircle,
|
||||
IconChevronDown,
|
||||
IconChevronUp,
|
||||
} from '@tabler/icons-react';
|
||||
import timestampConverter from '../../helpers/functions/timestampConverter';
|
||||
import StorageBar from '../UI/StorageBar/StorageBar';
|
||||
import QuickCommands from './QuickCommands/QuickCommands';
|
||||
|
||||
export default function Repo(props) {
|
||||
//Load displayDetails from LocalStorage
|
||||
const displayDetailsFromLS = () => {
|
||||
try {
|
||||
if (
|
||||
localStorage.getItem('displayDetailsRepo' + props.id) === null
|
||||
) {
|
||||
localStorage.setItem(
|
||||
'displayDetailsRepo' + props.id,
|
||||
JSON.stringify(true)
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
return JSON.parse(
|
||||
localStorage.getItem('displayDetailsRepo' + props.id)
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(
|
||||
'LocalStorage error, key',
|
||||
'displayDetailsRepo' + props.id,
|
||||
'will be removed. Try again.',
|
||||
'Error message on this key : ',
|
||||
error
|
||||
);
|
||||
localStorage.removeItem('displayDetailsRepo' + props.id);
|
||||
}
|
||||
};
|
||||
|
||||
//States
|
||||
const [displayDetails, setDisplayDetails] = useState(displayDetailsFromLS);
|
||||
|
||||
//BUTTON : Display or not repo details for ONE repo
|
||||
const displayDetailsForOneHandler = (boolean) => {
|
||||
//Update localStorage
|
||||
localStorage.setItem(
|
||||
'displayDetailsRepo' + props.id,
|
||||
JSON.stringify(boolean)
|
||||
);
|
||||
setDisplayDetails(boolean);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.displayDetails ? (
|
||||
{displayDetails ? (
|
||||
<>
|
||||
<div className={classes.RepoOpen}>
|
||||
<div className={classes.openFlex}>
|
||||
|
@ -127,6 +173,27 @@ export default function Repo(props) {
|
|||
</div>
|
||||
</>
|
||||
)}
|
||||
{displayDetails ? (
|
||||
<div className={classes.chevron}>
|
||||
<IconChevronUp
|
||||
color='#494b7a'
|
||||
size={28}
|
||||
onClick={() => {
|
||||
displayDetailsForOneHandler(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes.chevron}>
|
||||
<IconChevronDown
|
||||
color='#494b7a'
|
||||
size={28}
|
||||
onClick={() => {
|
||||
displayDetailsForOneHandler(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
margin: 20px 0px 0px 0px;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
transition: max-height 0.2s linear;
|
||||
transition: max-height 0.1s linear;
|
||||
overflow: visible;
|
||||
/* Need to display comment on hover (which is position : absolute) */
|
||||
position: relative;
|
||||
|
@ -193,6 +193,17 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.chevron :focus,
|
||||
.chevron :hover {
|
||||
cursor: pointer;
|
||||
filter: invert(27%) sepia(82%) saturate(2209%) hue-rotate(240deg)
|
||||
brightness(99%) contrast(105%);
|
||||
}
|
||||
|
||||
/* MOBILE */
|
||||
@media all and (max-width: 1000px) {
|
||||
.tabInfo {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//Lib
|
||||
import classes from './RepoList.module.css';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { IconPlus, IconChevronDown, IconChevronUp } from '@tabler/icons-react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { IconPlus } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/router';
|
||||
import Link from 'next/link';
|
||||
import useSWR, { useSWRConfig } from 'swr';
|
||||
|
@ -48,7 +48,6 @@ export default function RepoList() {
|
|||
////States
|
||||
const [displayRepoAdd, setDisplayRepoAdd] = useState(false);
|
||||
const [displayRepoEdit, setDisplayRepoEdit] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
////Functions
|
||||
|
||||
|
@ -67,32 +66,6 @@ export default function RepoList() {
|
|||
return <ToastContainer />;
|
||||
}
|
||||
|
||||
//BUTTON : Display or not repo details for ONE repo
|
||||
const displayDetailsForOneHandler = async (id, boolean) => {
|
||||
setIsLoading(true);
|
||||
await fetch('/api/repo/id/' + id + '/displayDetails', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ displayDetails: boolean }),
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
mutate('/api/repo');
|
||||
setIsLoading(false);
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
toast.error('API error', toastOptions);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
setIsLoading(false);
|
||||
toast.error('API error', toastOptions);
|
||||
});
|
||||
};
|
||||
|
||||
//BUTTON : Display RepoManage component box for ADD
|
||||
const manageRepoAddHandler = () => {
|
||||
router.replace('/manage-repo/add');
|
||||
|
@ -131,45 +104,11 @@ export default function RepoList() {
|
|||
storageSize={repo.storageSize}
|
||||
storageUsed={repo.storageUsed}
|
||||
sshPublicKey={repo.sshPublicKey}
|
||||
displayDetails={repo.displayDetails}
|
||||
unixUser={repo.unixUser}
|
||||
comment={repo.comment}
|
||||
lanCommand={repo.lanCommand}
|
||||
repoManageEditHandler={() => repoManageEditHandler(repo.id)}
|
||||
></Repo>
|
||||
{repo.displayDetails ? (
|
||||
<div className={classes.chevron}>
|
||||
{isLoading ? (
|
||||
<IconChevronUp color='#494b7a' size={28} />
|
||||
) : (
|
||||
<IconChevronUp
|
||||
color='#494b7a'
|
||||
size={28}
|
||||
onClick={() => {
|
||||
displayDetailsForOneHandler(repo.id, false);
|
||||
// tell all SWRs with this key to revalidate
|
||||
mutate('/api/repo');
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes.chevron}>
|
||||
{isLoading ? (
|
||||
<IconChevronDown color='#494b7a' size={28} />
|
||||
) : (
|
||||
<IconChevronDown
|
||||
color='#494b7a'
|
||||
size={28}
|
||||
onClick={() => {
|
||||
displayDetailsForOneHandler(repo.id, true);
|
||||
// tell all SWRs with this key to revalidate
|
||||
mutate('/api/repo');
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -112,17 +112,6 @@
|
|||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.chevron {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.chevron :focus,
|
||||
.chevron :hover {
|
||||
cursor: pointer;
|
||||
filter: invert(27%) sepia(82%) saturate(2209%) hue-rotate(240deg)
|
||||
brightness(99%) contrast(105%);
|
||||
}
|
||||
|
||||
@media all and (max-width: 1000px) {
|
||||
.newRepoButton {
|
||||
display: none;
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
import { authOptions } from '../../../auth/[...nextauth]';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method == 'PUT') {
|
||||
//Verify that the user is logged in.
|
||||
const session = await getServerSession(req, res, authOptions);
|
||||
if (!session) {
|
||||
res.status(401).json({ message: 'You must be logged in.' });
|
||||
return;
|
||||
}
|
||||
|
||||
//The data we expect to receive
|
||||
const { displayDetails } = req.body;
|
||||
//We check that we receive displayDetails and it must be a bool.
|
||||
if (typeof displayDetails != 'boolean') {
|
||||
//If a variable is empty.
|
||||
res.status(422).json({
|
||||
message: 'Unexpected data',
|
||||
});
|
||||
//A return to make sure we don't go any further if data are incorrect.
|
||||
return;
|
||||
}
|
||||
try {
|
||||
//console.log('API call (PUT)');
|
||||
//Find the absolute path of the json directory
|
||||
const jsonDirectory = path.join(process.cwd(), '/config');
|
||||
let repoList = await fs.readFile(
|
||||
jsonDirectory + '/repo.json',
|
||||
'utf8'
|
||||
);
|
||||
//Parse the repoList
|
||||
repoList = JSON.parse(repoList);
|
||||
|
||||
//Find the ID in the data and change the values transmitted by the form
|
||||
let newRepoList = repoList.map((repo) =>
|
||||
repo.id == req.query.slug
|
||||
? {
|
||||
...repo,
|
||||
displayDetails: displayDetails,
|
||||
}
|
||||
: repo
|
||||
);
|
||||
//Stringify the newRepoList to write it into the json file.
|
||||
newRepoList = JSON.stringify(newRepoList);
|
||||
//Write the new json
|
||||
await fs.writeFile(
|
||||
jsonDirectory + '/repo.json',
|
||||
newRepoList,
|
||||
(err) => {
|
||||
if (err) console.log(err);
|
||||
}
|
||||
);
|
||||
res.status(200).json({ message: 'Envoi API réussi' });
|
||||
} catch (error) {
|
||||
//Log for backend
|
||||
console.log(error);
|
||||
//Log for frontend
|
||||
if (error.code == 'ENOENT') {
|
||||
res.status(500).json({
|
||||
status: 500,
|
||||
message: 'No such file or directory',
|
||||
});
|
||||
} else {
|
||||
res.status(500).json({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
res.status(405).json({
|
||||
status: 405,
|
||||
message: 'Method Not Allowed ',
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue