From 28b7b1802c917875facf016769e7a3757618bc55 Mon Sep 17 00:00:00 2001 From: tavo Date: Sat, 14 Sep 2024 09:27:01 -0600 Subject: [PATCH] ui title and craft client request body --- public/client.js | 158 +++++++++++++++++++++++++++--- public/index.html | 22 +++-- public/paypal.js | 11 ++- public/static/css/style.css | 71 +++++++++++++- public/static/js/config.editor.js | 7 +- server/db.go | 4 + server/main.go | 28 ++++++ 7 files changed, 270 insertions(+), 31 deletions(-) diff --git a/public/client.js b/public/client.js index abe9c46..a2a01c6 100644 --- a/public/client.js +++ b/public/client.js @@ -1,20 +1,148 @@ document.addEventListener("DOMContentLoaded", function() { - const dialog = document.getElementById("dialog"); - const overlay = document.getElementById("overlay"); - const menu = document.getElementById("floatingButtons"); + const savedData = localStorage.getItem('editor_data'); + if (savedData) { + const parsedData = JSON.parse(savedData); + console.log('Loaded parsedData:', parsedData); + document.getElementById('title').value = parsedData.title || ''; + document.getElementById('slogan').value = parsedData.slogan || ''; + document.getElementById('banner').src = parsedData.banner || '/static/svg/banner.svg'; + } - function openDialog() { - dialog.style.display = "block"; - overlay.style.display = "block"; - menu.style.display = "none"; - } + const dialog = document.getElementById("dialog"); + const overlay = document.getElementById("overlay"); + const menu = document.getElementById("floatingButtons"); - function closeDialog() { - dialog.style.display = "none"; - overlay.style.display = "none"; - menu.style.display = "block"; - } + function openDialog() { + dialog.style.display = "block"; + overlay.style.display = "block"; + menu.style.display = "none"; + } - document.getElementById("openDialogButton").addEventListener("click", openDialog); - document.getElementById("cancelDialogButton").addEventListener("click", closeDialog); + function closeDialog() { + dialog.style.display = "none"; + overlay.style.display = "none"; + menu.style.display = "block"; + } + + document.getElementById("openDialogButton").addEventListener("click", openDialog); + document.getElementById("cancelDialogButton").addEventListener("click", closeDialog); + document.getElementById('title').addEventListener('change', saveEditorData); + document.getElementById('slogan').addEventListener('change', saveEditorData); +}); + +function saveEditorData() { + const banner = document.getElementById('banner').src; + const title = document.getElementById('title').value; + const slogan = document.getElementById('slogan').value; + + editor.save().then((editor_data) => { + const dataToSave = { + banner: banner, + title: title, + slogan: slogan, + editor_data: editor_data + }; + localStorage.setItem('editor_data', JSON.stringify(dataToSave)); + console.log('Editor data saved to localStorage'); + }).catch((error) => { + console.error('Saving failed:', error); + }); +} + +const directoryInput = document.getElementById('title'); +const statusPopup = document.getElementById('status-popup'); +const statusMessage = document.getElementById('status-message'); + +let typingTimeout; +let hideTimeout; + +directoryInput.addEventListener('input', () => { + clearTimeout(typingTimeout); + typingTimeout = setTimeout(() => { + const directoryName = directoryInput.value.trim(); + if (directoryName.length > 0) { + const sanitizedDirectoryName = sanitizeDirectoryName(directoryName); + checkDirectory(sanitizedDirectoryName); + } else { + hidePopup(); + } + }, 500); // Debounce +}); + +function sanitizeDirectoryName(name) { + return name + .toLowerCase() + .replace(/\s+/g, '-') + .replace(/[^a-z0-9\-]/g, ''); +} + +function checkDirectory(name) { + if (name.length < 4) { + return; + } + fetch(`/api/directory/${encodeURIComponent(name)}`) + .then(response => response.json()) + .then(data => { + if (data.exists) { + showPopup(`El sitio web conex.one/${name} ya existe`, 'exists'); + } else { + showPopup(`Se publicará en conex.one/${name}`, 'available'); + } + }) + .catch(error => { + console.error('Error checking directory:', error); + showPopup('Error checking directory.', 'exists'); + }); +} + +function showPopup(message, status) { + const popup = document.querySelector('.status-popup'); + + if (hideTimeout) { + clearTimeout(hideTimeout); + } + + const existingCloseButton = popup.querySelector('.close-popup'); + if (existingCloseButton) { + existingCloseButton.remove(); + } + + const closeButton = document.createElement('span'); + closeButton.classList.add('close-popup'); + closeButton.innerHTML = '×'; + closeButton.addEventListener('click', () => { + hidePopup(popup, status); + }); + + popup.innerHTML = message; + popup.appendChild(closeButton); + popup.classList.remove('exists', 'available'); + popup.classList.add(status); + popup.classList.add('show'); + + hideTimeout = setTimeout(() => { + hidePopup(popup, status); + }, 5000); +} + +function hidePopup(popup, status) { + popup.classList.remove('show'); + setTimeout(() => { + popup.classList.remove(status); + }, 100); +} + +document.getElementById('imageUpload').addEventListener('change', function (event) { + const file = event.target.files[0]; + const reader = new FileReader(); + + reader.onload = function (e) { + const base64Image = e.target.result; + document.getElementById('banner').src = base64Image; + saveEditorData(); + }; + + if (file) { + reader.readAsDataURL(file); + } }); diff --git a/public/index.html b/public/index.html index d1c9566..21a3d36 100644 --- a/public/index.html +++ b/public/index.html @@ -10,19 +10,20 @@ - - - - - - - @@ -60,6 +61,7 @@ + diff --git a/public/paypal.js b/public/paypal.js index dd0c452..3f66262 100644 --- a/public/paypal.js +++ b/public/paypal.js @@ -6,9 +6,13 @@ paypal.Buttons({ label: "pay" }, async createOrder() { + const savedData = JSON.parse(localStorage.getItem('editor_data')) || {}; const requestData = { - directory: "gofitness", - editor_data: await editor.save() + directory: sanitizeDirectoryName(savedData.title), + banner: savedData.banner || '/static/svg/banner.svg', + title: savedData.title, + slogan: savedData.slogan, + editor_data: savedData.editor_data }; const response = await fetch("/api/orders", { method: "POST", @@ -20,7 +24,7 @@ paypal.Buttons({ if (!response.ok) { if (response.status === 409) { - resultMessage(`No se puede comprar este sitio, ya existe. Prueba con un nombre diferente`); + resultMessage(`No se puede comprar este sitio, ya existe o tiene un nombre incorrecto. Prueba con un nombre diferente`); } else { resultMessage(`No se puede realizar la compra en este momento`); } @@ -39,6 +43,7 @@ paypal.Buttons({ }, async onApprove(data, actions) { try { + // @@@ TODO por alguna razon hizo la compra a pesar de que esto estaba mal puesto const requestData = { directory: "gofitness", editor_data: await editor.save() diff --git a/public/static/css/style.css b/public/static/css/style.css index a3a65bd..f862680 100644 --- a/public/static/css/style.css +++ b/public/static/css/style.css @@ -296,7 +296,7 @@ button { } .floating-button:hover { - background-color: #0056b3; + background-color: #0056b3; } #updateSiteButton { @@ -313,3 +313,72 @@ button { background: linear-gradient(135deg, #21532a, #4fc764); box-shadow: #27d100 0 10px 20px -15px; } + +.status-popup { + position: fixed; + top: 19%; + left: 50%; + transform: translate(-50%, -50%); + padding: 15px; + border-radius: 5px; + background-color: #f0f0f0; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + font-size: 16px; + text-align: left; + opacity: 0; + visibility: hidden; + transition: opacity 0.1s ease, visibility 0.1s ease; +} + +.status-popup.show { + opacity: 1; + visibility: visible; +} + +.status-popup.exists { + background-color: #f8d7da; + color: #721c24; +} + +.status-popup.available { + background-color: #d4edda; + color: #155724; +} + +.close-popup { + position: absolute; + top: -4px; + right: 5px; + cursor: pointer; + font-weight: bold; +} + +#imageUpload { + display: none; +} + +.upload-button { + position: fixed; + top: 2%; + left: 2%; + display: inline-block; + width: 2em; + height: 2em; + border-radius: 10px; + border: 1px solid var(--hover-border); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; + overflow: hidden; +} + +.upload-button:hover { + background-color: #ffffff40; /* Hover effect */ +} + +.upload-button .icon { + width: 1em; + height: 1em; +} diff --git a/public/static/js/config.editor.js b/public/static/js/config.editor.js index 0703ab2..41c44d4 100644 --- a/public/static/js/config.editor.js +++ b/public/static/js/config.editor.js @@ -1,3 +1,6 @@ +const savedData = localStorage.getItem('editor_data'); +const parsedData = savedData ? JSON.parse(savedData) : null; + const editor = new EditorJS({ // readOnly: false, holder: 'editorjs', @@ -73,7 +76,7 @@ const editor = new EditorJS({ }, }, - data: { + data: parsedData ? parsedData.editor_data : { blocks: [ { type: "header", @@ -188,7 +191,7 @@ const editor = new EditorJS({ } }, onChange: function(api, event) { - console.log('something changed', event); + saveEditorData(); } }); diff --git a/server/db.go b/server/db.go index c13ef7a..aff85ed 100644 --- a/server/db.go +++ b/server/db.go @@ -19,6 +19,10 @@ const ( ) func AvailableSite(folder string) error { + if len(folder) <= 3 { + return fmt.Errorf("folder name must be longer than 3 characters") + } + var exists bool if err := db.QueryRow(` SELECT EXISTS(SELECT * FROM sites WHERE folder = $1) diff --git a/server/main.go b/server/main.go index 57f0a0f..cfadd69 100644 --- a/server/main.go +++ b/server/main.go @@ -34,6 +34,7 @@ func main() { http.HandleFunc("/api/orders/", CaptureOrderHandler) http.HandleFunc("/api/update", UpdateSiteHandler) http.HandleFunc("/api/confirm", ConfirmChangesHandler) + http.HandleFunc("/api/directory/", VerifyDirectoryHandler) http.Handle("/", http.FileServer(http.Dir("./public"))) stop := make(chan os.Signal, 1) @@ -192,3 +193,30 @@ func ConfirmChangesHandler(w http.ResponseWriter, r *http.Request) { return } + +func VerifyDirectoryHandler(w http.ResponseWriter, r *http.Request) { + errClientNotice := "Error verifying directory against db" + + path := strings.TrimPrefix(r.URL.Path, "/api/directory/") + parts := strings.Split(path, "/") + folder := parts[0] + if folder == "" { + httpErrorAndLog(w, nil, "Error getting directory", errClientNotice) + return + } + + var response struct { + Exists bool `json:"exists"` + } + + err := AvailableSite(folder) + if err != nil { + response.Exists = true + } else { + response.Exists = false + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return +}