added breadcrumbs

This commit is contained in:
2024-08-31 23:41:42 +00:00
parent 89d5975267
commit 39c85aa148
6 changed files with 154 additions and 27 deletions

View File

@@ -0,0 +1,77 @@
import React from "react";
import ServerIcon from "@/components/Icons/Server";
import FolderIcon from "@/components/Icons/Folder";
interface Props {
serverId: string;
path: string;
changeDirectory: (path: string) => void;
}
const index = ({ serverId, path, changeDirectory }: Props) => {
const onClickHandler = (e: React.MouseEvent) => {
const newPath = e.currentTarget.getAttribute("data-custom-attribute");
if (!newPath) return;
changeDirectory(newPath);
};
const elements = path.split("/").filter((p) => p !== "");
console.log(elements);
return (
<div>
<div className="breadcrumbs text-sm">
<ul>
<li>
<div className="mr-2">
<ServerIcon />
</div>
{serverId}
</li>
<li onClick={onClickHandler} data-custom-attribute="/">
<div className="mr-2">
<FolderIcon />
</div>
<a>/</a>
</li>
{elements.map((element, index) => {
const path = elements.slice(0, index + 1).join("/");
console.log("path", path);
return (
<li
key={index}
onClick={onClickHandler}
data-custom-attribute={"/" + path}
>
<div className="mr-2">
<FolderIcon />
</div>
<a>{element}</a>
</li>
);
})}
<li>
<span className="inline-flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
className="h-4 w-4 stroke-current"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
></path>
</svg>
Add Document
</span>
</li>
</ul>
</div>
</div>
);
};
export default index;

View File

@@ -8,6 +8,7 @@ import MenuIcon from "@/components/Icons/Menu";
import ContextMenuContainer from "./ContextMenu/container";
import RenamePopup from "./ContextMenu/rename";
import Pterodactyl from "@/components/Pterodactyl";
import BreadCrumbs from "./BreadCrumbs";
interface FileAttributes {
name: string;
@@ -53,11 +54,11 @@ const Index = () => {
);
const [selectedFile, setSelectedFile] = useState<FileProps | null>(null);
const [ptero, setPtero] = useState<Pterodactyl | null>(null);
const [serverId, setServerId] = useState<string>("");
const [serverId, setServerId] = useState<string>("ec46691a");
const [path, setPath] = useState<string>("/world");
const setCredentials = useCallback(async () => {
const setCredentials = useCallback(() => {
setApiKey("ptlc_N77A2hEczFmSwGXm4cEXh4Gw3ZP0Ygr5NaBkGlE7pjU");
setServerId("ec46691a");
}, []);
const showRenamePopup = useCallback(() => {
@@ -69,21 +70,20 @@ const Index = () => {
setRenamePopup(initialRenamePopupState);
}, []);
const formateDate = (isoDate: string) => {
const date = new Date(isoDate);
return formatDistanceToNow(date, { addSuffix: true });
};
const fetchFiles = useCallback(async (ptero: Pterodactyl) => {
const files = await ptero.files.fetchFiles();
setFileList(files);
}, []);
const handleRenameFile = useCallback(
(file: FileProps, newName: string) => {
async (file: FileProps, newName: string) => {
if (ptero) {
ptero.files.rename(file, newName).then(() => {
ptero.files.fetchFiles().then(setFileList); // Pobierz zaktualizowaną listę plików po zmianie nazwy
});
await ptero.files.rename(file, newName);
await fetchFiles(ptero);
setRenamePopup(initialRenamePopupState);
}
setRenamePopup(initialRenamePopupState);
},
[ptero]
[ptero, fetchFiles]
);
const handleClickContextMenu = useCallback(
@@ -98,24 +98,30 @@ const Index = () => {
setContextMenu(initialContextMenuState);
}, []);
const formatDate = useCallback((isoDate: string) => {
return formatDistanceToNow(new Date(isoDate), { addSuffix: true });
}, []);
const changeDirectory = useCallback(
(newPath: string) => {
if (ptero) {
ptero.helpers.setWorkingDirectory(newPath);
fetchFiles(ptero);
setPath(newPath);
}
},
[ptero, fetchFiles]
);
useEffect(() => {
const setupApplication = async () => {
await setCredentials();
while (!apiKey) {
await new Promise((r) => setTimeout(r, 200));
if (apiKey) {
const pteroInstance = new Pterodactyl(serverId, apiKey);
pteroInstance.helpers.setWorkingDirectory(path);
setPtero(pteroInstance);
await fetchFiles(pteroInstance);
}
const pterodactylInstance = new Pterodactyl(serverId, apiKey);
setPtero(pterodactylInstance);
const files = await pterodactylInstance.files.fetchFiles();
setFileList(files);
};
setupApplication();
}, [apiKey, serverId, setCredentials]);
}, [apiKey, serverId, setCredentials, path, fetchFiles]);
return (
<>
@@ -136,6 +142,13 @@ const Index = () => {
file={contextMenu.file}
/>
)}
<div className="flex p-4 gap-4">
<BreadCrumbs
serverId={serverId}
path={path}
changeDirectory={changeDirectory}
/>
</div>
{fileList.map((file: FileProps) => (
<div
@@ -147,10 +160,12 @@ const Index = () => {
</div>
<div className="w-64 text-left">{file.attributes.name}</div>
<div className="w-48 text-right">
{file.attributes.is_file ? file.attributes.size + " bytes" : ""}
{file.attributes.is_file ? `${file.attributes.size} bytes` : ""}
</div>
<div title={file.attributes.modified_at} className="w-60 text-right">
{formateDate(file.attributes.modified_at)}
{formatDistanceToNow(new Date(file.attributes.modified_at), {
addSuffix: true,
})}
</div>
<div onClick={(e) => handleClickContextMenu(e, file)}>
<MenuIcon />

View File

@@ -0,0 +1,24 @@
import React from "react";
const index = () => {
return (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="size-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M21.75 17.25v-.228a4.5 4.5 0 0 0-.12-1.03l-2.268-9.64a3.375 3.375 0 0 0-3.285-2.602H7.923a3.375 3.375 0 0 0-3.285 2.602l-2.268 9.64a4.5 4.5 0 0 0-.12 1.03v.228m19.5 0a3 3 0 0 1-3 3H5.25a3 3 0 0 1-3-3m19.5 0a3 3 0 0 0-3-3H5.25a3 3 0 0 0-3 3m16.5 0h.008v.008h-.008v-.008Zm-3 0h.008v.008h-.008v-.008Z"
/>
</svg>
</>
);
};
export default index;

View File

@@ -12,7 +12,7 @@ export default function files(pterodactyl: any) {
method: "PUT",
headers: await pterodactyl.helpers.authHeader(),
body: JSON.stringify({
root: "/",
root: pterodactyl.workingDirectory,
files: [
{
from: from.attributes.name,
@@ -34,7 +34,7 @@ export default function files(pterodactyl: any) {
async fetchFiles() {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_URL}/api/client/servers/${pterodactyl.server_id}/files/list`,
`${process.env.NEXT_PUBLIC_URL}/api/client/servers/${pterodactyl.server_id}/files/list?directory=${pterodactyl.workingDirectory}`,
{
method: "GET",
headers: await pterodactyl.helpers.authHeader(),

View File

@@ -18,5 +18,15 @@ export default function helpers(pterodactyl: any) {
async setServerID(serverID: string) {
return (pterodactyl.server_id = serverID);
},
// setter for working directory
async setWorkingDirectory(workingDirectory: string) {
return (pterodactyl.workingDirectory = workingDirectory);
},
// getter for working directory
async getWorkingDirectory() {
return pterodactyl.workingDirectory;
},
};
}

View File

@@ -6,6 +6,7 @@ class Pterodactyl {
api_key: string;
files: any;
helpers: any;
workingDirectory: string = "/";
constructor(server_id: string, api_key: string) {
this.server_id = server_id;