mirror of
https://github.com/tavo-wasd-gh/conex-builder.git
synced 2025-07-13 10:33:30 -06:00
ui title and craft client request body
This commit is contained in:
parent
ec5a3be6fb
commit
28b7b1802c
7 changed files with 270 additions and 31 deletions
158
public/client.js
158
public/client.js
|
@ -1,20 +1,148 @@
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const dialog = document.getElementById("dialog");
|
const savedData = localStorage.getItem('editor_data');
|
||||||
const overlay = document.getElementById("overlay");
|
if (savedData) {
|
||||||
const menu = document.getElementById("floatingButtons");
|
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() {
|
const dialog = document.getElementById("dialog");
|
||||||
dialog.style.display = "block";
|
const overlay = document.getElementById("overlay");
|
||||||
overlay.style.display = "block";
|
const menu = document.getElementById("floatingButtons");
|
||||||
menu.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeDialog() {
|
function openDialog() {
|
||||||
dialog.style.display = "none";
|
dialog.style.display = "block";
|
||||||
overlay.style.display = "none";
|
overlay.style.display = "block";
|
||||||
menu.style.display = "block";
|
menu.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("openDialogButton").addEventListener("click", openDialog);
|
function closeDialog() {
|
||||||
document.getElementById("cancelDialogButton").addEventListener("click", 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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,19 +10,20 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
<link rel="stylesheet" href="/static/css/editorjs-dark.css">
|
<link rel="stylesheet" href="/static/css/editorjs-dark.css">
|
||||||
<script src="/client.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<!-- <div class="banner" style="background-image: url(/static/svg/banner.svg);"> -->
|
|
||||||
<!-- <div class="desc"> -->
|
|
||||||
<!-- <input type="text" name="title" class="input-title" placeholder="[Nombre Ejemplo]"> -->
|
|
||||||
<!-- <input type="text" name="slogan" class="input-slogan" placeholder="[Slogan llamativo o breve descripción]"> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<div class="banner">
|
<div class="banner">
|
||||||
<img src="/static/svg/banner.svg" class="banner-image"/>
|
<input type="file" id="imageUpload" accept="image/*">
|
||||||
|
<label for="imageUpload" class="upload-button">
|
||||||
|
<img src="/static/svg/edit.svg" alt="Edit Icon" class="icon">
|
||||||
|
</label>
|
||||||
|
<img id="banner" name="banner" src="/static/svg/banner.svg" class="banner-image"/>
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
<input type="text" name="title" class="input-title" placeholder="[Nombre Ejemplo]">
|
<input type="text" id="title" name="title" class="input-title" placeholder="[Nombre Ejemplo]">
|
||||||
<input type="text" name="slogan" class="input-slogan" placeholder="[Slogan llamativo o breve descripción]">
|
<input type="text" id="slogan" name="slogan" class="input-slogan" placeholder="[Slogan llamativo o breve descripción]">
|
||||||
|
</div>
|
||||||
|
<div id="status-popup" class="status-popup">
|
||||||
|
<span class="close-popup" onclick="hidePopup()">×</span>
|
||||||
|
<span id="status-message"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<body>
|
<body>
|
||||||
|
@ -60,6 +61,7 @@
|
||||||
</picture>
|
</picture>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="/client.js"></script>
|
||||||
<script src="https://sandbox.paypal.com/sdk/js?client-id=AcCW43LI1S6lLQgtLkF4V8UOPfmXcqXQ8xfEl41hRuMxSskR2jkWNwQN6Ab1WK7E2E52GNaoYBHqgIKd&components=buttons&enable-funding=card&disable-funding=paylater,venmo"></script>
|
<script src="https://sandbox.paypal.com/sdk/js?client-id=AcCW43LI1S6lLQgtLkF4V8UOPfmXcqXQ8xfEl41hRuMxSskR2jkWNwQN6Ab1WK7E2E52GNaoYBHqgIKd&components=buttons&enable-funding=card&disable-funding=paylater,venmo"></script>
|
||||||
<script src="/paypal.js"></script>
|
<script src="/paypal.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script><!-- Header -->
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script><!-- Header -->
|
||||||
|
|
|
@ -6,9 +6,13 @@ paypal.Buttons({
|
||||||
label: "pay"
|
label: "pay"
|
||||||
},
|
},
|
||||||
async createOrder() {
|
async createOrder() {
|
||||||
|
const savedData = JSON.parse(localStorage.getItem('editor_data')) || {};
|
||||||
const requestData = {
|
const requestData = {
|
||||||
directory: "gofitness",
|
directory: sanitizeDirectoryName(savedData.title),
|
||||||
editor_data: await editor.save()
|
banner: savedData.banner || '/static/svg/banner.svg',
|
||||||
|
title: savedData.title,
|
||||||
|
slogan: savedData.slogan,
|
||||||
|
editor_data: savedData.editor_data
|
||||||
};
|
};
|
||||||
const response = await fetch("/api/orders", {
|
const response = await fetch("/api/orders", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -20,7 +24,7 @@ paypal.Buttons({
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
if (response.status === 409) {
|
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 {
|
} else {
|
||||||
resultMessage(`No se puede realizar la compra en este momento`);
|
resultMessage(`No se puede realizar la compra en este momento`);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +43,7 @@ paypal.Buttons({
|
||||||
},
|
},
|
||||||
async onApprove(data, actions) {
|
async onApprove(data, actions) {
|
||||||
try {
|
try {
|
||||||
|
// @@@ TODO por alguna razon hizo la compra a pesar de que esto estaba mal puesto
|
||||||
const requestData = {
|
const requestData = {
|
||||||
directory: "gofitness",
|
directory: "gofitness",
|
||||||
editor_data: await editor.save()
|
editor_data: await editor.save()
|
||||||
|
|
|
@ -296,7 +296,7 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-button:hover {
|
.floating-button:hover {
|
||||||
background-color: #0056b3;
|
background-color: #0056b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateSiteButton {
|
#updateSiteButton {
|
||||||
|
@ -313,3 +313,72 @@ button {
|
||||||
background: linear-gradient(135deg, #21532a, #4fc764);
|
background: linear-gradient(135deg, #21532a, #4fc764);
|
||||||
box-shadow: #27d100 0 10px 20px -15px;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
const savedData = localStorage.getItem('editor_data');
|
||||||
|
const parsedData = savedData ? JSON.parse(savedData) : null;
|
||||||
|
|
||||||
const editor = new EditorJS({
|
const editor = new EditorJS({
|
||||||
// readOnly: false,
|
// readOnly: false,
|
||||||
holder: 'editorjs',
|
holder: 'editorjs',
|
||||||
|
@ -73,7 +76,7 @@ const editor = new EditorJS({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data: {
|
data: parsedData ? parsedData.editor_data : {
|
||||||
blocks: [
|
blocks: [
|
||||||
{
|
{
|
||||||
type: "header",
|
type: "header",
|
||||||
|
@ -188,7 +191,7 @@ const editor = new EditorJS({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onChange: function(api, event) {
|
onChange: function(api, event) {
|
||||||
console.log('something changed', event);
|
saveEditorData();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func AvailableSite(folder string) error {
|
func AvailableSite(folder string) error {
|
||||||
|
if len(folder) <= 3 {
|
||||||
|
return fmt.Errorf("folder name must be longer than 3 characters")
|
||||||
|
}
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
if err := db.QueryRow(`
|
if err := db.QueryRow(`
|
||||||
SELECT EXISTS(SELECT * FROM sites WHERE folder = $1)
|
SELECT EXISTS(SELECT * FROM sites WHERE folder = $1)
|
||||||
|
|
|
@ -34,6 +34,7 @@ func main() {
|
||||||
http.HandleFunc("/api/orders/", CaptureOrderHandler)
|
http.HandleFunc("/api/orders/", CaptureOrderHandler)
|
||||||
http.HandleFunc("/api/update", UpdateSiteHandler)
|
http.HandleFunc("/api/update", UpdateSiteHandler)
|
||||||
http.HandleFunc("/api/confirm", ConfirmChangesHandler)
|
http.HandleFunc("/api/confirm", ConfirmChangesHandler)
|
||||||
|
http.HandleFunc("/api/directory/", VerifyDirectoryHandler)
|
||||||
http.Handle("/", http.FileServer(http.Dir("./public")))
|
http.Handle("/", http.FileServer(http.Dir("./public")))
|
||||||
|
|
||||||
stop := make(chan os.Signal, 1)
|
stop := make(chan os.Signal, 1)
|
||||||
|
@ -192,3 +193,30 @@ func ConfirmChangesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue