mirror of
https://codeberg.org/JasterV/sentences-crud.git
synced 2026-04-27 02:15:43 +00:00
views almost done
This commit is contained in:
parent
58e53ce174
commit
20ce2bda35
7 changed files with 283 additions and 1 deletions
54
src/components/view/router.ts
Normal file
54
src/components/view/router.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { NextFunction, Request, Response, Router } from "express"
|
||||
import { Sentence } from "../sentences/interfaces/sentence"
|
||||
import { sentenceModel } from "../sentences/sentenceModel"
|
||||
import { NotFoundError } from "../../common/errors"
|
||||
import db from "../../db"
|
||||
|
||||
const router = Router()
|
||||
|
||||
const model = sentenceModel(db)
|
||||
|
||||
router.get('/sentences', async (req, res) => {
|
||||
const { orderBy, order, lastId } = req.query
|
||||
const sentences: Sentence[] = await model.list({ orderBy, order, last: lastId })
|
||||
return res.render('list', { sentences })
|
||||
})
|
||||
|
||||
router.get('/sentence/:id/update', async (req, res) => {
|
||||
const { id } = req.params
|
||||
const { text, category } = req.body
|
||||
const sentence: Sentence = await model.update(id, { text, category })
|
||||
return res.render('sentence', { sentence })
|
||||
})
|
||||
|
||||
router.get('/sentence/:id/delete', async (req, res) => {
|
||||
const { id } = req.params
|
||||
await model.del(id)
|
||||
return res.redirect('/sentences')
|
||||
})
|
||||
|
||||
router.get('/sentence/:id', async (req, res) => {
|
||||
const { id } = req.params
|
||||
const sentence: Sentence = await model.getById(id)
|
||||
return res.render('sentence', { sentence })
|
||||
})
|
||||
|
||||
router.get('/sentence', async (req, res) => {
|
||||
const { text, category } = req.body
|
||||
const id = await model.create({ text, category })
|
||||
return res.redirect('/sentence/' + id)
|
||||
})
|
||||
|
||||
// EJS views
|
||||
router.get('/', (_req, res) => res.render('index'))
|
||||
|
||||
router.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
|
||||
if (err instanceof NotFoundError) {
|
||||
return res.render('error', { error: { code: 404, title: 'NOT FOUND' } })
|
||||
}
|
||||
return res.render('error', { error: { code: 500, title: 'SERVER ERROR' } });
|
||||
})
|
||||
|
||||
router.use((_req, res) => res.render('error', { error: { code: 404, title: 'NOT FOUND' } }))
|
||||
|
||||
export default router
|
||||
|
|
@ -3,14 +3,21 @@ import authMiddleware from './common/middlewares/authMiddleware'
|
|||
import { errorService } from './common/services/errorService'
|
||||
import sentenceRouter from './components/sentences/router'
|
||||
import translationRouter from './components/translation/router'
|
||||
import viewsRouter from './components/view/router'
|
||||
import config from './config'
|
||||
|
||||
const { handle } = errorService()
|
||||
|
||||
const app = express()
|
||||
|
||||
app.set('view engine', 'ejs')
|
||||
app.set('views', process.cwd() + '/src/views')
|
||||
app.use(express.static(process.cwd() + '/public'))
|
||||
app.use(express.json())
|
||||
|
||||
app.use('/public', viewsRouter)
|
||||
// translation api
|
||||
app.use('/api/v1/translate', translationRouter)
|
||||
app.use('/api/v1/translate', authMiddleware(config.secret), translationRouter)
|
||||
// sentences api
|
||||
app.use('/api/v1/sentences', authMiddleware(config.secret), sentenceRouter)
|
||||
// Error handling logic
|
||||
|
|
|
|||
35
src/views/error.ejs
Normal file
35
src/views/error.ejs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
|
||||
<title>Sentences CRUD</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="d-flex flex-column h-100">
|
||||
<h1 class="mt-5 title align-self-center">
|
||||
<%= error.code + ' ' + error.title %>
|
||||
</h1>
|
||||
<a class="mt-5 align-self-center" href="/public">
|
||||
<button type="button" class="btn btn-primary">
|
||||
<h3>Home</h3>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Option 1: Bootstrap Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
||||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
32
src/views/index.ejs
Normal file
32
src/views/index.ejs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
|
||||
<title>Sentences CRUD</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="d-flex flex-column h-100 flex-grow-1">
|
||||
<h1 class="mt-5 title align-self-center flex-grow-1">Welcome :)</h1>
|
||||
<a class="mt-5 align-self-center flex-grow-1" href="/public/sentences">
|
||||
<button type="button" class="btn btn-primary">
|
||||
<h3>Sentences</h3>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Option 1: Bootstrap Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
||||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
94
src/views/list.ejs
Normal file
94
src/views/list.ejs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
|
||||
<title>Sentences CRUD</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="d-flex flex-column h-100 flex-grow-1">
|
||||
<% if(!sentences || sentences && sentences.length==0) { %>
|
||||
<h1 class="mt-5 title align-self-center">No sentences found</h1>
|
||||
<a class="mt-5 align-self-center" href="/public/sentence">
|
||||
<button type="button" class="btn btn-primary">
|
||||
<h3>New Sentence</h3>
|
||||
</button>
|
||||
</a>
|
||||
<% } %>
|
||||
<% if (sentences && sentences.length> 0) { %>
|
||||
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
|
||||
|
||||
<div class="btn-group mr-2" role="group" aria-label="First group">
|
||||
<a href="/sentences?page=0&orderBy">
|
||||
<button type="button" class="btn btn-secondary">Unsorted
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btnGroupDrop1" type="button" class="btn btn-secondary dropdown-toggle"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Sort categories
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
|
||||
<a class="dropdown-item" href="/sentences">ASC</a>
|
||||
<a class="dropdown-item" href="#">DESC</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/sentences/1"><button type="button" class="btn btn-secondary mr-2">Next</button></a>
|
||||
</div>
|
||||
|
||||
<table id="datatable" class="table table-striped mt-5" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Text</th>
|
||||
<th>Category</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for(const sentence of sentences) { %>
|
||||
<tr>
|
||||
<td>
|
||||
<a href=<%= '/public/sentence/' + sentence.id %>><%= sentence.id %></a>
|
||||
</td>
|
||||
<td>
|
||||
<%= sentence.text %>
|
||||
</td>
|
||||
<td>
|
||||
<%= sentence.category %>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group" aria-label="First group">
|
||||
<a href=<%='/public/sentence/' + sentence.id %>>
|
||||
<button type="button" class="btn btn-primary">Edit</button>
|
||||
</a>
|
||||
<a href=<%='/public/sentence/' + sentence.id + '/delete' %>><button
|
||||
type="button" class="btn btn-primary">Delete</button></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Option 1: Bootstrap Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
||||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
60
src/views/sentence.ejs
Normal file
60
src/views/sentence.ejs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
|
||||
<title>Sentences CRUD</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="d-flex flex-column h-100 flex-grow-1">
|
||||
<h1 class="mt-5 align-self-center flex-grow-1">
|
||||
Sentence <%= sentence.id %>
|
||||
</h1>
|
||||
<h1 class="mt-2 align-self-center flex-grow-1">
|
||||
Sentence <%= sentence.text %>
|
||||
</h1>
|
||||
<h1 class="mt-2 align-self-center flex-grow-1">
|
||||
Sentence <%= sentence.category %>
|
||||
</h1>
|
||||
<div
|
||||
class="btn-group mt-5 align-self-center flex-grow-1"
|
||||
role="group"
|
||||
aria-label="First group"
|
||||
>
|
||||
<a href="/sentences?page=0&orderBy"
|
||||
><button type="button" class="mr-2 btn btn-primary">Edit</button></a
|
||||
>
|
||||
<a href="/sentences?page=0&orderBy"
|
||||
><button type="button" class="btn btn-primary mr-2">Delete</button></a
|
||||
>
|
||||
</div>
|
||||
|
||||
<a href="/sentences?page=0&orderBy"
|
||||
><button
|
||||
type="button"
|
||||
class="btn btn-primary mt-5 align-self-center flex-grow-1 mr-2"
|
||||
>
|
||||
Sentences
|
||||
</button></a
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Option 1: Bootstrap Bundle with Popper -->
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue