Enrico Battistella
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Esercizio Sito web di raccolta dati meteo - [ ] Inserimento e salvataggio dati - [ ] Città - [ ] Condizioni meteo - [ ] Temperatura - [ ] DateTime - [ ] Commento - [ ] Ricerca dati inseriti - [ ] Città - [ ] Intervallo di tempo - [ ] Visione a tabella dei record che corrispondono alla ricerca - [ ] Vista home con gli ultimi inserimenti - [ ] Vista di dettaglio dell'inserimento con i dati completi ## Creazione del server base 1. Creazione cartella e `npm init` 2. nodemon e script in package.json 3. creazione index.js e app.js 4. test di una chiamata alla home per verificare il funzionamento ### 1- npm init Serve ad inizializzare il package.json. File che conterrà tutti gli script e le dipendenze (librerie) del progetto. ```bash npm init ``` ### 2- nodemon e live reload Nodemon è una utility che avvia il programma nodejs tenendo monitorati i file del progetto, ogni volta che un file cambia riavvia automaticamente il processo. Serve ad ad avere sempre in esecuzione le ultime modifiche salvate. ```bash npm install --save-dev nodemon ``` aggiungere nel file package.json lo script `dev` ```json= "scripts": { "start": "node index.js", "dev": "nodemon index.js", "test": "echo \"Error: no test specified\" && exit 1" }, ``` ### 3 index e app.js `Express` è la libreria che si occupa di gestire il server web. ```bash npm install --save express ``` Il file `app.js` contiene la configurazione del server `express`, si occupa di registrare i middleware comuni a tutta l'applicazione (es: body-parser, log, autenticazione, ecc...) Il file instanzia l'applicazione express `const app = express()`, la configura e la esporta. Creare il file `app.js` nella cartella src ```javascript const express = require('express'); const app = express(); module.exports = app; ``` Il file `index.js` si occupa solo di avviare l'applicazione. Importa l'app dal file `app.js` e chiama il metodo `listen`. Creare il file `index.js` nella root del progetto ```javascript const app = require('./src/app'); app.listen(3000, () => { console.log('App listening on port 3000'); }); ``` Avviare l'applicazione con: ```bash npm run dev ``` ### 4 - aggiungere una chiamata di test (poi va rimossa) E' sempre buona norma procedere per piccoli passi e testare il funzionamento. Per verificare che il server funzioni aggiungere nel file `app.js` un middleware che risponde a qualsiasi chiamata con una risposta di conferma. ```javascript= app.use((req, res) => { res.send('funziono!'); }) ``` Aprire il browser all'indirizzo [http://localhost:3000](http://localhost:3000) e verificare che compaia il testo corretto. Una volta eseguito il test rimuovere il middleware. ## Suddivisione in sottoproblemi Una volta avviato un server funzionante si procede con l'implementazione del codice relativo al progetto in esame. Prima di procedere è sempre bene suddividere il problema in parti più piccole, stabilire l'ordine in cui affrontarle e i test intermedi da fare. Sottoproblemi: * Servono 3 pagine * Inserimento * Visualizzazione ultimi risultati * Visualizzazione risultati filtrati (stessa pagina del punto precedente) * Dettaglio di un record * Abbiamo 1 tipo di dato: entry del meteo, lo chiamiamo `record` * E' necessario avere un sistema di filtri Ordine di implementazione 1. creare le pagine, anche vuote, con i relativi router e configurare l'indizzamento 1. Creazione e configurazione del router generico e di quello specifico per i record 2. Creazione del controller e dei metodi necessari a gestire le varie pagine 3. Verifica che navigando i vari url venga utilizzato il metodo previsto nel controller 4. Creazione dei vari template per le pagine 5. Test che per ogni url venga renderizzato il template corretto 2. Visualizzazione del dettaglio di un record con dati di mock 1. definire la struttura del dato del record 2. creare un oggetto direttamente in javascript da passare alla view 3. verificare che la view mostri correttamente i dati di prova 3. Gestire la pagina di inserimento 1. Creare il form nella view della pagina 2. Creare la route per gestire la chiamata `POST` 3. Configurare il server per accettare il body della richiesta 4. Verificare che i dati arrivino correttamente e siano leggibili 4. Scrittura dello schema e del model 1. Scrivere il file `record.schema.js` seguendo la struttura dei dati definita in precedenza 2. Scrivere il file `record.model.js` e il suo metodo `create` 5. Attaccare la pagina di inserimento al model 6. Attaccare la pagina di dettaglio al model 1. Aggiungere il metodo `getById` al model 2. Modificare il controller in modo che vada ad utilizzare il metodo `getById` del model 7. Home: visualizzare tutti i record 1. Implementare il metodo `find` nel model 2. Visualizzare tutta la lista dei record inseriti 8. Home: visualizzare i record filtrati 1. Definizione dei filtri previsti 2. Implementazione del form dei filtri nella view della lista 3. Modifica del metodo `find` del model perchè accetti e utilizzi i filtri 4. Modifica del controller perchè accetti i filtri e chiami il metodo `find` del model nel modo corretto 9. Home: visualizzare gli ultimi record inseriti se non sono applicati filtri 1. Modifica del controller perchè applichi dei filtri predefiniti nel caso in cui non ne arrivino dalla richiesta ### 1 - Creazione delle pagine 1. Creazione e configurazione del router generico e di quello specifico per i record 2. Creazione del controller e dei metodi necessari a gestire le varie pagine 3. Verifica che navigando i vari url venga utilizzato il metodo previsto nel controller 4. Creazione dei vari template per le pagine 5. Test che per ogni url venga renderizzato il template corretto #### 1.1 Configurazione router I router sono i componenti che si occupano di gestire in modo gerarchico quale funzione andrà a gestire un determinato url. Creare il file `router.js` nella cartella pages: ```javascript const express = require('express'); const router = express.Router(); module.exports = router; ``` Modificare `app.js` in modo da registrare il router creato: ```javascript //in alto vicino agli altri require: const router = require('./pages/router'); //dopo la configurazione dei middleware generici: app.use(router); ``` Creare il file `record.router.js` nella cartella `pages/record`. ```javascript const express = require('express'); const router = express.Router(); module.exports = router; ``` Modificare il file `router.js` creato in precedenza per fare in modo che tutte le richieste che iniziano con `/record` vengano gestite dal `record.router`: ```javascript const express = require('express'); const router = express.Router(); const recordRouter = require('./record/record.router'); router.use('/records', recordRouter); router.get('/', (req, res) => { res.redirect('/records'); }) module.exports = router; ``` #### 1.2 Creare record.controller Il controller esporta le funzioni che andranno a gestire le varie chiamate. In genere ogni funzione che viene esportata dal controller viene registrata nel router per gestire un tipo di url. Creare il file `record.controller.js` nella cartella `pages/record` e predisporre un metodo per ogni pagina che si andrà a gestire: ``` javascript module.exports.list = async (req, res, next) => { res.send('List Page'); } module.exports.add = (req, res, next) => { res.send('Add Page'); } module.exports.details = async (req, res, next) => { res.send('Detail Page'); } ``` Configurare `record.router.js` con le varie route e i corrispettivi metodi del controller: ```javascript const express = require('express'); const router = express.Router(); const recordController = require('./record.controller'); router.get('/', recordController.list); router.get('/add', recordController.add); router.get('/:id', recordController.details); module.exports = router; ``` #### 1.3 Verifica del corretto indirizzamento Aprire il browser e navigare nelle varie pagine previste dai router, verificando che la risposta corrisponda a quella prevista nel controller. #### 1.4 Creazione dei template di esempio per le varie pagine Per renderizzare i template viene usata la libreria `ejs`: ```bash npm i --save ejs ``` Configurare express perchè utilizzi eja come `view engine`, nel file `app.js`: ```javascript // prima della registrazione del router app.set('view engine', 'ejs'); app.set('views', './src/templates'); // dice a express in che cartella cercare i template ``` Creazione dei file template nella cartella `src/templates`: `add.ejs`, `details.ejs`, `list.ejs`. Ogni template per il momento è una pagina html con dentro solo il nome della pagina visualizzata, ci serve solo per verificare che tutto funzioni. ```html <html> <head> <title>Add</title> </head> <body> Add page </body> </html> ``` Configurare `record.controller` perchè renderizzi la pagina corretta ad ogni richiesta: ```javascript module.exports.list = async (req, res, next) => { res.render('list.ejs') } module.exports.add = (req, res, next) => { res.render('add.ejs') } module.exports.details = async (req, res, next) => { res.render('details.ejs') } ``` #### 1.5 Verifica del corretto funzionamento Aprire il browser e navigare nelle varie pagine previste dai router, verificando che ogni pagina contenga il testo previsto nel template corretto. ### 2 - Pagina di dettaglio con dati di mock 1. definire la struttura del dato del record 2. creare un oggetto direttamente in javascript da passare alla view 3. verificare che la view mostri correttamente i dati di prova #### 2.1 Definire la struttura del dato del record Ragionare su che dati ci serve avere nella nostra entità `record`, ci serve: - data (data a cui corrispondono le rilevazioni) - city (luogo di pertinenza) - conditions (sole, pioggia, nuvolo, nebbia, neve) - temperature (temperature in °C) - note (eventuali annotazioni) #### 2.2 Creare un oggetto di mock da passare alla view Prima di gestire il salvataggio e il model è utile verificare il funzionamento e la visualizzazione del dato usanto dati di prova (mock). Definire un oggetto e passarlo al template di `details`, nel file `record.controller.js`: ```javascript module.exports.details = async (req, res, next) => { const record = { date: new Date(), city: 'Vicenza', temperature: 21, conditions: 'sole', note: 'nota di prova' }; res.render('details.ejs', {record: record}) } ``` Modificare il template in modo da mostrare i dati, nel file `details.ejs`: ```html <html> <head> <title>Detail</title> </head> <body> Data: <%= record.date %> <br> Condizioni: <%= record.conditions %> <br> Temperatura: <%= record.temperature %>°C <br> Città: <%= record.city %> <br> Nota: <%= record.note %> </body> </html> ``` #### 2.3 Verificare che la view mostri correttamente i dati di prova Aprire la pagina di dettaglio dal browser e verificare che i dati vengano mostrati correttamente ### 3 Gestire la pagina di inserimento 1. Creare il form nella view della pagina 2. Creare la route per gestire la chiamata `POST` 3. Configurare il server per accettare il body della richiesta 4. Verificare che i dati arrivino correttamente e siano leggibili #### 3.1 Creare il form nella pagina add I dati verranno mandati tramite un form html, creare il form nel template `add.ejs`. `action` e `method` nel tag `form` corrispondono all'url e al method con cui il form invierà i dati al server. ```html <html> <head> <title>Add</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script> </head> <body> <div class="container"> <h1>Add Record</h1> <form action="/records/add" method="POST"> <div class="form-group"> <label for="city">Data</label> <input type="datetime-local" class="form-control" name="date" > </div> <div class="form-group"> <label for="city">Città</label> <input type="text" class="form-control" name="city" > </div> <div class="form-group"> <label for="temperature">Temperatura</label> <input type="number" class="form-control" name="temperature" > </div> <div class="form-group"> <label>Condizioni</label> <select class="custom-select" name="conditions"> <option selected>Choose...</option> <option value="sole">Sole</option> <option value="pioggia">Pioggia</option> <option value="nuvolo">nuvolo</option> <option value="nebbia">nebbia</option> <option value="neve">neve</option> </select> </div> <div class="form-group"> <label for="note">Nota</label> <input type="text" class="form-control" name="note" > </div> <button type="submit" class="btn btn-primary">Aggiungi</button> </form> </div> </body> </html> ``` #### 3.2 Creare la route per gestire la chiamata `POST` La richiesta che viene fatta dal form è di tipo `POST` all'url `records/add`, attualmente il nostro server non è configurato per gestire tale richiesta. Nel file `record.controller.js` creare il metodo che gestirà la chiamata di aggiunta: ```javascript module.exports.create = async (req, res, next) => { console.log(req.body); const newId = 'test'; res.redirect(`records/${newId}`); } ``` Nel file `record.router.js` configurare la chiamata post perchè venga gestita dal metodo creato: ```javascript router.post('/add', recordController.create); ``` #### 3.3 Configurare il server per accettare il body della richiesta Attualmente facendo il submit del form il log che abbiamo messo nel controller non mostra correttamente i dati, questo perchè non abbiamo detto al server come interpretarli. Nel caso di form HTML il formato con cui vengono inviati i dati di una chiamata post è `x-www-form-urlencoded`, per abilitare express a leggere questo formato è necessario installare la libreria `body-parser`: ```bash npm i --save body-parser ``` E configuare il server nel file `app.js`: ```javascript // prima della registrazione del router app.use(express.urlencoded()); ``` #### 3.4 Verificare che i dati arrivino correttamente e siano leggibili Facendo il submit del form il console log dovrebbe stampare correttamente l'oggetto con i dati inviati. ### 4 Scrittura dello schema e del model 1. Scrivere il file `record.schema.js` seguendo la struttura dei dati definita in precedenza 2. Scrivere il file `record.model.js` e il suo metodo `create` #### 4.1 Creazione dello schema Mongoose è la libreria che utilizziamo per interagire con un database `mongodb`: ```bash npm i --save mongoose ``` Per connettersi al database è necessario chiamare il metodo `connect` nel file `app.js`: ```javascript const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:27017/its_meteo', { useNewUrlParser: true, useUnifiedTopology: true }); ``` La libreria crea automaticamente un database chiamato `its_meteo` quando necessario. Lo `schema` è l'entità che usa mongoose per definire la struttura di un dato che può essere scritto a db. Creare il file `record.schema.js` nella cartella `record`: ```javascript const mongoose = require('mongoose'); const RecordSchema = mongoose.Schema({ date: {type: Date}, city: String, conditions: {type: String, enum: ['sole', 'pioggia', 'nuvolo', 'nebbia', 'neve']}, temperature: Number, note: String }); module.exports = mongoose.model('Record', RecordSchema); ``` #### 4.2 Scrivere il file `record.model.js` e il suo metodo `create` Il model è l'entità che verrà richiamata dal controller per manipolare i dati (lettura o scrittura). Importa lo schema e viene importato dal controller. Creare il file `record.model.js` che esporti il metodo create: ```javascript const Record = require('./record.schema'); module.exports.create = async (data) => { const newRecord = new Record(data); return newRecord.save(); // return Record.create(data); }; ``` ### 5 Attaccare la logica della pagina di create al model Modificare `record.controller.js` in modo che utilizzi il model creato: ```javascript const recordModel = require('./record.model'); module.exports.create = async (req, res, next) => { try { const newRecord = await recordModel.create(req.body); res.redirect(`/records/${newRecord.id}`); } catch(err) { console.log(err); res.status(500); res.send(); } } ``` Verificare che i dati siano correttamente scritti a database. ### 6 Attaccare la pagina di dettaglio al model 1. Aggiungere il metodo getById al model 2. Modificare il controller in modo che vada ad utilizzare il metodo getById del model #### 6.1 Aggiungere `getById` al model Nel file `record.model.js`: ```javascript module.exports.getById = async (id) => { return Record.findById(id); } ``` #### 6.2 Modificare il controller In `record.router.js` l'url è definito come `/:id`, questo permette di accedere al parametro `id` richiesto accedendo alla variabile `req.params.id` nel controller. Nel file `record.controller.js`: ```javascript= module.exports.details = async (req, res, next) => { try { const record = await recordModel.getById(req.params.id); if (!record) { res.status(404); res.send('Not Found'); return; } res.render('details.ejs', {record: record}); } catch(err) { console.log(err); res.status(500); res.send(); } } ``` Viene controllato se il record richiesto esiste (tramite l'`if`) e in caso contrario la risposta avrà codice `404 Not Found`. ### 7 Visualizzare tutti i record Nel file `record.model.js` creare il metodo `find` che richiama lo schema di mongoose e torna tutti i Record inseriti: ```javascript= module.exports.find = async () => { return Record.find(); } ``` Nel file `record.controller.js` chiamare il metodo `find` del model e passare i risultati al template: ```javascript= module.exports.list = async (req, res, next) => { const records = await recordModel.find(); res.render('list.ejs', {records: records}); } ``` Nel file `list.ejs` renderizzare con un forEach una riga della tabella per ogni record trovato: ```htmlembedded= <html> <head> <title>List</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script> </head> <body> <div class="container"> <h3>Records</h3> <table class="table"> <thead> <tr> <th> Data </th> <th> Città </th> <th> Condizioni </th> <th> Link </th> </tr> </thead> <tbody> <% records.forEach(record => { %> <tr> <td> <%= record.date %> </td> <td> <%= record.city %> </td> <td> <%= record.conditions %> - <%= record.temperature %>°C </td> <td> <a href="/records/<%= record.id %>">Details</a> </td> </tr> <% }) %> </tbody> </table> </div> </body> </html> ``` ### 8 Gestione dei filtri Iniziare col definire i filtri che ci interessa avere a disposizione e aggiungendo al template `list.ejs` il form di ricerca. A differenza del form di aggiunta, questo form avrà `method="GET"`. Questo significa che i valori inseriti dall'utente verranno inviati tramite queryparams nell'url della richiesta. `action="/records"` significa che l'url che verrà richiesto al submit è sempre quello della lista dei record, ma conterrà anche i queryparams dei filtri. Aggiungere a `list.ejs` il form di ricerca: ```htmlembedded= <form class="form-inline" action="/records" method="GET"> <label class="mr-2">Città:</label> <input type="text" class="form-control mr-2" name="city"> <label class="mr-2">Da:</label> <input type="datetime-local" class="form-control mr-2" name="from"> <label class="mr-2">A:</label> <input type="datetime-local" class="form-control mr-2" name="to"> <button class="btn btn-secondary" type="submit">Cerca</button> </form> ``` Nel controller i parametri di ricerca sono messi a disposizione nell'oggetto req.query. In questo caso i parametri non richiedono trasformazioni particolari, quindi è compito direttamente del model controllare che filtri sono richiesti e comporre la query adatta per mongoose. Nel file `record.model.js`: ```javascript= module.exports.find = async (query) => { const q = {}; if (query.city) { q.city = { $regex : new RegExp(query.city, "i")}; } if (query.from || query.to) { q.date = {}; } if (query.from) { q.date.$gte = query.from; } if (query.to) { q.date.$lte = query.to; } return Record.find(q); } ``` La strategia utilizzata è quella di partire con un oggetto `q` vuoto e aggiungere in seguito le proprietà necessarie a filtrare nel caso arrivino nell'argomento query della funzione. Questo permette di tornare tutti i risultati se arriva un oggetto `query` vuoto come argomento, e invece di popolare la query nel caso arrivino uno o più parametri di ricerca. Nel file `record.controller.js` è sufficiente passare al metodo `find` del model l'oggetto `req.query`, che contiene i queryparams della richiesta. Nel file `record.controller.js`: ```javascript= module.exports.list = async (req, res, next) => { const query = req.query; const records = await recordModel.find(query); res.render('list.ejs', {records: records}); } ``` ### 9 - Visualizzare gli ultimi record inseriti se non sono applicati filtri Iniziare col definire cosa si intende per "ultimi record": in questo caso si è deciso di tornare i record inseriti nella data di oggi. Questo riduce il problema all'applicazione di un filtro per date di default nel caso che l'utente non ne imposti uno nei filtri. Impostare questo filtro di default è compito del controller, il model sa solo come cercare i dati a partire da determinati parametri, se in assenza di richieste particolari vengono applicati dei valori di default è compito del controller definirlo e gestirlo. Nel file `record.controller.js`: ```javascript= module.exports.list = async (req, res, next) => { const query = req.query; if (!query.city && !query.from && !query.to) { const from = new Date(); from.setHours(0, 0, 0, 0); const to = new Date(); to.setHours(23, 59, 59, 999); query.from = from; query.to = to; } const records = await recordModel.find(query); res.render('list.ejs', {records: records, query: query}); } ``` Si è deciso di applicare l'intervallo di date di default solo se non è presente alcun filtro impostato dall'utente, questo controllo avviene tramite l'`if`. Se ci troviamo in queste condizioni viene calcolata una data che rappresenta l'inizio della giornata di oggi e una che rappresenta la fine e vengono passate come `from` e `to` al model. Il resto della logica non richiede modifiche. # Migliorie - popolare i valori dei filtri con quelli applicati - navbar - validazione nel campo data in inserimento - template della pagina di dettaglio - possibilità di eliminare un record - formattazione date nel template - prepopolare pagina add con data di oggi e ultima città inserita

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully