mirror of
https://github.com/tavo-wasd-gh/conex-builder.git
synced 2025-06-07 04:03:29 -06:00
extra field in update handler, frontend refactor
This commit is contained in:
parent
b9d1620646
commit
57c7c15ec5
6 changed files with 312 additions and 62 deletions
237
public/client.js
237
public/client.js
|
@ -21,9 +21,12 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
const checkoutDialog = document.getElementById("checkoutDialog");
|
const checkoutDialog = document.getElementById("checkoutDialog");
|
||||||
const editDialog = document.getElementById("editDialog");
|
const editDialog = document.getElementById("editDialog");
|
||||||
const buyDialog = document.getElementById("buyDialog");
|
const buyDialog = document.getElementById("buyDialog");
|
||||||
|
const updateContentDialog = document.getElementById("updateContentDialog");
|
||||||
|
|
||||||
checkoutDialog.style.display = "none";
|
checkoutDialog.style.display = "none";
|
||||||
editDialog.style.display = "none";
|
editDialog.style.display = "none";
|
||||||
|
buyDialog.style.display = "none";
|
||||||
|
updateContentDialog.style.display = "none";
|
||||||
loadLanguage('es');
|
loadLanguage('es');
|
||||||
|
|
||||||
Promise.all(EditorJSComponents.map(src => loadScript(src))).then(() => {
|
Promise.all(EditorJSComponents.map(src => loadScript(src))).then(() => {
|
||||||
|
@ -58,7 +61,7 @@ function loadEditorState() {
|
||||||
if (savedData) {
|
if (savedData) {
|
||||||
const parsedData = JSON.parse(savedData);
|
const parsedData = JSON.parse(savedData);
|
||||||
console.log('Loaded parsedData:', parsedData);
|
console.log('Loaded parsedData:', parsedData);
|
||||||
document.getElementById('title').value = parsedData.title || '';
|
document.getElementById('title').innerText = parsedData.title || '';
|
||||||
document.getElementById('slogan').value = parsedData.slogan || '';
|
document.getElementById('slogan').value = parsedData.slogan || '';
|
||||||
document.getElementById('banner').src = parsedData.banner || '/static/svg/banner.svg';
|
document.getElementById('banner').src = parsedData.banner || '/static/svg/banner.svg';
|
||||||
const disclaimers = document.querySelectorAll(".localstorage-exists");
|
const disclaimers = document.querySelectorAll(".localstorage-exists");
|
||||||
|
@ -82,7 +85,7 @@ function loadEditorState() {
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error loading translation file:', error));
|
.catch(error => console.error('Error loading translation file:', error));
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('title').value = '';
|
document.getElementById('title').innerText = '';
|
||||||
document.getElementById('slogan').value = '';
|
document.getElementById('slogan').value = '';
|
||||||
document.getElementById('banner').src = '/static/svg/banner.svg';
|
document.getElementById('banner').src = '/static/svg/banner.svg';
|
||||||
document.getElementById("continueEditingModeButton").style.display = "none";
|
document.getElementById("continueEditingModeButton").style.display = "none";
|
||||||
|
@ -104,28 +107,73 @@ function initializeEventListeners() {
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("buyButton").addEventListener("click", () => openDialog(checkoutDialog));
|
document.getElementById("buyButton").addEventListener("click", () => openDialog(checkoutDialog));
|
||||||
|
document.getElementById("editButton").addEventListener("click", () => openDialog(updateContentDialog));
|
||||||
document.getElementById("closeDialogButton").addEventListener("click", () => closeDialog());
|
document.getElementById("closeDialogButton").addEventListener("click", () => closeDialog());
|
||||||
|
|
||||||
// // Editor save
|
// // Editor save
|
||||||
document.getElementById('title').addEventListener('change', saveEditorData);
|
// document.getElementById('title').addEventListener('change', saveEditorData);
|
||||||
document.getElementById('slogan').addEventListener('change', saveEditorData);
|
document.getElementById('slogan').addEventListener('change', saveEditorData);
|
||||||
|
|
||||||
// // Mode switching
|
// // Mode switching
|
||||||
// document.getElementById('buyModeButton').addEventListener('click', openBuyModeDialog);
|
document.getElementById('buyModeButton').addEventListener('click', openBuyModeDialog);
|
||||||
document.getElementById('buyModeButton').addEventListener('click', buyMode);
|
|
||||||
document.getElementById('editModeButton').addEventListener('click', openEditModeDialog);
|
document.getElementById('editModeButton').addEventListener('click', openEditModeDialog);
|
||||||
|
document.getElementById("continueToBuyModeButton").addEventListener('click', async () => {
|
||||||
|
const directory = sanitizeDirectoryTitle(document.getElementById("buyModeDirectoryInput").value);
|
||||||
|
const exists = await checkDirectoryExists(directory);
|
||||||
|
if (exists) {
|
||||||
|
document.getElementById("checkdir-error-message").style.display = "block";
|
||||||
|
document.getElementById("checkdir-error-message").innerHTML = `El sitio https://conex.one/${directory} ya existe.`;
|
||||||
|
} else {
|
||||||
|
document.getElementById("checkdir-error-message").style.display = "none";
|
||||||
|
buyMode(directory);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
document.getElementById("continueToEditModeButton").addEventListener('click', () =>
|
document.getElementById("continueToEditModeButton").addEventListener('click', () =>
|
||||||
editMode(document.getElementById("editModeDirectoryInput").value)
|
editMode(extractSitePath(document.getElementById("editModeDirectoryInput").value))
|
||||||
);
|
);
|
||||||
document.getElementById('continueEditingModeButton').addEventListener('click', continueMode);
|
document.getElementById('continueEditingModeButton').addEventListener('click', continueMode);
|
||||||
|
|
||||||
document.getElementById('dashButton').addEventListener('click', dashboardMode);
|
document.getElementById('dashButton').addEventListener('click', dashboardMode);
|
||||||
document.getElementById('uploadBannerBtn').addEventListener('change', handleImageUpload);
|
document.getElementById('uploadBannerBtn').addEventListener('change', handleImageUpload);
|
||||||
|
|
||||||
const titleElement = document.getElementById('title');
|
document.getElementById('requestChangesButton').addEventListener('click', async () => {
|
||||||
if (titleElement) {
|
const button = document.getElementById('requestChangesButton');
|
||||||
setupDirectoryInput(titleElement);
|
button.disabled = true;
|
||||||
}
|
button.classList.add('disabled');
|
||||||
|
|
||||||
|
await updateSiteRequest();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
button.disabled = false;
|
||||||
|
button.classList.remove('disabled');
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('confirmChangesButton').addEventListener('click', function() {
|
||||||
|
successElement = document.getElementById('update-success-message');
|
||||||
|
errorElement = document.getElementById('update-error-message');
|
||||||
|
|
||||||
|
const codeInput = document.getElementById('updateContentCodeInput').value;
|
||||||
|
if (codeInput.length === 6 && !isNaN(codeInput)) {
|
||||||
|
document.getElementById('updateContentCodeInput').value = '';
|
||||||
|
errorElement.style.display = "none"
|
||||||
|
updateSiteConfirm(codeInput);
|
||||||
|
} else {
|
||||||
|
successElement.style.display = "none"
|
||||||
|
errorElement.style.display = "block"
|
||||||
|
errorElement.innerHTML = "El código es un pin numérico de 6 dígitos.";
|
||||||
|
console.error('Invalid code. Please enter a 6-digit number.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const titleElement = document.getElementById('buyModeDirectoryInput');
|
||||||
|
titleElement.addEventListener('input', debounce(function() {
|
||||||
|
const directory = titleElement.value.trim();
|
||||||
|
if (directory.length > 0) {
|
||||||
|
validateDirectory(directory);
|
||||||
|
}
|
||||||
|
}, 500)); // 500ms debounce
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDialog(content) {
|
function openDialog(content) {
|
||||||
|
@ -135,21 +183,31 @@ function openDialog(content) {
|
||||||
floatingButtons.style.display = "none";
|
floatingButtons.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function debounce(func, delay) {
|
||||||
|
let timeout;
|
||||||
|
return function(...args) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(() => func.apply(this, args), delay);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function closeDialog() {
|
function closeDialog() {
|
||||||
checkoutDialog.style.display = "none";
|
checkoutDialog.style.display = "none";
|
||||||
editDialog.style.display = "none";
|
editDialog.style.display = "none";
|
||||||
// buyDialog.style.display = "none";
|
buyDialog.style.display = "none";
|
||||||
|
updateContentDialog.style.display = "none";
|
||||||
dialog.style.display = "none";
|
dialog.style.display = "none";
|
||||||
overlay.style.display = "none";
|
overlay.style.display = "none";
|
||||||
floatingButtons.style.display = "flex";
|
floatingButtons.style.display = "flex";
|
||||||
document.getElementById('checkout-error-message').style.display = "none";
|
document.getElementById('checkout-error-message').style.display = "none";
|
||||||
|
document.getElementById('update-error-message').style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveEditorData() {
|
function saveEditorData() {
|
||||||
const titleValue = document.getElementById('title').value.trim();
|
const titleValue = document.getElementById('title').innerText.trim();
|
||||||
const dataToSave = {
|
const dataToSave = {
|
||||||
banner: document.getElementById('banner').src || '/static/svg/banner.svg',
|
banner: document.getElementById('banner').src || '/static/svg/banner.svg',
|
||||||
title: document.getElementById('title').value,
|
title: document.getElementById('title').innerText,
|
||||||
slogan: document.getElementById('slogan').value,
|
slogan: document.getElementById('slogan').value,
|
||||||
directory: sanitizeDirectoryTitle(titleValue)
|
directory: sanitizeDirectoryTitle(titleValue)
|
||||||
};
|
};
|
||||||
|
@ -162,21 +220,37 @@ function saveEditorData() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDirectoryInput(inputElement, debounceTime = 500) {
|
function validateDirectory(directory) {
|
||||||
inputElement.addEventListener('input', () => {
|
successMessageElement = document.getElementById('checkdir-success-message');
|
||||||
clearTimeout(typingTimeout);
|
errorMessageElement = document.getElementById('checkdir-error-message');
|
||||||
|
successMessageElement.textContent = '';
|
||||||
|
errorMessageElement.textContent = '';
|
||||||
|
|
||||||
typingTimeout = setTimeout(() => {
|
if (!validateDirectoryLength(directory)) {
|
||||||
const inputValue = inputElement.value.trim();
|
successMessageElement.style.display = "none";
|
||||||
|
errorMessageElement.style.display = "block";
|
||||||
|
errorMessageElement.textContent = 'Directory name must be between 4 and 35 characters.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (inputValue.length > 0) {
|
directory = sanitizeDirectoryTitle(directory)
|
||||||
const sanitizedValue = sanitizeDirectoryTitle(inputValue); // Sanitize the input value
|
checkDirectoryExists(directory)
|
||||||
checkDirectory(sanitizedValue);
|
.then(exists => {
|
||||||
|
if (exists) {
|
||||||
|
successMessageElement.style.display = "none";
|
||||||
|
errorMessageElement.style.display = "block";
|
||||||
|
errorMessageElement.textContent = `El sitio https://conex.one/${directory} ya existe.`;
|
||||||
} else {
|
} else {
|
||||||
hidePopup();
|
successMessageElement.style.display = "block";
|
||||||
|
errorMessageElement.style.display = "none";
|
||||||
|
successMessageElement.textContent = `Se publicará en https://conex.one/${directory}`;
|
||||||
}
|
}
|
||||||
}, debounceTime);
|
})
|
||||||
});
|
.catch(() => {
|
||||||
|
successMessageElement.style.display = "none";
|
||||||
|
errorMessageElement.style.display = "block";
|
||||||
|
errorMessageElement.textContent = 'Error occurred while checking the directory.';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanitizeDirectoryTitle(title) {
|
function sanitizeDirectoryTitle(title) {
|
||||||
|
@ -188,11 +262,6 @@ function sanitizeDirectoryTitle(title) {
|
||||||
.replace(/[^a-z0-9\-]/g, '');
|
.replace(/[^a-z0-9\-]/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDirectory(directory) {
|
|
||||||
if (!validateDirectoryLength(directory)) return;
|
|
||||||
fetchDirectoryStatus(directory, 'exists', 'available', 'El sitio web ya existe', 'Se publicará en');
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateDirectoryLength(directory) {
|
function validateDirectoryLength(directory) {
|
||||||
if (directory.length < 4 || directory.length > 35) {
|
if (directory.length < 4 || directory.length > 35) {
|
||||||
showPopup('El título debe tener entre 4 y 35 caracteres', 'exists');
|
showPopup('El título debe tener entre 4 y 35 caracteres', 'exists');
|
||||||
|
@ -201,14 +270,6 @@ function validateDirectoryLength(directory) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchDirectoryStatus(directory, failureStatus, successStatus, failureMessage, successMessage) {
|
|
||||||
checkDirectoryExists(directory).then(exists => {
|
|
||||||
const message = exists ? `${failureMessage} conex.one/${directory}` : `${successMessage} conex.one/${directory}`;
|
|
||||||
const status = exists ? failureStatus : successStatus;
|
|
||||||
showPopup(message, status);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkDirectoryExists(directory) {
|
function checkDirectoryExists(directory) {
|
||||||
return fetch(`/api/directory/${encodeURIComponent(directory)}`)
|
return fetch(`/api/directory/${encodeURIComponent(directory)}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
|
@ -331,8 +392,14 @@ function dashboardMode() {
|
||||||
|
|
||||||
function buyMode() {
|
function buyMode() {
|
||||||
localStorage.removeItem('conex_data');
|
localStorage.removeItem('conex_data');
|
||||||
|
const dataToSave = {
|
||||||
|
title: document.getElementById('buyModeDirectoryInput').value.trim(),
|
||||||
|
};
|
||||||
|
localStorage.setItem('conex_data', JSON.stringify(dataToSave));
|
||||||
loadEditorState();
|
loadEditorState();
|
||||||
|
|
||||||
|
closeDialog();
|
||||||
|
|
||||||
document.getElementById('checkout-success-message').style.display = "none";
|
document.getElementById('checkout-success-message').style.display = "none";
|
||||||
document.querySelector("#paypal-button-container").style.display = "block";
|
document.querySelector("#paypal-button-container").style.display = "block";
|
||||||
document.getElementById("buyButton").style.display = "block";
|
document.getElementById("buyButton").style.display = "block";
|
||||||
|
@ -380,6 +447,8 @@ function continueBuyMode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function openBuyModeDialog() {
|
function openBuyModeDialog() {
|
||||||
|
document.getElementById("checkdir-error-message").style.display = "none";
|
||||||
|
document.getElementById("checkdir-success-message").style.display = "none";
|
||||||
overlay.style.display = "block";
|
overlay.style.display = "block";
|
||||||
dialog.style.display = "block";
|
dialog.style.display = "block";
|
||||||
buyDialog.style.display = "block";
|
buyDialog.style.display = "block";
|
||||||
|
@ -392,13 +461,23 @@ function openEditModeDialog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function editMode(dir) {
|
async function editMode(dir) {
|
||||||
closeDialog();
|
const errorMessageElement = document.getElementById('edit-error-message');
|
||||||
const success = await fetchAndStoreData(dir);
|
const conexData = JSON.parse(localStorage.getItem('conex_data'));
|
||||||
if (!success) {
|
|
||||||
console.error("Data could not be loaded, aborting UI changes");
|
if (conexData?.directory === dir) {
|
||||||
return;
|
console.log("Directory already loaded, skipping fetch.");
|
||||||
|
} else {
|
||||||
|
const success = await fetchAndStoreData(dir);
|
||||||
|
if (!success) {
|
||||||
|
errorMessageElement.innerHTML = "No se pudo cargar el sitio, asegúrate que estás digitando el enlace correcto.";
|
||||||
|
errorMessageElement.style.display = "block";
|
||||||
|
console.error("Data could not be loaded, aborting UI changes");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeDialog();
|
||||||
|
errorMessageElement.style.display = "none";
|
||||||
document.getElementById("buyButton").style.display = "none";
|
document.getElementById("buyButton").style.display = "none";
|
||||||
document.getElementById("editButton").style.display = "block";
|
document.getElementById("editButton").style.display = "block";
|
||||||
const dashboard = document.getElementById('dashboard');
|
const dashboard = document.getElementById('dashboard');
|
||||||
|
@ -428,3 +507,77 @@ async function fetchAndStoreData(directoryName) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSiteRequest() {
|
||||||
|
const conexData = JSON.parse(localStorage.getItem('conex_data'));
|
||||||
|
const directory = conexData?.directory;
|
||||||
|
successElement = document.getElementById('update-success-message');
|
||||||
|
errorElement = document.getElementById('update-error-message');
|
||||||
|
|
||||||
|
fetch('/api/update', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ directory: directory })
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
successElement.style.display = "block"
|
||||||
|
errorElement.style.display = "none"
|
||||||
|
successElement.innerHTML = "Se envió el código de autenticación de 6 dígitos a su correo electrónico.";
|
||||||
|
} else {
|
||||||
|
successElement.style.display = "none"
|
||||||
|
errorElement.style.display = "block"
|
||||||
|
errorElement.innerHTML = "Error enviando el código de confirmación a su correo, recuerde que puede solicitar el código solamente una vez cada minuto.";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSiteConfirm(code) {
|
||||||
|
const conexData = JSON.parse(localStorage.getItem('conex_data'));
|
||||||
|
const directory = conexData?.directory;
|
||||||
|
const editorData = conexData?.editor_data;
|
||||||
|
const slogan = conexData?.slogan;
|
||||||
|
|
||||||
|
successElement = document.getElementById('update-success-message');
|
||||||
|
errorElement = document.getElementById('update-error-message');
|
||||||
|
|
||||||
|
if (!directory || !editorData) {
|
||||||
|
console.error('Directory or editor_data not found in localStorage');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch('/api/confirm', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
directory: directory,
|
||||||
|
auth_code: code,
|
||||||
|
slogan: slogan,
|
||||||
|
editor_data: editorData
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
successElement.style.display = "block"
|
||||||
|
errorElement.style.display = "none"
|
||||||
|
successElement.innerHTML = "Se actualizó correctamente la información de su sitio, los cambios deberían verse reflejados en menos de 24 horas.";
|
||||||
|
} else {
|
||||||
|
successElement.style.display = "none"
|
||||||
|
errorElement.style.display = "block"
|
||||||
|
errorElement.innerHTML = "Error actualizando su sitio, por favor vuelva a intentarlo más tarde.";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractSitePath(url) {
|
||||||
|
if (!url.includes("conex.one")) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
const cleanUrl = url.replace(/^(https?:\/\/)?(www\.)?/, '').replace(/#.*$/, '');
|
||||||
|
const match = cleanUrl.match(/^conex\.one\/([^\/?#]+)\/?/);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
}
|
||||||
|
|
|
@ -10,10 +10,6 @@
|
||||||
<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">
|
||||||
</head>
|
</head>
|
||||||
<div id="status-popup" class="status-popup">
|
|
||||||
<span class="close-popup" onclick="hidePopup()">×</span>
|
|
||||||
<span id="status-message"></span>
|
|
||||||
</div>
|
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
<div id="dashboard">
|
<div id="dashboard">
|
||||||
<div class="wave"></div>
|
<div class="wave"></div>
|
||||||
|
@ -45,13 +41,21 @@
|
||||||
</div>
|
</div>
|
||||||
<img id="banner" src="/static/svg/banner.svg" class="banner-image"/>
|
<img id="banner" src="/static/svg/banner.svg" class="banner-image"/>
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
<input type="text" id="title" maxlength="35" class="input-title" data-translate="sampleTitle" placeholder="" >
|
<h1 id="title" class="input-title"></h1>
|
||||||
<textarea type="text" id="slogan" maxlength="100" class="input-slogan" data-translate="sampleSlogan" placeholder=""></textarea>
|
<textarea type="text" id="slogan" maxlength="100" class="input-slogan" data-translate="sampleSlogan" placeholder=""></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<body>
|
<body>
|
||||||
<div id="editorjs"></div>
|
<div id="editorjs"></div>
|
||||||
</body>
|
</body>
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="footer-content">
|
||||||
|
<ul class="footer-links">
|
||||||
|
<li><a href="#contact">Contactar con soporte</a></li>
|
||||||
|
</ul>
|
||||||
|
<p data-translate="footer"></p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
<div class="floating-buttons-container" id="floatingButtons">
|
<div class="floating-buttons-container" id="floatingButtons">
|
||||||
<button class="floating-button" id="buyButton">
|
<button class="floating-button" id="buyButton">
|
||||||
<img src="/static/svg/check.svg">
|
<img src="/static/svg/check.svg">
|
||||||
|
@ -86,9 +90,29 @@
|
||||||
<div class="message error-message" id="checkout-error-message"></div>
|
<div class="message error-message" id="checkout-error-message"></div>
|
||||||
<div id="paypal-button-container"></div>
|
<div id="paypal-button-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="buyDialog">
|
||||||
|
<h2 data-translate="buyDialogHeader"></h2>
|
||||||
|
<p data-translate="buyDialogParagraph"></p>
|
||||||
|
<div class="message success-message" id="checkdir-success-message"></div>
|
||||||
|
<div class="message error-message" id="checkdir-error-message"></div>
|
||||||
|
<input class="input-dialog" type="text" id="buyModeDirectoryInput" maxlength="35" placeholder="Mi Sitio"><br>
|
||||||
|
<button id="continueToBuyModeButton" class="right">
|
||||||
|
<span data-translate="continueToBuyModeButton"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="updateContentDialog">
|
||||||
|
<h2 data-translate="updateContentDialogHeader"></h2>
|
||||||
|
<p data-translate="updateContentDialogParagraph"></p>
|
||||||
|
<div class="message success-message" id="update-success-message"></div>
|
||||||
|
<div class="message error-message" id="update-error-message"></div>
|
||||||
|
<input data-translate="tempCodePlaceholder" class="input-dialog" type="number" id="updateContentCodeInput" min="0" max="999999" placeholder=""><br>
|
||||||
|
<button data-translate="requestChangesButton" id="requestChangesButton"></button>
|
||||||
|
<button data-translate="confirmChangesButton" id="confirmChangesButton"></button>
|
||||||
|
</div>
|
||||||
<div id="editDialog">
|
<div id="editDialog">
|
||||||
<h2 data-translate="editDialogHeader"></h2>
|
<h2 data-translate="editDialogHeader"></h2>
|
||||||
<p data-translate="editDialogParagraph"></p>
|
<p data-translate="editDialogParagraph"></p>
|
||||||
|
<div class="message error-message" id="edit-error-message"></div>
|
||||||
<input class="input-dialog" type="text" id="editModeDirectoryInput" name="title" maxlength="35" placeholder="https://conex.one/mi-sitio"><br>
|
<input class="input-dialog" type="text" id="editModeDirectoryInput" name="title" maxlength="35" placeholder="https://conex.one/mi-sitio"><br>
|
||||||
<button id="continueToEditModeButton" class="right">
|
<button id="continueToEditModeButton" class="right">
|
||||||
<span data-translate="continueToEditModeButton"></span>
|
<span data-translate="continueToEditModeButton"></span>
|
||||||
|
|
|
@ -6,6 +6,14 @@
|
||||||
"editModeButton": "Editar sitio existente",
|
"editModeButton": "Editar sitio existente",
|
||||||
"editModeButtonDisclaimer": "Limpiará el progreso actual para cargar un sitio existente",
|
"editModeButtonDisclaimer": "Limpiará el progreso actual para cargar un sitio existente",
|
||||||
"continueEditingModeButton": "Continuar editando",
|
"continueEditingModeButton": "Continuar editando",
|
||||||
|
"buyDialogHeader": "Diseñar un nuevo sitio web",
|
||||||
|
"buyDialogParagraph": "Ingresa el nombre del sitio y revisa el enlace en el que se publicará una vez adquirido.",
|
||||||
|
"updateContentDialogHeader": "Actualizar mi sitio",
|
||||||
|
"updateContentDialogParagraph": "Para actualizar el sitio web, requerimos confirmar que el sitio es suyo. Para esto, enviaremos un correo electrónico a la cuenta de correo con la que compró este sitio web, con un código temporal de 6 dígitos que expirará en 5 minutos luego de ser enviado. Por favor, presione el botón para enviar el código y luego compruebe su identidad digitándolo en la casilla.",
|
||||||
|
"tempCodePlaceholder": "Código de 6 dígitos enviado a su correo",
|
||||||
|
"requestChangesButton": "Enviar correo con el pin",
|
||||||
|
"confirmChangesButton": "Verificar pin y actualizar sitio",
|
||||||
|
"continueToBuyModeButton": "Empezar a diseñar",
|
||||||
"editDialogHeader": "Editar un sitio existente",
|
"editDialogHeader": "Editar un sitio existente",
|
||||||
"editDialogParagraph": "El sitio ya debe estar registrado en conex.one para poder cargarlo localmente.",
|
"editDialogParagraph": "El sitio ya debe estar registrado en conex.one para poder cargarlo localmente.",
|
||||||
"continueToEditModeButton": "Editar este sitio",
|
"continueToEditModeButton": "Editar este sitio",
|
||||||
|
@ -18,7 +26,7 @@
|
||||||
"supportEmail": "Correo electrónico: soporte@conex.one",
|
"supportEmail": "Correo electrónico: soporte@conex.one",
|
||||||
"supportPhone": "",
|
"supportPhone": "",
|
||||||
"supportSchedule": "Horario de atención: L-V: 9:00 a.m. - 6:00 p.m.",
|
"supportSchedule": "Horario de atención: L-V: 9:00 a.m. - 6:00 p.m.",
|
||||||
"sampleTitle": "[Título de ejemplo]",
|
"sampleTitle": "Mi Sitio",
|
||||||
"sampleSlogan": "[Slogan o breve descripción]",
|
"sampleSlogan": "[Slogan o breve descripción]",
|
||||||
"sampleHeader": "Acerca de [Empres]",
|
"sampleHeader": "Acerca de [Empres]",
|
||||||
"sampleParagraph": "En [Nombre de Tu Empresa], nos dedicamos a ofrecer [tu servicio/producto] de la más alta calidad con un servicio al cliente excepcional. Nuestro equipo de expertos se asegura de que cada aspecto de tu experiencia sea manejado con profesionalismo y cuidado.",
|
"sampleParagraph": "En [Nombre de Tu Empresa], nos dedicamos a ofrecer [tu servicio/producto] de la más alta calidad con un servicio al cliente excepcional. Nuestro equipo de expertos se asegura de que cada aspecto de tu experiencia sea manejado con profesionalismo y cuidado.",
|
||||||
|
@ -33,5 +41,6 @@
|
||||||
"sampleTable23": "1000",
|
"sampleTable23": "1000",
|
||||||
"sampleTable31": "Laminado",
|
"sampleTable31": "Laminado",
|
||||||
"sampleTable32": "Breve descripción",
|
"sampleTable32": "Breve descripción",
|
||||||
"sampleTable33": "2000"
|
"sampleTable33": "2000",
|
||||||
|
"footer": "Copyright (C) 2024 Conex"
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,7 @@ a {
|
||||||
|
|
||||||
#continueEditingModeButton {
|
#continueEditingModeButton {
|
||||||
display: none;
|
display: none;
|
||||||
background-image: linear-gradient(45deg, #4a3b72, #4a3b72);
|
background-image: linear-gradient(45deg, #4a3b72, #8a6cdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes gradient {
|
@keyframes gradient {
|
||||||
|
@ -352,18 +352,14 @@ a {
|
||||||
|
|
||||||
#dialog button {
|
#dialog button {
|
||||||
margin: 0.5em 0.5em 0 0;
|
margin: 0.5em 0.5em 0 0;
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#dialog button {
|
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
color: var(--unemph-color);
|
color: var(--unemph-color);
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
border: 1px solid var(--hover-border);
|
border: 1px solid var(--hover-border);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1em;
|
right: 1.3em;
|
||||||
bottom: 1em;
|
bottom: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#dialog button:hover {
|
#dialog button:hover {
|
||||||
|
@ -382,6 +378,15 @@ a {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#requestChangesButton,
|
||||||
|
#confirmChangesButton {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#requestChangesButton {
|
||||||
|
left: 1.78em;
|
||||||
|
}
|
||||||
|
|
||||||
.input-dialog {
|
.input-dialog {
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
|
@ -472,3 +477,47 @@ a {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
background-color: var(--hover-background);
|
||||||
|
color: var(--unemph-color);
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background-color: var(--hover-background);
|
||||||
|
color: var(--unemph-color);
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-content {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer p {
|
||||||
|
margin: 0.5em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0.5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links li {
|
||||||
|
display: inline;
|
||||||
|
margin: 1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links a {
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: var(--hyper-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
24
server/db.go
24
server/db.go
|
@ -119,10 +119,12 @@ func RegisterSitePayment(db *sql.DB, capture Capture, cart ConexData) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateSite(db *sql.DB, pkey int, editorData json.RawMessage) error {
|
func UpdateSite(db *sql.DB, pkey int, editorData json.RawMessage, slogan string) error {
|
||||||
if _, err := db.Exec(`
|
if _, err := db.Exec(`
|
||||||
UPDATE sites SET raw = $1 WHERE id = $2
|
UPDATE sites
|
||||||
`, editorData, pkey); err != nil {
|
SET raw = $1, slogan = $2, status = 'diff'
|
||||||
|
WHERE id = $3
|
||||||
|
`, editorData, slogan, pkey); err != nil {
|
||||||
return fmt.Errorf("%s: %v", errDBUpdateRaw, err)
|
return fmt.Errorf("%s: %v", errDBUpdateRaw, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,15 +132,27 @@ func UpdateSite(db *sql.DB, pkey int, editorData json.RawMessage) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateSiteAuth(db *sql.DB, folder string, code string) (string, error) {
|
func UpdateSiteAuth(db *sql.DB, folder string, code string) (string, error) {
|
||||||
valid := time.Now().Add(5 * time.Minute)
|
var valid sql.NullTime
|
||||||
|
if err := db.QueryRow(`
|
||||||
|
SELECT valid
|
||||||
|
FROM sites
|
||||||
|
WHERE folder = $1
|
||||||
|
`, folder).Scan(&valid); err != nil {
|
||||||
|
return "", fmt.Errorf("error fetching valid timestamp: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if valid.Valid && valid.Time.After(time.Now().Add(4*time.Minute)) {
|
||||||
|
return "", fmt.Errorf("valid timestamp is still active, cannot update")
|
||||||
|
}
|
||||||
|
|
||||||
|
newValid := time.Now().Add(5 * time.Minute)
|
||||||
var email string
|
var email string
|
||||||
if err := db.QueryRow(`
|
if err := db.QueryRow(`
|
||||||
UPDATE sites
|
UPDATE sites
|
||||||
SET auth = $1, valid = $2
|
SET auth = $1, valid = $2
|
||||||
WHERE folder = $3
|
WHERE folder = $3
|
||||||
RETURNING email;
|
RETURNING email;
|
||||||
`, code, valid, folder).Scan(&email); err != nil {
|
`, code, newValid, folder).Scan(&email); err != nil {
|
||||||
return "", fmt.Errorf("%s: %v", errDBUpdateSiteAuth, err)
|
return "", fmt.Errorf("%s: %v", errDBUpdateSiteAuth, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,7 @@ func ConfirmChangesHandler(db *sql.DB) http.HandlerFunc {
|
||||||
Directory string `json:"directory"`
|
Directory string `json:"directory"`
|
||||||
Code string `json:"auth_code"`
|
Code string `json:"auth_code"`
|
||||||
EditorData json.RawMessage `json:"editor_data"`
|
EditorData json.RawMessage `json:"editor_data"`
|
||||||
|
Slogan string `json:"slogan"`
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&cart); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&cart); err != nil {
|
||||||
httpErrorAndLog(w, err, errReadBody, errClientNotice)
|
httpErrorAndLog(w, err, errReadBody, errClientNotice)
|
||||||
|
@ -296,7 +297,7 @@ func ConfirmChangesHandler(db *sql.DB) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := UpdateSite(db, pkey, cart.EditorData); err != nil {
|
if err := UpdateSite(db, pkey, cart.EditorData, cart.Slogan); err != nil {
|
||||||
httpErrorAndLog(w, err, errUpdateSite, errClientNotice)
|
httpErrorAndLog(w, err, errUpdateSite, errClientNotice)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue