feat: implement unified editor with content persistence and server-side upsert
- Replace dual update systems with single markdown-first editor architecture - Add server-side upsert to eliminate 404 errors on PUT operations - Fix content persistence race condition between preview and save operations - Remove legacy updateElementContent system entirely - Add comprehensive authentication with JWT scaffolding and dev mode - Implement EditContext.updateOriginalContent() for proper baseline management - Enable markdown formatting in all text elements (h1-h6, p, div, etc) - Clean terminology: remove 'unified' references from codebase Technical changes: * core/editor.js: Remove legacy update system, unify content types as markdown * ui/Editor.js: Add updateOriginalContent() method to fix save persistence * ui/Previewer.js: Clean live preview system for all content types * api/handlers.go: Implement UpsertContent for idempotent PUT operations * auth/*: Complete authentication service with OAuth scaffolding * db/queries/content.sql: Add upsert query with ON CONFLICT handling * Schema: Remove type constraints, rely on server-side validation Result: Clean content editing with persistent saves, no 404 errors, markdown support in all text elements
This commit is contained in:
@@ -212,3 +212,42 @@ func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (C
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertContent = `-- name: UpsertContent :one
|
||||
INSERT INTO content (id, site_id, value, type, last_edited_by)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5)
|
||||
ON CONFLICT(id, site_id) DO UPDATE SET
|
||||
value = EXCLUDED.value,
|
||||
type = EXCLUDED.type,
|
||||
last_edited_by = EXCLUDED.last_edited_by
|
||||
RETURNING id, site_id, value, type, created_at, updated_at, last_edited_by
|
||||
`
|
||||
|
||||
type UpsertContentParams struct {
|
||||
ID string `json:"id"`
|
||||
SiteID string `json:"site_id"`
|
||||
Value string `json:"value"`
|
||||
Type string `json:"type"`
|
||||
LastEditedBy string `json:"last_edited_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertContent(ctx context.Context, arg UpsertContentParams) (Content, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertContent,
|
||||
arg.ID,
|
||||
arg.SiteID,
|
||||
arg.Value,
|
||||
arg.Type,
|
||||
arg.LastEditedBy,
|
||||
)
|
||||
var i Content
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SiteID,
|
||||
&i.Value,
|
||||
&i.Type,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LastEditedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ type Querier interface {
|
||||
InitializeSchema(ctx context.Context) error
|
||||
InitializeVersionsTable(ctx context.Context) error
|
||||
UpdateContent(ctx context.Context, arg UpdateContentParams) (Content, error)
|
||||
UpsertContent(ctx context.Context, arg UpsertContentParams) (Content, error)
|
||||
}
|
||||
|
||||
var _ Querier = (*Queries)(nil)
|
||||
|
||||
Reference in New Issue
Block a user