diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index 0d8b6fb..91bf6fd 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -491,14 +491,80 @@ export default function AdminPage() {
};
function handleExportTarball() {
- fetch('/api/admin/export')
+ // Create popup modal
+ const modal = document.createElement('div');
+ modal.style.position = 'fixed';
+ modal.style.top = '0';
+ modal.style.left = '0';
+ modal.style.width = '100%';
+ modal.style.height = '100%';
+ modal.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
+ modal.style.display = 'flex';
+ modal.style.alignItems = 'center';
+ modal.style.justifyContent = 'center';
+ modal.style.zIndex = '1000';
+
+ const modalContent = document.createElement('div');
+ modalContent.style.backgroundColor = 'white';
+ modalContent.style.padding = '30px';
+ modalContent.style.borderRadius = '8px';
+ modalContent.style.maxWidth = '500px';
+ modalContent.style.width = '90%';
+ modalContent.style.textAlign = 'center';
+ modalContent.style.position = 'relative';
+
+ modalContent.innerHTML = `
+
+
Export Method
+ How are you hosting this application?
+ If you don't know your method of hosting, ask your Systems Administrator
+
+
+
+
+ `;
+
+ modal.appendChild(modalContent);
+ document.body.appendChild(modal);
+
+ // Add event listeners
+ const dockerBtn = modal.querySelector('#docker-btn');
+ const localBtn = modal.querySelector('#local-btn');
+ const closeBtn = modal.querySelector('#close-btn');
+
+ const closeModal = () => {
+ document.body.removeChild(modal);
+ };
+
+ dockerBtn?.addEventListener('click', () => {
+ closeModal();
+ exportFromEndpoint('/api/admin/export');
+ });
+
+ localBtn?.addEventListener('click', () => {
+ closeModal();
+ exportFromEndpoint('/api/admin/exportlocal');
+ });
+
+ closeBtn?.addEventListener('click', closeModal);
+
+ // Close modal when clicking outside
+ modal.addEventListener('click', (e) => {
+ if (e.target === modal) {
+ closeModal();
+ }
+ });
+ }
+
+ function exportFromEndpoint(endpoint: string) {
+ fetch(endpoint)
.then(async (res) => {
if (!res.ok) throw new Error('Export failed');
const blob = await res.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
- a.download = 'markdownblog-export.tar.gz';
+ a.download = endpoint.includes('local') ? 'local-export.tar.gz' : 'docker-export.tar.gz';
document.body.appendChild(a);
a.click();
a.remove();
diff --git a/src/app/api/admin/export/route.ts b/src/app/api/admin/export/route.ts
index 7c2bb61..f028e5d 100644
--- a/src/app/api/admin/export/route.ts
+++ b/src/app/api/admin/export/route.ts
@@ -3,6 +3,9 @@ import { NextResponse } from 'next/server';
import { statSync, createReadStream, existsSync } from 'fs';
import path from 'path';
+// This is the route for exporting posts when using the docker production server
+// If you try this on the local server, it will fail because the posts directory is not on the local server
+
export async function GET() {
try {
const dockerDir = '/app/docker'; // update this to your actual path
diff --git a/src/app/api/admin/exportlocal/route.ts b/src/app/api/admin/exportlocal/route.ts
new file mode 100644
index 0000000..fa760f7
--- /dev/null
+++ b/src/app/api/admin/exportlocal/route.ts
@@ -0,0 +1,47 @@
+import tar from 'tar';
+import { NextResponse } from 'next/server';
+import { statSync, createReadStream, existsSync } from 'fs';
+import path from 'path';
+import { gzip } from 'zlib';
+
+
+// This is the route for exporting posts when using the local production server
+// If you try this on the docker server, it will fail because the posts directory is not on the docker server
+
+export async function GET() {
+ try {
+ const localDir = 'posts';
+ const tarballName = 'local-export.tar.gz';
+ const tarballPath = path.join('/tmp', tarballName);
+
+ if (!existsSync(localDir)) {
+ return NextResponse.json({ error: `${localDir} directory does not exist` }, { status: 400 });
+ }
+
+ await tar.c(
+ {
+ gzip: true,
+ file: tarballPath,
+ cwd: path.dirname(localDir),
+ portable: true,
+ noMtime: true,
+ },
+ [path.basename(localDir)]
+ );
+
+ const stat = statSync(tarballPath);
+ const stream = createReadStream(tarballPath);
+
+ return new Response(stream as any, {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/gzip',
+ 'Content-Disposition': `attachment; filename="${tarballName}"`,
+ 'Content-Length': stat.size.toString(),
+ },
+ });
+ } catch (error) {
+ console.error('Error exporting local:', error);
+ return NextResponse.json({ error: 'Error exporting local' }, { status: 500 });
+ }
+}