Skip to content

Commit 0166f4c

Browse files
committed
Add source document storage and editing functionality for document history
1 parent b0f87d1 commit 0166f4c

File tree

10 files changed

+123
-24
lines changed

10 files changed

+123
-24
lines changed

public/js/components/document-history.js

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,26 @@ export class DocumentHistory extends BaseComponent {
7575
background-color: var(--primary-dark);
7676
}
7777
78+
.edit-link {
79+
display: inline-block;
80+
padding: 5px 10px;
81+
background-color: var(--secondary-color, #6c757d);
82+
color: white;
83+
text-decoration: none;
84+
border-radius: 4px;
85+
font-size: 14px;
86+
margin-left: 5px;
87+
}
88+
89+
.edit-link:hover {
90+
background-color: var(--secondary-dark, #5a6268);
91+
}
92+
93+
.action-buttons {
94+
display: flex;
95+
gap: 5px;
96+
}
97+
7898
.pagination {
7999
display: flex;
80100
justify-content: space-between;
@@ -219,8 +239,9 @@ export class DocumentHistory extends BaseComponent {
219239
<td>${this._formatDate(item.generated_at)}</td>
220240
<td>${item.storage_path}</td>
221241
<td>${this._formatMetadata(item.metadata)}</td>
222-
<td>
242+
<td class="action-buttons">
223243
<button class="download-link" data-path="${item.storage_path}">Download</button>
244+
${item.source_doc ? `<button class="edit-link" data-source="${encodeURIComponent(item.source_doc)}" data-type="${item.document_type}">Edit</button>` : ''}
224245
</td>
225246
</tr>
226247
`).join('')}
@@ -363,6 +384,40 @@ export class DocumentHistory extends BaseComponent {
363384
}
364385
}
365386

387+
/**
388+
* Edit a document by pre-filling the HTML editor with the source document content
389+
* @param {string} sourceDocEncoded - URL-encoded source document content
390+
* @param {string} documentType - Type of document (pdf, doc, etc.)
391+
* @private
392+
*/
393+
_editDocument(sourceDocEncoded, documentType) {
394+
try {
395+
// Decode the source document content
396+
const sourceDoc = decodeURIComponent(sourceDocEncoded);
397+
398+
// Dispatch a custom event with the source document content
399+
const event = new CustomEvent('edit-document', {
400+
bubbles: true,
401+
composed: true,
402+
detail: {
403+
sourceDoc,
404+
documentType
405+
}
406+
});
407+
408+
this.dispatchEvent(event);
409+
410+
// Scroll to the top of the page to show the editor
411+
window.scrollTo({ top: 0, behavior: 'smooth' });
412+
413+
// Show a notification to the user
414+
alert('The editor has been pre-filled with the original content. You can now make changes and regenerate the document.');
415+
} catch (error) {
416+
console.error('Error editing document:', error);
417+
alert(`Error editing document: ${error.message}`);
418+
}
419+
}
420+
366421
/**
367422
* Initialize event listeners
368423
*/
@@ -387,15 +442,26 @@ export class DocumentHistory extends BaseComponent {
387442
}
388443
});
389444

390-
// Add event delegation for download buttons
445+
// Add event delegation for download and edit buttons
391446
this.shadowRoot.addEventListener('click', (event) => {
447+
// Handle download button clicks
392448
const downloadButton = event.target.closest('.download-link');
393449
if (downloadButton) {
394450
const path = downloadButton.dataset.path;
395451
if (path) {
396452
this._downloadDocument(path);
397453
}
398454
}
455+
456+
// Handle edit button clicks
457+
const editButton = event.target.closest('.edit-link');
458+
if (editButton) {
459+
const sourceDoc = editButton.dataset.source;
460+
const documentType = editButton.dataset.type;
461+
if (sourceDoc) {
462+
this._editDocument(sourceDoc, documentType);
463+
}
464+
}
399465
});
400466
}
401467

public/js/components/html-editor.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ export class HtmlEditor extends DocumentEditor {
7474
generateDocBtn.addEventListener('click', () => this.generateDoc());
7575
generateEpubBtn.addEventListener('click', () => this.generateEpub());
7676
convertToMarkdownBtn.addEventListener('click', () => this.convertToMarkdown());
77+
78+
// Listen for the edit-document event from the document history component
79+
document.addEventListener('edit-document', (event) => {
80+
const { sourceDoc, documentType } = event.detail;
81+
if (sourceDoc) {
82+
this.setContent(sourceDoc);
83+
this.updatePreview();
84+
this.showStatus(`Loaded original content for editing (${documentType} document)`, 'success');
85+
86+
// Scroll to the editor
87+
this.scrollIntoView({ behavior: 'smooth' });
88+
}
89+
});
7790
}
7891

7992
/**

src/routes/html-to-doc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ export async function htmlToDocHandler(c) {
2828
// Get user email from context
2929
const userEmail = c.get('userEmail');
3030

31-
// Store the document with user association
32-
const result = await storageService.storeDoc(docBuffer, filename, metadata, userEmail);
31+
// Store the document with user association and original HTML content
32+
const result = await storageService.storeDoc(docBuffer, filename, metadata, userEmail, html);
3333

3434
// Add storage information to the response headers
3535
c.header('X-Storage-Path', result.path);

src/routes/html-to-epub.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ export async function htmlToEpubHandler(c) {
3131
// Get user email from context
3232
const userEmail = c.get('userEmail');
3333

34-
// Store the EPUB with user association
35-
const result = await storageService.storeEpub(epubBuffer, filename, metadata, userEmail);
34+
// Store the EPUB with user association and original HTML content
35+
const result = await storageService.storeEpub(epubBuffer, filename, metadata, userEmail, html);
3636

3737
// Add storage information to the response headers
3838
c.header('X-Storage-Path', result.path);

src/routes/html-to-excel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ export async function htmlToExcelHandler(c) {
2929
// Get user email from context
3030
const userEmail = c.get('userEmail');
3131

32-
// Store the Excel file with user association
33-
const result = await storageService.storeExcel(excelBuffer, filename, metadata, userEmail);
32+
// Store the Excel file with user association and original HTML content
33+
const result = await storageService.storeExcel(excelBuffer, filename, metadata, userEmail, html);
3434

3535
// Add storage information to the response headers
3636
c.header('X-Storage-Path', result.path);

src/routes/html-to-pdf.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ export async function htmlToPdfHandler(c) {
3030
// Get user email from context
3131
const userEmail = c.get('userEmail');
3232

33-
// Store the PDF with user association
34-
const result = await storageService.storePdf(pdfBuffer, filename, metadata, userEmail);
33+
// Store the PDF with user association and original HTML content
34+
const result = await storageService.storePdf(pdfBuffer, filename, metadata, userEmail, html);
3535

3636
// Add storage information to the response headers
3737
c.header('X-Storage-Path', result.path);

src/routes/html-to-ppt.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ export async function htmlToPptHandler(c) {
2929
// Get user email from context
3030
const userEmail = c.get('userEmail');
3131

32-
// Store the PowerPoint with user association
33-
const result = await storageService.storePpt(pptBuffer, filename, metadata, userEmail);
32+
// Store the PowerPoint with user association and original HTML content
33+
const result = await storageService.storePpt(pptBuffer, filename, metadata, userEmail, html);
3434

3535
// Add storage information to the response headers
3636
c.header('X-Storage-Path', result.path);

src/services/storage-service.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ export const storageService = {
1010
* @param {string} filename - Filename
1111
* @param {Object} metadata - Additional metadata
1212
* @param {string} userEmail - User email for associating with user_id
13+
* @param {string} sourceHtml - Original HTML content used to generate the PDF
1314
* @returns {Promise<Object>} - Storage result
1415
*/
15-
async storePdf(pdfBuffer, filename = 'document.pdf', metadata = {}, userEmail = null) {
16+
async storePdf(pdfBuffer, filename = 'document.pdf', metadata = {}, userEmail = null, sourceHtml = null) {
1617
const result = await supabaseUtils.storeDocument(
1718
pdfBuffer,
1819
filename,
@@ -21,7 +22,7 @@ export const storageService = {
2122
);
2223

2324
// Record the document generation in the database
24-
await supabaseUtils.recordDocumentGeneration('pdf', result.path, metadata, userEmail);
25+
await supabaseUtils.recordDocumentGeneration('pdf', result.path, metadata, userEmail, sourceHtml);
2526

2627
return result;
2728
},
@@ -32,9 +33,10 @@ export const storageService = {
3233
* @param {string} filename - Filename
3334
* @param {Object} metadata - Additional metadata
3435
* @param {string} userEmail - User email for associating with user_id
36+
* @param {string} sourceHtml - Original HTML content used to generate the document
3537
* @returns {Promise<Object>} - Storage result
3638
*/
37-
async storeDoc(docBuffer, filename = 'document.doc', metadata = {}, userEmail = null) {
39+
async storeDoc(docBuffer, filename = 'document.doc', metadata = {}, userEmail = null, sourceHtml = null) {
3840
const result = await supabaseUtils.storeDocument(
3941
docBuffer,
4042
filename,
@@ -43,7 +45,7 @@ export const storageService = {
4345
);
4446

4547
// Record the document generation in the database
46-
await supabaseUtils.recordDocumentGeneration('doc', result.path, metadata, userEmail);
48+
await supabaseUtils.recordDocumentGeneration('doc', result.path, metadata, userEmail, sourceHtml);
4749

4850
return result;
4951
},
@@ -54,9 +56,10 @@ export const storageService = {
5456
* @param {string} filename - Filename
5557
* @param {Object} metadata - Additional metadata
5658
* @param {string} userEmail - User email for associating with user_id
59+
* @param {string} sourceHtml - Original HTML content used to generate the Excel file
5760
* @returns {Promise<Object>} - Storage result
5861
*/
59-
async storeExcel(excelBuffer, filename = 'document.xlsx', metadata = {}, userEmail = null) {
62+
async storeExcel(excelBuffer, filename = 'document.xlsx', metadata = {}, userEmail = null, sourceHtml = null) {
6063
const result = await supabaseUtils.storeDocument(
6164
excelBuffer,
6265
filename,
@@ -65,7 +68,7 @@ export const storageService = {
6568
);
6669

6770
// Record the document generation in the database
68-
await supabaseUtils.recordDocumentGeneration('excel', result.path, metadata, userEmail);
71+
await supabaseUtils.recordDocumentGeneration('excel', result.path, metadata, userEmail, sourceHtml);
6972

7073
return result;
7174
},
@@ -76,9 +79,10 @@ export const storageService = {
7679
* @param {string} filename - Filename
7780
* @param {Object} metadata - Additional metadata
7881
* @param {string} userEmail - User email for associating with user_id
82+
* @param {string} sourceHtml - Original HTML content used to generate the PowerPoint
7983
* @returns {Promise<Object>} - Storage result
8084
*/
81-
async storePpt(pptBuffer, filename = 'presentation.pptx', metadata = {}, userEmail = null) {
85+
async storePpt(pptBuffer, filename = 'presentation.pptx', metadata = {}, userEmail = null, sourceHtml = null) {
8286
const result = await supabaseUtils.storeDocument(
8387
pptBuffer,
8488
filename,
@@ -87,7 +91,7 @@ export const storageService = {
8791
);
8892

8993
// Record the document generation in the database
90-
await supabaseUtils.recordDocumentGeneration('ppt', result.path, metadata, userEmail);
94+
await supabaseUtils.recordDocumentGeneration('ppt', result.path, metadata, userEmail, sourceHtml);
9195

9296
return result;
9397
},
@@ -98,9 +102,10 @@ export const storageService = {
98102
* @param {string} filename - Filename
99103
* @param {Object} metadata - Additional metadata
100104
* @param {string} userEmail - User email for associating with user_id
105+
* @param {string} sourceHtml - Original HTML content used to generate the EPUB
101106
* @returns {Promise<Object>} - Storage result
102107
*/
103-
async storeEpub(epubBuffer, filename = 'document.epub', metadata = {}, userEmail = null) {
108+
async storeEpub(epubBuffer, filename = 'document.epub', metadata = {}, userEmail = null, sourceHtml = null) {
104109
const result = await supabaseUtils.storeDocument(
105110
epubBuffer,
106111
filename,
@@ -109,7 +114,7 @@ export const storageService = {
109114
);
110115

111116
// Record the document generation in the database
112-
await supabaseUtils.recordDocumentGeneration('epub', result.path, metadata, userEmail);
117+
await supabaseUtils.recordDocumentGeneration('epub', result.path, metadata, userEmail, sourceHtml);
113118

114119
return result;
115120
},

src/utils/supabase.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,10 @@ export const supabaseUtils = {
240240
* @param {string} storagePath - Path in Supabase storage
241241
* @param {Object} metadata - Additional metadata
242242
* @param {string} userEmail - User email for associating with user_id
243+
* @param {string} sourceDoc - Original source document content (HTML, Markdown, etc.)
243244
* @returns {Promise<Object>} - Database record
244245
*/
245-
async recordDocumentGeneration(documentType, storagePath, metadata = {}, userEmail = null) {
246+
async recordDocumentGeneration(documentType, storagePath, metadata = {}, userEmail = null, sourceDoc = null) {
246247
try {
247248
console.log(`Recording document generation for type: ${documentType}, path: ${storagePath}`);
248249

@@ -251,7 +252,8 @@ export const supabaseUtils = {
251252
document_type: documentType,
252253
storage_path: storagePath,
253254
generated_at: new Date().toISOString(),
254-
metadata
255+
metadata,
256+
source_doc: sourceDoc
255257
};
256258

257259
// If no user email is provided, we can't associate the document with a user
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Add source_doc column to document_generations table
2+
-- This column will store the original input content for the conversion,
3+
-- allowing users to edit and regenerate documents
4+
ALTER TABLE document_generations ADD COLUMN source_doc TEXT;
5+
6+
-- Add comment to explain the purpose of the column
7+
COMMENT ON COLUMN document_generations.source_doc IS 'Stores the original input content (HTML, Markdown, etc.) used for the document generation, enabling document editing and regeneration';
8+
9+
-- Create an index on document_type and source_doc for faster lookups when filtering by document type
10+
CREATE INDEX IF NOT EXISTS idx_document_generations_type_source ON document_generations(document_type, (source_doc IS NOT NULL));
11+
12+
-- Update the RLS policies to ensure they still work with the new column
13+
-- (No changes needed as the existing policies are based on user_id)

0 commit comments

Comments
 (0)