add html and server interpreters
these are basic and lack most features. the server seems to work the best. the html on the other hand is really rough and doesn't seem to work yet. but it does build the pages and they have all the shapes and sections we wanted. More work to come. :)
This commit is contained in:
@ -10,6 +10,7 @@ import (
|
||||
type HTMLInterpreter struct {
|
||||
entities map[string]*lang.Entity
|
||||
pages map[string]*lang.Page
|
||||
server *lang.Server
|
||||
}
|
||||
|
||||
// NewHTMLInterpreter creates a new HTML interpreter
|
||||
@ -40,7 +41,7 @@ func (hi *HTMLInterpreter) escapeHTML(s string) string {
|
||||
|
||||
// GenerateHTML converts a Masonry AST to HTML output
|
||||
func (hi *HTMLInterpreter) GenerateHTML(ast *lang.AST) (map[string]string, error) {
|
||||
// First pass: collect entities and pages
|
||||
// First pass: collect entities, pages, and server config
|
||||
for _, def := range ast.Definitions {
|
||||
if def.Entity != nil {
|
||||
hi.entities[def.Entity.Name] = def.Entity
|
||||
@ -48,6 +49,9 @@ func (hi *HTMLInterpreter) GenerateHTML(ast *lang.AST) (map[string]string, error
|
||||
if def.Page != nil {
|
||||
hi.pages[def.Page.Name] = def.Page
|
||||
}
|
||||
if def.Server != nil {
|
||||
hi.server = def.Server
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: generate HTML for each page
|
||||
@ -135,6 +139,86 @@ func (hi *HTMLInterpreter) generatePageHTML(page *lang.Page) (string, error) {
|
||||
|
||||
// JavaScript for interactivity
|
||||
html.WriteString(" <script>\n")
|
||||
|
||||
// API Base URL configuration
|
||||
apiBaseURL := "http://localhost:8080"
|
||||
if hi.server != nil {
|
||||
host := "localhost"
|
||||
port := 8080
|
||||
for _, setting := range hi.server.Settings {
|
||||
if setting.Host != nil {
|
||||
host = *setting.Host
|
||||
}
|
||||
if setting.Port != nil {
|
||||
port = *setting.Port
|
||||
}
|
||||
}
|
||||
apiBaseURL = fmt.Sprintf("http://%s:%d", host, port)
|
||||
}
|
||||
|
||||
html.WriteString(fmt.Sprintf(" const API_BASE_URL = '%s';\n", apiBaseURL))
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // API helper functions\n")
|
||||
html.WriteString(" async function apiRequest(method, endpoint, data = null) {\n")
|
||||
html.WriteString(" const config = {\n")
|
||||
html.WriteString(" method: method,\n")
|
||||
html.WriteString(" headers: {\n")
|
||||
html.WriteString(" 'Content-Type': 'application/json',\n")
|
||||
html.WriteString(" },\n")
|
||||
html.WriteString(" };\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" if (data) {\n")
|
||||
html.WriteString(" config.body = JSON.stringify(data);\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" try {\n")
|
||||
html.WriteString(" const response = await fetch(API_BASE_URL + endpoint, config);\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" if (!response.ok) {\n")
|
||||
html.WriteString(" throw new Error(`HTTP error! status: ${response.status}`);\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" if (response.status === 204) {\n")
|
||||
html.WriteString(" return null; // No content\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" return await response.json();\n")
|
||||
html.WriteString(" } catch (error) {\n")
|
||||
html.WriteString(" console.error('API request failed:', error);\n")
|
||||
html.WriteString(" alert('Error: ' + error.message);\n")
|
||||
html.WriteString(" throw error;\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Entity-specific API functions\n")
|
||||
|
||||
// Generate API functions for each entity
|
||||
for entityName := range hi.entities {
|
||||
entityLower := strings.ToLower(entityName)
|
||||
entityPlural := entityLower + "s"
|
||||
|
||||
html.WriteString(fmt.Sprintf(" async function list%s() {\n", entityName))
|
||||
html.WriteString(fmt.Sprintf(" return await apiRequest('GET', '/%s');\n", entityPlural))
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(fmt.Sprintf(" async function get%s(id) {\n", entityName))
|
||||
html.WriteString(fmt.Sprintf(" return await apiRequest('GET', '/%s/' + id);\n", entityPlural))
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(fmt.Sprintf(" async function create%s(data) {\n", entityName))
|
||||
html.WriteString(fmt.Sprintf(" return await apiRequest('POST', '/%s', data);\n", entityPlural))
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(fmt.Sprintf(" async function update%s(id, data) {\n", entityName))
|
||||
html.WriteString(fmt.Sprintf(" return await apiRequest('PUT', '/%s/' + id, data);\n", entityPlural))
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(fmt.Sprintf(" async function delete%s(id) {\n", entityName))
|
||||
html.WriteString(fmt.Sprintf(" return await apiRequest('DELETE', '/%s/' + id);\n", entityPlural))
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
}
|
||||
|
||||
html.WriteString(" // Tab functionality\n")
|
||||
html.WriteString(" function showTab(tabName) {\n")
|
||||
html.WriteString(" const tabs = document.querySelectorAll('.tab-content');\n")
|
||||
@ -153,13 +237,110 @@ func (hi *HTMLInterpreter) generatePageHTML(page *lang.Page) (string, error) {
|
||||
html.WriteString(" document.getElementById(modalId).style.display = 'none';\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Form validation and submission\n")
|
||||
html.WriteString(" function submitForm(formId) {\n")
|
||||
html.WriteString(" // Enhanced form submission with API integration\n")
|
||||
html.WriteString(" async function submitForm(formId, entityType = null) {\n")
|
||||
html.WriteString(" const form = document.getElementById(formId);\n")
|
||||
html.WriteString(" const formData = new FormData(form);\n")
|
||||
html.WriteString(" console.log('Form submitted:', Object.fromEntries(formData));\n")
|
||||
html.WriteString(" alert('Form submitted successfully!');\n")
|
||||
html.WriteString(" const data = Object.fromEntries(formData);\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" console.log('Form data:', data);\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" if (entityType) {\n")
|
||||
html.WriteString(" try {\n")
|
||||
html.WriteString(" const result = await window['create' + entityType](data);\n")
|
||||
html.WriteString(" console.log('Created:', result);\n")
|
||||
html.WriteString(" alert(entityType + ' created successfully!');\n")
|
||||
html.WriteString(" form.reset();\n")
|
||||
html.WriteString(" // Refresh any tables showing this entity type\n")
|
||||
html.WriteString(" await refreshTables(entityType);\n")
|
||||
html.WriteString(" } catch (error) {\n")
|
||||
html.WriteString(" console.error('Form submission failed:', error);\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" } else {\n")
|
||||
html.WriteString(" alert('Form submitted successfully!');\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Load data into tables\n")
|
||||
html.WriteString(" async function loadTableData(tableId, entityType) {\n")
|
||||
html.WriteString(" try {\n")
|
||||
html.WriteString(" const data = await window['list' + entityType]();\n")
|
||||
html.WriteString(" const table = document.getElementById(tableId);\n")
|
||||
html.WriteString(" const tbody = table.querySelector('tbody');\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" if (!data || data.length === 0) {\n")
|
||||
html.WriteString(" tbody.innerHTML = '<tr><td colspan=\"100%\">No data found</td></tr>';\n")
|
||||
html.WriteString(" return;\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" tbody.innerHTML = '';\n")
|
||||
html.WriteString(" data.forEach(item => {\n")
|
||||
html.WriteString(" const row = document.createElement('tr');\n")
|
||||
html.WriteString(" const headers = table.querySelectorAll('thead th');\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" headers.forEach((header, index) => {\n")
|
||||
html.WriteString(" const cell = document.createElement('td');\n")
|
||||
html.WriteString(" const fieldName = header.textContent.toLowerCase().replace(/\\s+/g, '_');\n")
|
||||
html.WriteString(" cell.textContent = item[fieldName] || item[header.textContent.toLowerCase()] || '';\n")
|
||||
html.WriteString(" row.appendChild(cell);\n")
|
||||
html.WriteString(" });\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Add action buttons\n")
|
||||
html.WriteString(" const actionCell = document.createElement('td');\n")
|
||||
html.WriteString(" actionCell.innerHTML = `\n")
|
||||
html.WriteString(" <button onclick=\"editItem('${item.id}', '${entityType}')\" class=\"button button-primary\">Edit</button>\n")
|
||||
html.WriteString(" <button onclick=\"deleteItem('${item.id}', '${entityType}')\" class=\"button button-secondary\">Delete</button>\n")
|
||||
html.WriteString(" `;\n")
|
||||
html.WriteString(" row.appendChild(actionCell);\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" tbody.appendChild(row);\n")
|
||||
html.WriteString(" });\n")
|
||||
html.WriteString(" } catch (error) {\n")
|
||||
html.WriteString(" console.error('Failed to load table data:', error);\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Refresh all tables of a specific entity type\n")
|
||||
html.WriteString(" async function refreshTables(entityType) {\n")
|
||||
html.WriteString(" const tables = document.querySelectorAll(`table[data-entity=\"${entityType}\"]`);\n")
|
||||
html.WriteString(" tables.forEach(table => {\n")
|
||||
html.WriteString(" loadTableData(table.id, entityType);\n")
|
||||
html.WriteString(" });\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Edit and delete functions\n")
|
||||
html.WriteString(" async function editItem(id, entityType) {\n")
|
||||
html.WriteString(" try {\n")
|
||||
html.WriteString(" const item = await window['get' + entityType](id);\n")
|
||||
html.WriteString(" console.log('Edit item:', item);\n")
|
||||
html.WriteString(" // TODO: Populate form with item data for editing\n")
|
||||
html.WriteString(" alert('Edit functionality coming soon!');\n")
|
||||
html.WriteString(" } catch (error) {\n")
|
||||
html.WriteString(" console.error('Failed to fetch item for editing:', error);\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" async function deleteItem(id, entityType) {\n")
|
||||
html.WriteString(" if (confirm('Are you sure you want to delete this item?')) {\n")
|
||||
html.WriteString(" try {\n")
|
||||
html.WriteString(" await window['delete' + entityType](id);\n")
|
||||
html.WriteString(" alert('Item deleted successfully!');\n")
|
||||
html.WriteString(" await refreshTables(entityType);\n")
|
||||
html.WriteString(" } catch (error) {\n")
|
||||
html.WriteString(" console.error('Failed to delete item:', error);\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" }\n")
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // Initialize page - load data when page loads\n")
|
||||
html.WriteString(" document.addEventListener('DOMContentLoaded', function() {\n")
|
||||
html.WriteString(" // Auto-load data for all tables with data-entity attribute\n")
|
||||
html.WriteString(" const tables = document.querySelectorAll('table[data-entity]');\n")
|
||||
html.WriteString(" tables.forEach(table => {\n")
|
||||
html.WriteString(" const entityType = table.getAttribute('data-entity');\n")
|
||||
html.WriteString(" loadTableData(table.id, entityType);\n")
|
||||
html.WriteString(" });\n")
|
||||
html.WriteString(" });\n")
|
||||
html.WriteString(" </script>\n")
|
||||
|
||||
html.WriteString("</body>\n</html>")
|
||||
|
Reference in New Issue
Block a user