feat: Complete HTML-first architecture implementation with API integration
- Replace value field with html_content for direct HTML storage - Add original_template field for style detection preservation - Remove all markdown processing from injector (delete markdown.go) - Fix critical content extraction/injection bugs in engine - Add missing UpdateContent PUT handler for content persistence - Fix API client field names and add updateContent() method - Resolve content type validation (only allow text/link types) - Add UUID-based ID generation to prevent collisions - Complete first-pass processing workflow for unprocessed elements - Verify end-to-end: Enhancement → Database → API → Editor → Persistence All 37 files updated for HTML-first content management system. Phase 3a implementation complete and production ready.
This commit is contained in:
@@ -2,6 +2,7 @@ package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/insertr/insertr/internal/db"
|
||||
@@ -9,6 +10,14 @@ import (
|
||||
"github.com/insertr/insertr/internal/db/sqlite"
|
||||
)
|
||||
|
||||
// Helper function to convert sql.NullString to string
|
||||
func getStringFromNullString(ns sql.NullString) string {
|
||||
if ns.Valid {
|
||||
return ns.String
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DatabaseClient implements ContentClient interface using the database
|
||||
type DatabaseClient struct {
|
||||
database *db.Database
|
||||
@@ -33,11 +42,12 @@ func (c *DatabaseClient) GetContent(siteID, contentID string) (*ContentItem, err
|
||||
return nil, err
|
||||
}
|
||||
return &ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
Value: content.Value,
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}, nil
|
||||
|
||||
case "postgresql":
|
||||
@@ -49,11 +59,12 @@ func (c *DatabaseClient) GetContent(siteID, contentID string) (*ContentItem, err
|
||||
return nil, err
|
||||
}
|
||||
return &ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
Value: content.Value,
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}, nil
|
||||
|
||||
default:
|
||||
@@ -76,11 +87,12 @@ func (c *DatabaseClient) GetBulkContent(siteID string, contentIDs []string) (map
|
||||
items := make(map[string]ContentItem)
|
||||
for _, content := range contents {
|
||||
items[content.ID] = ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
Value: content.Value,
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}
|
||||
}
|
||||
return items, nil
|
||||
@@ -97,11 +109,12 @@ func (c *DatabaseClient) GetBulkContent(siteID string, contentIDs []string) (map
|
||||
items := make(map[string]ContentItem)
|
||||
for _, content := range contents {
|
||||
items[content.ID] = ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
Value: content.Value,
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}
|
||||
}
|
||||
return items, nil
|
||||
@@ -123,11 +136,12 @@ func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, e
|
||||
items := make(map[string]ContentItem)
|
||||
for _, content := range contents {
|
||||
items[content.ID] = ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
Value: content.Value,
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}
|
||||
}
|
||||
return items, nil
|
||||
@@ -141,11 +155,12 @@ func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, e
|
||||
items := make(map[string]ContentItem)
|
||||
for _, content := range contents {
|
||||
items[content.ID] = ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
Value: content.Value,
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}
|
||||
}
|
||||
return items, nil
|
||||
@@ -154,3 +169,61 @@ func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, e
|
||||
return nil, fmt.Errorf("unsupported database type: %s", c.database.GetDBType())
|
||||
}
|
||||
}
|
||||
|
||||
// CreateContent creates a new content item
|
||||
func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, contentType, lastEditedBy string) (*ContentItem, error) {
|
||||
switch c.database.GetDBType() {
|
||||
case "sqlite3":
|
||||
content, err := c.database.GetSQLiteQueries().CreateContent(context.Background(), sqlite.CreateContentParams{
|
||||
ID: contentID,
|
||||
SiteID: siteID,
|
||||
HtmlContent: htmlContent,
|
||||
OriginalTemplate: toNullString(originalTemplate),
|
||||
Type: contentType,
|
||||
LastEditedBy: lastEditedBy,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}, nil
|
||||
|
||||
case "postgresql":
|
||||
content, err := c.database.GetPostgreSQLQueries().CreateContent(context.Background(), postgresql.CreateContentParams{
|
||||
ID: contentID,
|
||||
SiteID: siteID,
|
||||
HtmlContent: htmlContent,
|
||||
OriginalTemplate: toNullString(originalTemplate),
|
||||
Type: contentType,
|
||||
LastEditedBy: lastEditedBy,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ContentItem{
|
||||
ID: content.ID,
|
||||
SiteID: content.SiteID,
|
||||
HTMLContent: content.HtmlContent,
|
||||
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
|
||||
Type: content.Type,
|
||||
LastEditedBy: content.LastEditedBy,
|
||||
}, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported database type: %s", c.database.GetDBType())
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to convert string to sql.NullString
|
||||
func toNullString(s string) sql.NullString {
|
||||
if s == "" {
|
||||
return sql.NullString{Valid: false}
|
||||
}
|
||||
return sql.NullString{String: s, Valid: true}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user