Просмотр исходного кода

fix: remove copy button and implement title persistence

- Removed problematic Copy button from content modal UI
- Added title column to shop_content database table with migration
- Updated saveContent method to accept and persist page titles
- Modified all saveContent calls to pass extracted titles
- Fixed modal titles showing 'undefined Content' issue

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fszontagh 8 месяцев назад
Родитель
Сommit
5f79759ac7
4 измененных файлов с 18 добавлено и 25 удалено
  1. BIN
      data/shops.db
  2. 14 4
      src/database/Database.ts
  3. 4 4
      src/scraper/WebshopScraper.ts
  4. 0 17
      web/src/components/pages/ContentPage.ts

+ 14 - 4
src/database/Database.ts

@@ -45,6 +45,7 @@ export interface ShopContent {
   changed: boolean; // true if content changed from previous scrape
   changed: boolean; // true if content changed from previous scrape
   created_at: string;
   created_at: string;
   updated_at: string;
   updated_at: string;
+  title: string | null; // Page title from <title> tag
 }
 }
 
 
 export interface ShopContentWithResults extends ShopContent {
 export interface ShopContentWithResults extends ShopContent {
@@ -175,10 +176,18 @@ export class ShopDatabase {
         changed INTEGER DEFAULT 0,
         changed INTEGER DEFAULT 0,
         created_at TEXT NOT NULL,
         created_at TEXT NOT NULL,
         updated_at TEXT NOT NULL,
         updated_at TEXT NOT NULL,
+        title TEXT,
         FOREIGN KEY (shop_id) REFERENCES shops(id) ON DELETE CASCADE
         FOREIGN KEY (shop_id) REFERENCES shops(id) ON DELETE CASCADE
       )
       )
     `);
     `);
 
 
+    // Add title column to existing databases (migration)
+    try {
+      this.db.exec(`ALTER TABLE shop_content ADD COLUMN title TEXT`);
+    } catch (error) {
+      // Column might already exist, ignore error
+    }
+
     // Create index on shop_content for faster lookups
     // Create index on shop_content for faster lookups
     this.db.exec(`
     this.db.exec(`
       CREATE INDEX IF NOT EXISTS idx_shop_content_shop_type
       CREATE INDEX IF NOT EXISTS idx_shop_content_shop_type
@@ -449,7 +458,8 @@ export class ShopDatabase {
     shopId: string,
     shopId: string,
     contentType: 'shipping' | 'contacts' | 'terms' | 'faq',
     contentType: 'shipping' | 'contacts' | 'terms' | 'faq',
     url: string,
     url: string,
-    content: string
+    content: string,
+    title?: string
   ): { changed: boolean; contentId: string } {
   ): { changed: boolean; contentId: string } {
     const crypto = require('crypto');
     const crypto = require('crypto');
     const contentHash = crypto.createHash('md5').update(content).digest('hex');
     const contentHash = crypto.createHash('md5').update(content).digest('hex');
@@ -468,9 +478,9 @@ export class ShopDatabase {
 
 
     // Insert new content record
     // Insert new content record
     this.db.prepare(`
     this.db.prepare(`
-      INSERT INTO shop_content (id, shop_id, content_type, url, content, content_hash, changed, created_at, updated_at)
-      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-    `).run(id, shopId, contentType, url, content, contentHash, changed ? 1 : 0, now, now);
+      INSERT INTO shop_content (id, shop_id, content_type, url, content, content_hash, changed, created_at, updated_at, title)
+      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+    `).run(id, shopId, contentType, url, content, contentHash, changed ? 1 : 0, now, now, title || null);
 
 
     if (changed) {
     if (changed) {
       logger.info(`Content changed detected for ${contentType} in shop ${shopId}`);
       logger.info(`Content changed detected for ${contentType} in shop ${shopId}`);

+ 4 - 4
src/scraper/WebshopScraper.ts

@@ -106,7 +106,7 @@ export class WebshopScraper {
       if (this.db && shopId) {
       if (this.db && shopId) {
         // Save all shipping pages
         // Save all shipping pages
         for (const content of shippingContent) {
         for (const content of shippingContent) {
-          const result = this.db.saveContent(shopId, 'shipping', content.url, content.content);
+          const result = this.db.saveContent(shopId, 'shipping', content.url, content.content, content.title);
 
 
           // Trigger webhook if content changed
           // Trigger webhook if content changed
           if (result.changed && this.webhookManager) {
           if (result.changed && this.webhookManager) {
@@ -125,7 +125,7 @@ export class WebshopScraper {
         }
         }
         // Save all contact pages
         // Save all contact pages
         for (const content of contactsContent) {
         for (const content of contactsContent) {
-          const result = this.db.saveContent(shopId, 'contacts', content.url, content.content);
+          const result = this.db.saveContent(shopId, 'contacts', content.url, content.content, content.title);
 
 
           // Trigger webhook if content changed
           // Trigger webhook if content changed
           if (result.changed && this.webhookManager) {
           if (result.changed && this.webhookManager) {
@@ -144,7 +144,7 @@ export class WebshopScraper {
         }
         }
         // Save all terms pages
         // Save all terms pages
         for (const content of termsContent) {
         for (const content of termsContent) {
-          const result = this.db.saveContent(shopId, 'terms', content.url, content.content);
+          const result = this.db.saveContent(shopId, 'terms', content.url, content.content, content.title);
 
 
           // Trigger webhook if content changed
           // Trigger webhook if content changed
           if (result.changed && this.webhookManager) {
           if (result.changed && this.webhookManager) {
@@ -163,7 +163,7 @@ export class WebshopScraper {
         }
         }
         // Save all FAQ pages
         // Save all FAQ pages
         for (const content of faqContent) {
         for (const content of faqContent) {
-          const result = this.db.saveContent(shopId, 'faq', content.url, content.content);
+          const result = this.db.saveContent(shopId, 'faq', content.url, content.content, content.title);
 
 
           // Trigger webhook if content changed
           // Trigger webhook if content changed
           if (result.changed && this.webhookManager) {
           if (result.changed && this.webhookManager) {

+ 0 - 17
web/src/components/pages/ContentPage.ts

@@ -175,10 +175,6 @@ export class ContentPage {
                           Formatted
                           Formatted
                         </button>
                         </button>
                       </div>
                       </div>
-                      <button type="button" class="btn btn-secondary btn-sm" id="copy-content-btn">
-                        <div class="w-4 h-4 mr-1">${getIcon('copy')}</div>
-                        Copy
-                      </button>
                       <button type="button" class="btn btn-secondary btn-sm" id="open-url-btn">
                       <button type="button" class="btn btn-secondary btn-sm" id="open-url-btn">
                         <div class="w-4 h-4 mr-1">${getIcon('external-link')}</div>
                         <div class="w-4 h-4 mr-1">${getIcon('external-link')}</div>
                         Open URL
                         Open URL
@@ -243,7 +239,6 @@ export class ContentPage {
     const modal = this.element.querySelector('#content-modal');
     const modal = this.element.querySelector('#content-modal');
     const modalOverlay = this.element.querySelector('#modal-overlay');
     const modalOverlay = this.element.querySelector('#modal-overlay');
     const closeModalBtn = this.element.querySelector('#close-modal');
     const closeModalBtn = this.element.querySelector('#close-modal');
-    const copyContentBtn = this.element.querySelector('#copy-content-btn');
     const openUrlBtn = this.element.querySelector('#open-url-btn');
     const openUrlBtn = this.element.querySelector('#open-url-btn');
 
 
     const closeModal = () => {
     const closeModal = () => {
@@ -253,18 +248,6 @@ export class ContentPage {
     closeModalBtn?.addEventListener('click', closeModal);
     closeModalBtn?.addEventListener('click', closeModal);
     modalOverlay?.addEventListener('click', closeModal);
     modalOverlay?.addEventListener('click', closeModal);
 
 
-    copyContentBtn?.addEventListener('click', async () => {
-      if (this.currentModalItem) {
-        try {
-          const content = this.currentModalItem.content || '';
-          await navigator.clipboard.writeText(content);
-          this.toastService.success('Copied!', 'Content copied to clipboard');
-        } catch (error) {
-          this.toastService.error('Copy Failed', 'Could not copy to clipboard');
-        }
-      }
-    });
-
     openUrlBtn?.addEventListener('click', () => {
     openUrlBtn?.addEventListener('click', () => {
       if (this.currentModalItem) {
       if (this.currentModalItem) {
         window.open(this.currentModalItem.url, '_blank');
         window.open(this.currentModalItem.url, '_blank');