diff --git a/assets/css/export.css b/assets/css/export.css index 80fcc6e..84d7b5f 100644 --- a/assets/css/export.css +++ b/assets/css/export.css @@ -214,21 +214,37 @@ border: 1px solid var(--border-color); } -.export-commands code { - background: var(--background-color); - padding: 4px 8px; - border-radius: 3px; - font-family: 'Courier New', monospace; +.export-command-container { + margin: 20px 0; border: 1px solid var(--border-color); - display: inline-block; - margin-top: 8px; + border-radius: 8px; + overflow: hidden; +} + +.export-command { + background: var(--header-background); + padding: 16px; + border-bottom: 1px solid var(--border-color); +} + +.export-command code { + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 13px; + line-height: 1.4; + color: var(--text-color); + word-break: break-all; + display: block; + background: none; + border: none; + padding: 0; + margin: 0; } .export-actions { display: flex; - gap: 12px; - justify-content: flex-end; - margin-top: 20px; + gap: 8px; + padding: 12px 16px; + background: var(--card-background); } .export-actions button { @@ -254,6 +270,124 @@ .export-actions button:last-child:hover { background: var(--primary-color-dark, #0056b3); } + +.copy-btn, .close-btn { + padding: 8px 16px; + border: 1px solid var(--border-color); + border-radius: 6px; + background: var(--card-background); + color: var(--text-color); + cursor: pointer; + transition: all 0.2s ease; + font-size: 14px; + display: flex; + align-items: center; + gap: 4px; +} + +.copy-btn:hover { + background: var(--primary-color, #007bff); + color: white; + border-color: var(--primary-color, #007bff); +} + +.close-btn { + background: #dc3545; + color: white; + border-color: #dc3545; + margin-left: auto; +} + +.close-btn:hover { + background: #c82333; + border-color: #bd2130; +} + +.export-details, .export-tips { + margin: 20px 0; + padding: 16px; + border-radius: 6px; + border: 1px solid var(--border-color); +} + +.export-details { + background: var(--header-background); +} + +.export-tips { + background: var(--card-background); + border-color: var(--primary-color, #007bff); + border-left: 4px solid var(--primary-color, #007bff); +} + +.export-details h4, .export-tips h4 { + margin: 0 0 12px 0; + color: var(--text-color); + font-size: 16px; +} + +.export-details ul, .export-tips ul { + margin: 0; + padding-left: 20px; + color: var(--text-color); +} + +.export-details li, .export-tips li { + margin: 8px 0; + line-height: 1.5; +} + +.export-details code, .export-tips code { + background: var(--background-color); + padding: 2px 6px; + border-radius: 3px; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 12px; + border: 1px solid var(--border-color); +} + +.export-tips kbd { + background: var(--header-background); + border: 1px solid var(--border-color); + border-radius: 3px; + padding: 2px 6px; + font-family: inherit; + font-size: 12px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.copy-feedback { + position: absolute; + top: 10px; + right: 10px; + padding: 8px 12px; + border-radius: 4px; + font-size: 12px; + font-weight: 500; + z-index: 1003; + animation: fadeInOut 2s ease-in-out; +} + +.copy-feedback-success { + background: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.copy-feedback-error { + background: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +@keyframes fadeInOut { + 0% { opacity: 0; transform: translateY(-10px); } + 20% { opacity: 1; transform: translateY(0); } + 80% { opacity: 1; transform: translateY(0); } + 100% { opacity: 0; transform: translateY(-10px); } +} + +/* Dark theme adjustments */ [data-theme="dark"] .selection-checkbox { background: var(--card-background); border-color: var(--border-color); @@ -287,3 +421,20 @@ color: #f8d7da; border-color: #a94442; } + +[data-theme="dark"] .copy-feedback-success { + background: #155724; + color: #d4edda; + border-color: #1e7e34; +} + +[data-theme="dark"] .copy-feedback-error { + background: #721c24; + color: #f8d7da; + border-color: #a94442; +} + +[data-theme="dark"] .export-tips kbd { + background: var(--background-color); + color: var(--text-color); +} diff --git a/assets/js/export-manager.js b/assets/js/export-manager.js index ad9daeb..b60967b 100644 --- a/assets/js/export-manager.js +++ b/assets/js/export-manager.js @@ -52,7 +52,7 @@ export class ExportManager { this.toggleSelectionMode(); } if (e.key === 'Escape') { - this.clearSelection(); + this.exitSelectionMode(); } }); @@ -118,10 +118,17 @@ export class ExportManager { * Exit selection mode */ exitSelectionMode() { + const wasInSelectionMode = document.body.classList.contains('selection-mode'); + document.body.classList.remove('selection-mode'); document.getElementById('exportBtn').style.display = 'none'; document.getElementById('selectionCounter').style.display = 'none'; this.clearSelection(); + + // Show message if user was actually in selection mode + if (wasInSelectionMode) { + this.showMessage('Exited selection mode', 'info'); + } } /** @@ -229,17 +236,26 @@ export class ExportManager { return url; }); + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0]; + const outputName = `merged_plots_${timestamp}.pdf`; + const payload = { plots: actualPaths, layout: this.calculateLayout(actualPaths.length), - output_name: `merged_plots_${new Date().toISOString().split('T')[0]}.pdf` + output_name: outputName }; + // Generate a unique temporary filename + const tempFileName = `export_request_${Date.now()}.json`; + + // Get work directory from config or fallback + const workDir = window.galleryConfig?.workDir || '/work/kschmidt/web'; + // Save the request to a JSON file that can be picked up by a Python script const requestData = JSON.stringify(payload, null, 2); - // Since we can't directly call Python from the browser, we'll show instructions - this.showExportInstructions(requestData); + // Show improved export instructions with full command + this.showExportInstructions(requestData, tempFileName, workDir); } /** @@ -258,21 +274,49 @@ export class ExportManager { /** * Show export instructions to user */ - showExportInstructions(requestData) { + showExportInstructions(requestData, tempFileName, workDir) { + const tempFilePath = `/tmp/${tempFileName}`; + const fullCommand = `echo '${requestData.replace(/'/g, "'\\''")}' > ${tempFilePath} && cd ${workDir} && python export_plots.py ${tempFilePath}`; + const instructions = `
To export your selected plots, save the following data to a file called export_request.json and run the export script:
Run the following command in your terminal to export the selected plots:
+ +${fullCommand}
+ Command to run:
-cd /work/kschmidt/web && python export_plots.py export_request.json
+
+ ${tempFilePath}${workDir}python export_plots.py