update
This commit is contained in:
@@ -23,6 +23,16 @@ function Page() {
|
||||
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(
|
||||
function () {
|
||||
async function startupApp() {
|
||||
@@ -82,7 +92,10 @@ function Page() {
|
||||
</BreadCrumbs>
|
||||
<div className="flex justify-end gap-4">
|
||||
<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
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -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() {
|
||||
return (
|
||||
<div>
|
||||
<Header name='Testowy test' age={18} isMan={true} />
|
||||
<Header name='Ala ma kota' age={24} isMan={false} />
|
||||
Main page test
|
||||
</div>
|
||||
)
|
||||
const [number, addNumber] = useState(0);
|
||||
const [showPopup, setShowPopup] = useState(true);
|
||||
|
||||
return (
|
||||
<>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
67
app/components/FilesEditor/AddDocument/index.tsx
Normal file
67
app/components/FilesEditor/AddDocument/index.tsx
Normal 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;
|
||||
@@ -11,6 +11,7 @@ import RenamePopup from "./ContextMenu/rename";
|
||||
import Pterodactyl from "@/components/Pterodactyl";
|
||||
import BreadCrumbs from "@/components/BreadCrumbs";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import AddDocument from "./AddDocument";
|
||||
|
||||
interface FileAttributes {
|
||||
name: string;
|
||||
@@ -23,6 +24,12 @@ interface FileProps {
|
||||
attributes: FileAttributes;
|
||||
}
|
||||
|
||||
interface NewDocumentState {
|
||||
show: boolean;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface ContextMenuState {
|
||||
show: boolean;
|
||||
x: number;
|
||||
@@ -34,6 +41,12 @@ interface RenamePopupState {
|
||||
show: boolean;
|
||||
}
|
||||
|
||||
const initialNewDocumentState: NewDocumentState = {
|
||||
show: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
|
||||
const initialContextMenuState: ContextMenuState = {
|
||||
show: false,
|
||||
x: 0,
|
||||
@@ -72,7 +85,6 @@ const Index = () => {
|
||||
}, []);
|
||||
|
||||
const fetchFiles = useCallback(async () => {
|
||||
console.log("chwytam pliki");
|
||||
const files = await pterodactyl.files.fetchFiles();
|
||||
setFileList(files);
|
||||
}, [pterodactyl]);
|
||||
@@ -168,20 +180,7 @@ const Index = () => {
|
||||
})}
|
||||
<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
|
||||
<AddDocument />
|
||||
</span>
|
||||
</li>
|
||||
</BreadCrumbs>
|
||||
|
||||
25
app/components/Icons/AddDocument/index.tsx
Normal file
25
app/components/Icons/AddDocument/index.tsx
Normal 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;
|
||||
49
app/components/Popup/index.tsx
Normal file
49
app/components/Popup/index.tsx
Normal 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;
|
||||
@@ -77,5 +77,29 @@ export default function files(pterodactyl: any) {
|
||||
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, "");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
export default function helpers(pterodactyl: any) {
|
||||
return {
|
||||
// helper what return auth header
|
||||
async authHeader() {
|
||||
async authHeader(contentType: string = "application/json") {
|
||||
return {
|
||||
Authorization: `Bearer ${pterodactyl.api_key}`,
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": contentType,
|
||||
Accept: "Application/vnd.pterodactyl.v1+json",
|
||||
};
|
||||
},
|
||||
@@ -28,5 +28,16 @@ export default function helpers(pterodactyl: any) {
|
||||
async getWorkingDirectory() {
|
||||
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;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ const Index = (props: LanguageSelectorProps) => {
|
||||
{Object.entries(languages).map(([key, value]) => (
|
||||
<option
|
||||
disabled={selectedLanguage === key}
|
||||
selected={selectedLanguage === key}
|
||||
defaultValue={selectedLanguage}
|
||||
// selected={selectedLanguage === key}
|
||||
key={key}
|
||||
value={key}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user