//routes/backend/post.js

import express from 'express'
const postRouter = express.Router()
import post from '../../controllers/backend/post.js'

postRouter.get('/', async function(req,res){
    await post.getPage(req,res)
})

export default postRouter

 

//controllers/backend/post.js

import category from '../../models/category.js'

class Post{
    async getPage(req,res){
        req.settings.pageTitle = 'ទំព័រ​ការផ្សាយ'
        req.settings.message = ''
        req.settings.route = '/admin/post'
        req.settings.type = 'post'

        req.settings.categories = await category.getItem(req,'all')
        
        res.render('base', {data:req.settings})
    }
}

export default new Post()

 

<!--views/backend/index.ejs-->

<link href="/styles/backend/index.css" rel="stylesheet">
<script src="/scripts/backend/paginate.js"></script>
 
<section class="Header">
    <div class="wrapper region">
        <div class="logo"><%= data.pageTitle %></div>
        <form method="post" action="/search">
            <select name="type">
                <option>ការផ្សាយ</option>
                <option>ទំព័រស្តាទិក</option>
                <option>អ្នក​ប្រើប្រាស់</option>
            </select>
            <input type="text" name="q" placeholder="Search" required>
            <input type="submit" value="ស្វែង​រក">
        </form>
        <div class="logout">
            <a href="/">ទំព័រ​មុខ</a> | <a href="/admin/login/logout">ចេញ​ក្រៅ</a>
        </div>
    </div>
</section>
 
<section class="Body">
    <div class="wrapper region">
        <div class="sidebar-wrapper">
        <div class="sidebar">
            <a href='/admin/post'><img src='/images/movie.png' /></a>
            <a href='/admin/post'>ការផ្សាយ</a>
            
            <a href='/admin/category'><img src='/images/category.png' /></a>
            <a href='/admin/category'>ជំពូក</a>
            
            <a href='/admin/book'><img src='/images/books.png' /></a>
            <a href='/admin/book'>សៀវភៅ</a>
            
            <a href='/admin/upload'><img src='/images/upload.png' /></a>
            <a href='/admin/upload'>Upload</a>
            
            <a href='/admin/user'><img src='/images/users.png' /></a>
            <a href='/admin/user'>អ្នក​ប្រើប្រាស់</a>
            
            <a href='/admin/setting'><img src='/images/setting.png' /></a>
            <a href='/admin/setting'>Setting</a>
        </div>
        </div>
        
        <% if(data.route == '/admin/post'){ %>
            <%- include('./post.ejs') %>
        <% } else if(data.route == '/admin/category'){ %>
            <%- include('./category.ejs') %>
        <% } else if(data.route == '/admin/post'){ %>
            <%- include('./post.ejs') %>
        <% } %>

    </div>
</section>

<section class="Footer Listing region">
    <div class="info">សរុប​ទាំងអស់​មាន​ចំនួនៈ <%= data.count %></div>

    <ul class="list">
        <% if('items' in data){ %>
            <% for(let item of data.items) { %>
            <li>
                <div class='thumb'>
                    <a href='/<%= data.type %>/<%= item.id %>'><img src='<%= item.thumb %>'/></a>
                    <% if('video' in item){ %>
                        <% if(item.video !== ''){ %>
                            <img class="play-icon" src="/images/play-icon"/>
                        <% } %>
                    <% } %>
                </div>
                <div class="title">
                    <a href="/<%= data.type %>/<%= item.id %>"><%= item.title %></a>
                    <div><%= (new Date(item.date)).toLocaleDateString('it-IT') %></div>
                </div>
                <div class="edit">
                    <a href="<%= data.route %>/edit/<%= item.id %>"><img src="/images/edit.png"/></a>
                    <a href="<%= data.route %>/delete/<%= item.id %>"><img src="/images/delete.png"/></a>
                </div> 
            </li>
            <% } %>
        <% } %>
    </ul>

    <div class="paginate">
        <img onclick="paginate('<%= data.route %>')" src='/images/load-more.png' />
    </div>
</section>

 

<!--views/backend/post.ejs-->

<link rel="stylesheet" href="/styles/backend/post.css" />
<script src="/scripts/ckeditor/ckeditor.js"></script>
<script src="/scripts/backend/addCategory.js"></script>
<script src="/scripts/backend/video.js"></script>

<section class="Post">
    <form action="/admin/post" method="post" name="form" onSubmit="submitForm(event)">
        <input type="text" name="title" required placeholder="Title" />
        <textarea name="content" id="editor"></textarea>
        <input type="text" name="categories" required placeholder="Categories" />
        <div class="wrapper"> 
            <select id="category" onChange="getCategory()">
                <option>Select a category</option>
                <% for(let category of data.categories){ %>
                <option><%= category.title %></option>
                <% } %>
            </select>
            <input type="text" name="thumb" required placeholder="Thumbnail" />
            <input type="datetime-local" name="datetime" required />
            <input type="submit" value="Publish" />
            <input type="hidden" name="videos" value="" />
        </div>
    </form>
 
    <div class='form'>
        <select name='type'>
            <option>YouTube</option>
            <option>YouTubePlaylist</option>
            <option>Facebook</option>
            <option>OK</option>
            <option>Dailymotion</option>
            <option>Vimeo</option>
        </select>
        <input name='videoid' type='text' placeholder="Video ID" required />
        <select name='status'>
            <option>End</option>
            <option>Continue</option>
            <option>~ End</option>
        </select>
        <input onclick='genJson()' type="button" value="Insert video" />
    </div>

    <div class='viddata'>
        <div></div>
    </div>
    
    <script src="/scripts/ckeditor/config.js"></script>
</section>

 

/* public/styles/backend/post.css */

.Post form input,
.Post form select,
.Post .form input,
.Post .form select{
    font: var(--body-font);
    width: 100%;
    padding: 1px 5px;
}

.Post form .ck-editor__editable{
    min-height: 350px;
    color: black;
}

.Post form .wrapper{
    margin-top: 0;
}

.Post form .wrapper,
.Post .form, 
.Post .viddata div{
    display: grid;
    grid-template-columns: 20% 32.5% 32.5% 15%;
}

.Post .viddata div{
    width: 100%;
}

.Post .viddata div p:hover{
    cursor: pointer;
    color: red;
}

.Post .viddata b,
.Post .viddata input,
.Post .viddata p{
    font: var(--body-font);
    padding: 5px;
    background: lightgrey;
    border: 1px solid grey;
    text-align: center;
}

.Post .viddata input{
    background: white;
}

 

// static/scripts/addCategory.js 

function getCategory(){
    const category = $('#category option:selected').text()
    $('select').prop('selectedIndex',0)
    let categories = $('[name=categories]').val()
    if(categories === ''){
        categories += category
    }else{
        categories += (`, ${category}`)
    }
    
    $('[name=categories]').val(categories)
}

 

// static/scripts/video.js

let episode = 0

const genJson = () => {
    let json = $('input[name="videos"]').val()
    if((json !== '')&&(json !== '[]')){
        json = JSON.parse(json)
        episode = json.length
    }else{
        episode = 0
    }

    const type = $('select[name="type"').val()
    const id = $('input[name="videoid"').val()
    const status = $('select[name="status"').val()
            
    let video = {
        type: type,
        id: id,
        status: status,
    }
        
    let success = false
    
    for(let v in video){
        if(video[v] === ''){
            alert('You need to fill the required field '+v)
            success = false
            break
        }else{
            success = true
        }
    }

    if(success){
        let json = $('input[name="videos"]').val()
        video = {
            type: type,
            id: id,
            status: status,
        }
        if((json === '')){
            json = JSON.stringify([video])
            $('input[name="videos"]').val(json)
        }else{
            json = JSON.parse(json)
            json.push(video)
            json = JSON.stringify(json)
            $('input[name="videos"').val(json)
        }

        let html =``

        for(let v in video){
            html += `<input value="${video[v]}" required />`
        }

        html += `<p title="Delete" onClick="deleteRow(event)" class="episode">${++episode}</p>`
        html = `<div>${html}</div>`
        
        if($('.viddata div').html() === ''){
            $('.viddata div').append('<b>Video type​</b>')
            $('.viddata div').append('<b>Video id​</b>')
            $('.viddata div').append('<b>Status</b>')
            $('.viddata div').append('<b>Part/Delete</b>')
        }
        
        $('.viddata div:eq(0)' ).after(html)
    }
}

function submitForm(e){
    e.preventDefault()
    
    const is_video = $('input[name="videos"').val()

    if((is_video !== '') && (is_video !== '[]')){
        episode = JSON.parse(is_video).length
        let videos = []
        let part = {}
        let key = {0:'type', 1:'id', 2:'status'}

        for(let v=1; v<=episode; v++){
            for(let j=0; j<3; j++){
                part[key[j]] = $(`.viddata div:eq(${v}) input:eq(${j})`).val()
            }

            videos.push({...part})
        }
    
        const json = JSON.stringify(videos)
        $('input[name="videos"').val(json)
    }
    
    document.forms["form"].submit()
}

function deleteRow(e) {
    e.target.parentElement.remove()
    
    let index = parseInt(e.target.innerHTML)
    index = index - 1
    let json = $('input[name="videos"]').val()
    json = JSON.parse(json)
    json.splice(index, 1)
    episode = json.length
    json = JSON.stringify(json)
    $('input[name="videos"').val(json)

    for(let v=episode; v>-1; v--){
        $('.episode').eq(v).html(episode-v)
    }
}

 

GitHub: https://github.com/Sokhavuth/Node.js_backend

Vercel: https://vercel.com/sokhavuth/node-js-backend