apuntes:backend_frontend
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| apuntes:backend_frontend [2024/10/20 17:47] – [API con CRUD completo y base de datos] Santiago Faci | apuntes:backend_frontend [2025/03/24 09:34] (current) – [Backend: API] Santiago Faci | ||
|---|---|---|---|
| Line 14: | Line 14: | ||
| " | " | ||
| " | " | ||
| - | " | ||
| " | " | ||
| " | " | ||
| Line 259: | Line 258: | ||
| < | < | ||
| </ | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| ===== CRUD Backend + Frontend ===== | ===== CRUD Backend + Frontend ===== | ||
| Line 452: | Line 455: | ||
| ==== Backend: API ==== | ==== Backend: API ==== | ||
| + | |||
| + | El primer paso será preparar el fichero de configuración de la base de datos, indicando el tipo (SQLite) y la ubicación (el fichero ' | ||
| <file javascript src/ | <file javascript src/ | ||
| Line 467: | Line 472: | ||
| exports.db = db; | exports.db = db; | ||
| </ | </ | ||
| + | |||
| + | En el fichero principal simplemente añadiremos las operaciones definidas en el fichero ' | ||
| <file javascript src/ | <file javascript src/ | ||
| Line 483: | Line 490: | ||
| </ | </ | ||
| + | |||
| + | El fichero ' | ||
| <file javascript src/ | <file javascript src/ | ||
| Line 498: | Line 507: | ||
| module.exports = router; | module.exports = router; | ||
| </ | </ | ||
| + | |||
| + | La capa // | ||
| <file javascript src/ | <file javascript src/ | ||
| Line 545: | Line 556: | ||
| }; | }; | ||
| </ | </ | ||
| + | |||
| + | En nuestro caso, en la capa // | ||
| <file javascript src/ | <file javascript src/ | ||
| Line 598: | Line 611: | ||
| </ | </ | ||
| + | ==== Frontend: Utilidades ==== | ||
| + | <file javascript documentUtils.js> | ||
| + | const icons = new Map(); | ||
| + | icons.set(' | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | ); | ||
| + | icons.set(' | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | ); | ||
| + | // TODO Añadir más iconos | ||
| + | |||
| + | const el = function (elementId) { | ||
| + | return document.getElementById(elementId); | ||
| + | }; | ||
| + | |||
| + | const icon = function(iconName) { | ||
| + | return icons.get(iconName); | ||
| + | }; | ||
| + | |||
| + | const td = function(text) { | ||
| + | return '< | ||
| + | } | ||
| + | |||
| + | module.exports = { | ||
| + | el, | ||
| + | icon, | ||
| + | td | ||
| + | }; | ||
| + | </ | ||
| + | ==== Frontend: carga de datos en una tabla ==== | ||
| + | |||
| + | <file html index.html> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <link href=" | ||
| + | <script type=" | ||
| + | </ | ||
| + | <body onload=" | ||
| + | <div class=" | ||
| + | <ul class=" | ||
| + | <li class=" | ||
| + | <a class=" | ||
| + | </li> | ||
| + | <li class=" | ||
| + | <a class=" | ||
| + | </li> | ||
| + | </ul> | ||
| + | |||
| + | < | ||
| + | | ||
| + | <table class=" | ||
| + | < | ||
| + | <tr> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <th>. . .</ | ||
| + | </tr> | ||
| + | </ | ||
| + | <tbody id=" | ||
| + | </ | ||
| + | </ | ||
| + | </ul> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <file javascript index.js> | ||
| + | import axios from ' | ||
| + | import { el, icon, td } from ' | ||
| + | import { notifyOk } from ' | ||
| + | |||
| + | window.readCities = function() { | ||
| + | axios.get(' | ||
| + | .then((response) => { | ||
| + | const cityList = response.data; | ||
| + | const cityTable = el(' | ||
| + | | ||
| + | cityList.forEach(city => { | ||
| + | const row = document.createElement(' | ||
| + | row.id = ' | ||
| + | row.innerHTML = td(city.name) + | ||
| + | td(city.population) + | ||
| + | td(city.area) + | ||
| + | '<a class=" | ||
| + | icon(' | ||
| + | '</ | ||
| + | '<a class=" | ||
| + | icon(' | ||
| + | '</ | ||
| + | cityTable.appendChild(row); | ||
| + | }) | ||
| + | }); | ||
| + | }; | ||
| + | |||
| + | window.removeCity = function(id) { | ||
| + | if (confirm(' | ||
| + | axios.delete(' | ||
| + | .then((response) => { | ||
| + | if (response.status == 204) { | ||
| + | notifyOk(' | ||
| + | el(' | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | </ | ||
| + | ==== Frontend: Diálogos ==== | ||
| + | |||
| + | <file javascript dialogUtils.js> | ||
| + | import Toastify from ' | ||
| + | import ' | ||
| + | |||
| + | const notifyError = function(message) { | ||
| + | Toastify({ | ||
| + | text: message, | ||
| + | duration: 3000, | ||
| + | gravity: ' | ||
| + | position: ' | ||
| + | style: { | ||
| + | background: " | ||
| + | }, | ||
| + | }).showToast(); | ||
| + | }; | ||
| + | |||
| + | const notifyOk = function(message) { | ||
| + | Toastify({ | ||
| + | text: message, | ||
| + | duration: 3000, | ||
| + | gravity: ' | ||
| + | position: ' | ||
| + | style: { | ||
| + | background: " | ||
| + | }, | ||
| + | }).showToast(); | ||
| + | }; | ||
| + | |||
| + | module.exports = { | ||
| + | notifyError, | ||
| + | notifyOk | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | ==== Frontend: formulario de registro ==== | ||
| + | |||
| + | <file html register.html> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <link href=" | ||
| + | <script type=" | ||
| + | </ | ||
| + | < | ||
| + | <div class=" | ||
| + | <ul class=" | ||
| + | <li class=" | ||
| + | <a class=" | ||
| + | </li> | ||
| + | <li class=" | ||
| + | <a class=" | ||
| + | </li> | ||
| + | </ul> | ||
| + | | ||
| + | < | ||
| + | <form action=" | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input class=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input class=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input class=" | ||
| + | </ | ||
| + | <button type=" | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <file javascript register.js> | ||
| + | import axios from ' | ||
| + | import { notifyError, | ||
| + | import { el } from ' | ||
| + | |||
| + | window.addCity = function() { | ||
| + | const name = el(' | ||
| + | const population = el(' | ||
| + | const area = el(' | ||
| + | |||
| + | // TODO Validación de datos | ||
| + | if (name === '' | ||
| + | notifyError(' | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | axios.post(' | ||
| + | name: name, | ||
| + | population: population, | ||
| + | area: area | ||
| + | }); | ||
| + | |||
| + | // TODO Confirmar al usuario que todo ha ido bien (o mal) | ||
| + | notifyOk(' | ||
| + | |||
| + | // TODO Limpiar el formulario | ||
| + | el(' | ||
| + | el(' | ||
| + | el(' | ||
| + | }; | ||
| + | </ | ||
| + | ===== Funciones de utilidad ===== | ||
| + | |||
| + | <code javascript> | ||
| + | function getDays(fromDate, | ||
| + | const days = toDate.getTime() - fromDate.getTime(); | ||
| + | |||
| + | return Math.abs(Math.round(days / (1000 * 3600 * 24))); | ||
| + | } | ||
| + | |||
| + | function getDaysFromNow(date) { | ||
| + | const now = new Date(Date.now()); | ||
| + | | ||
| + | return getDays(date, | ||
| + | } | ||
| + | |||
| + | function getYearsFromNow(date) { | ||
| + | const now = new Date(Date.now()); | ||
| + | return Math.ceil(getDays(date, | ||
| + | } | ||
| + | |||
| + | module.exports = { | ||
| + | getDaysFromNow, | ||
| + | getYearsFromNow, | ||
| + | getDays | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Ficheros de configuración ===== | ||
| + | |||
| + | <code yaml config.local.yaml> | ||
| + | db: | ||
| + | host: localhost | ||
| + | port: 3306 | ||
| + | user: user | ||
| + | password: password | ||
| + | database: cities | ||
| + | |||
| + | service: | ||
| + | port: 8080 | ||
| + | </ | ||
| + | |||
| + | <file javascript config/ | ||
| + | const yaml = require(' | ||
| + | const fs = require(' | ||
| + | const yargs = require(' | ||
| + | const { hideBin } = require(' | ||
| + | |||
| + | // Lee el fichero de configuración | ||
| + | let configFile = ' | ||
| + | const argv = yargs(hideBin(process.argv)).argv; | ||
| + | if (argv.config != undefined) { | ||
| + | configFile = argv.config; | ||
| + | } | ||
| + | const config = yaml.load(fs.readFileSync(configFile, | ||
| + | |||
| + | module.exports = { | ||
| + | config | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== MariaDB como base de datos ===== | ||
| + | |||
| + | <code javascript> | ||
| + | const knex = require(' | ||
| + | . . . | ||
| + | const { config } = require(' | ||
| + | |||
| + | // Configuración de la base de datos: tipo, ubicación y otros parámetros | ||
| + | const db = knex({ | ||
| + | client: ' | ||
| + | connection: { | ||
| + | host: config.db.host, | ||
| + | port: config.db.port, | ||
| + | user: config.db.user, | ||
| + | password: config.db.password, | ||
| + | database: config.db.database | ||
| + | }, | ||
| + | useNullAsDefault: | ||
| + | }); | ||
| + | </ | ||
| ---- | ---- | ||
apuntes/backend_frontend.1729446428.txt.gz · Last modified: by Santiago Faci
