This commit is contained in:
2024-10-15 21:37:55 +00:00
parent e677a45ecd
commit 7302b27dc3
10 changed files with 233 additions and 28 deletions

View File

@@ -23,6 +23,16 @@ function Page() {
setLanguage(event.target.value); setLanguage(event.target.value);
}; };
const saveFile = async () => {
const panelApp = new Panel();
const pterodactyl = new Pterodactyl();
const credentials = await panelApp.getCredentials();
pterodactyl.setApiKey(credentials.api_key);
pterodactyl.setServerId(serverId);
await pterodactyl.files.saveContent(path, code);
};
useEffect( useEffect(
function () { function () {
async function startupApp() { async function startupApp() {
@@ -82,7 +92,10 @@ function Page() {
</BreadCrumbs> </BreadCrumbs>
<div className="flex justify-end gap-4"> <div className="flex justify-end gap-4">
<LanguageSelector onChange={setLanguageHandler} /> <LanguageSelector onChange={setLanguageHandler} />
<button className="ml-auto btn btn-base-100 text-success"> <button
className="ml-auto btn btn-base-100 text-success"
onClick={saveFile}
>
Save Save
</button> </button>
</div> </div>

View File

@@ -1,11 +1,27 @@
import Header from "@/components/Header" "use client";
import React, { useState } from "react";
import Popup from "@/components/Popup";
export default function Page() { export default function Page() {
return ( const [number, addNumber] = useState(0);
<div> const [showPopup, setShowPopup] = useState(true);
<Header name='Testowy test' age={18} isMan={true} />
<Header name='Ala ma kota' age={24} isMan={false} /> return (
Main page test <>
</div> <Popup
) show={showPopup}
title="Popup Title"
onClick={() => setShowPopup(false)}
>
<span className="text-base-content">{number}</span>
<button className="btn btn-sm" onClick={() => addNumber(number + 1)}>
Add{" "}
</button>
</Popup>
<button className="btn btn-sm" onClick={() => setShowPopup(!showPopup)}>
Toggle Popup
</button>
</>
);
} }

View File

@@ -0,0 +1,67 @@
"use client";
import React from "react";
import AddDocumentIcon from "@/components/Icons/AddDocument";
import Popup from "@/components/Popup";
import { useState } from "react";
import Pterodactyl from "@/components/Pterodactyl";
import { useSearchParams } from "next/navigation";
const Index = () => {
const [showPopup, setShowPopup] = useState(false);
const [fileName, setFileName] = useState("");
const urlParams = useSearchParams();
const serverId = urlParams.get("serverid") || "";
const pathParam = urlParams.get("path") || "/";
const apiKey = `${process.env.NEXT_PUBLIC_API_KEY}`;
const pterodactyl = new Pterodactyl();
function togglePopup() {
setShowPopup(!showPopup);
}
function handleOk() {
console.log({ fileName });
if (fileName) {
pterodactyl.setApiKey(apiKey);
pterodactyl.setServerId(serverId);
pterodactyl.helpers.setWorkingDirectory(pathParam);
pterodactyl.files.createFile(fileName);
}
setShowPopup(false);
}
return (
<>
<Popup
title="New file name"
show={showPopup}
onClickClose={togglePopup}
onClickOk={handleOk}
>
<div>
<input
type="text"
className="input input-sm input-bordered mb-4 text-base-content"
placeholder="File name"
value={fileName}
onChange={(e) => setFileName(e.target.value)}
/>
</div>
</Popup>
<button
onClick={() => {
setFileName("");
togglePopup();
}}
className="btn btn-sm"
>
<AddDocumentIcon />
Add Document
</button>
</>
);
};
export default Index;

View File

@@ -11,6 +11,7 @@ import RenamePopup from "./ContextMenu/rename";
import Pterodactyl from "@/components/Pterodactyl"; import Pterodactyl from "@/components/Pterodactyl";
import BreadCrumbs from "@/components/BreadCrumbs"; import BreadCrumbs from "@/components/BreadCrumbs";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import AddDocument from "./AddDocument";
interface FileAttributes { interface FileAttributes {
name: string; name: string;
@@ -23,6 +24,12 @@ interface FileProps {
attributes: FileAttributes; attributes: FileAttributes;
} }
interface NewDocumentState {
show: boolean;
x: number;
y: number;
}
interface ContextMenuState { interface ContextMenuState {
show: boolean; show: boolean;
x: number; x: number;
@@ -34,6 +41,12 @@ interface RenamePopupState {
show: boolean; show: boolean;
} }
const initialNewDocumentState: NewDocumentState = {
show: false,
x: 0,
y: 0,
};
const initialContextMenuState: ContextMenuState = { const initialContextMenuState: ContextMenuState = {
show: false, show: false,
x: 0, x: 0,
@@ -72,7 +85,6 @@ const Index = () => {
}, []); }, []);
const fetchFiles = useCallback(async () => { const fetchFiles = useCallback(async () => {
console.log("chwytam pliki");
const files = await pterodactyl.files.fetchFiles(); const files = await pterodactyl.files.fetchFiles();
setFileList(files); setFileList(files);
}, [pterodactyl]); }, [pterodactyl]);
@@ -168,20 +180,7 @@ const Index = () => {
})} })}
<li> <li>
<span className="inline-flex items-center gap-2"> <span className="inline-flex items-center gap-2">
<svg <AddDocument />
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> </span>
</li> </li>
</BreadCrumbs> </BreadCrumbs>

View File

@@ -0,0 +1,25 @@
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"
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>
</>
);
};
export default index;

View File

@@ -0,0 +1,49 @@
"use client";
import React from "react";
interface PopupProps extends React.HTMLAttributes<HTMLDivElement> {
show?: boolean;
title?: string;
children: React.ReactNode;
onClickClose?: React.MouseEventHandler<HTMLButtonElement>;
onClickOk?: React.MouseEventHandler<HTMLButtonElement>;
}
const Popup: React.FC<PopupProps> = ({
show = false,
title,
children,
...props
}) => {
if (!show) return null;
return (
<>
<div className="fixed top-0 left-0 w-full h-full bg-black opacity-75 z-10"></div>
<div className="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-20">
<div className="bg-base-100 p-8 rounded-lg">
{title && (
<h2 className="text-xl font-bold mb-4 text-base-content">
{title}
</h2>
)}
{children}
<div className="flex justify-between">
<button onClick={props.onClickClose} className="btn btn-sm">
Close
</button>
<button
onClick={props.onClickOk}
className="btn btn-sm btn-success"
>
Ok
</button>
</div>
</div>
</div>
</>
);
};
export default Popup;

View File

@@ -77,5 +77,29 @@ export default function files(pterodactyl: any) {
console.error("Error fetching data:", error); console.error("Error fetching data:", error);
} }
}, },
async saveContent(filename: string, content: string) {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_URL}/api/client/servers/${pterodactyl.server_id}/files/write?file=${filename}`,
{
method: "POST",
headers: await pterodactyl.helpers.authHeader("application/text"),
body: "'test'",
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching data:", error);
}
},
async createFile(filename: string) {
this.saveContent(filename, "");
},
}; };
} }

View File

@@ -1,10 +1,10 @@
export default function helpers(pterodactyl: any) { export default function helpers(pterodactyl: any) {
return { return {
// helper what return auth header // helper what return auth header
async authHeader() { async authHeader(contentType: string = "application/json") {
return { return {
Authorization: `Bearer ${pterodactyl.api_key}`, Authorization: `Bearer ${pterodactyl.api_key}`,
"Content-Type": "application/json", "Content-Type": contentType,
Accept: "Application/vnd.pterodactyl.v1+json", Accept: "Application/vnd.pterodactyl.v1+json",
}; };
}, },
@@ -28,5 +28,16 @@ export default function helpers(pterodactyl: any) {
async getWorkingDirectory() { async getWorkingDirectory() {
return pterodactyl.workingDirectory; return pterodactyl.workingDirectory;
}, },
// helper that get main site and get csrf token from it
async getCsrfToken() {
const response = await fetch(`${process.env.NEXT_PUBLIC_URL}`, {
method: "GET",
});
const text = await response.text();
const match = text.match(/<meta name="csrf-token" content="(.*)">/);
const csrfToken = match ? match[1] : null;
return csrfToken;
},
}; };
} }

View File

@@ -31,7 +31,8 @@ const Index = (props: LanguageSelectorProps) => {
{Object.entries(languages).map(([key, value]) => ( {Object.entries(languages).map(([key, value]) => (
<option <option
disabled={selectedLanguage === key} disabled={selectedLanguage === key}
selected={selectedLanguage === key} defaultValue={selectedLanguage}
// selected={selectedLanguage === key}
key={key} key={key}
value={key} value={key}
> >