In the dashboard, post page is a place where we can prepare to publish video(s) with or without text. So we need a rich text editor to write text content and to embed pictures into the text.

 

Among rich text editor, we can use CKEditor 5 for free. It is a very good text editor; we can build and download it at https://ckeditor.com/ckeditor-5/online-builder/

 

If we include CKEditor in a form with other input gadgets, the CKEDitor content will be automatically sent to the sever with other contents. And we can easily copy these contents to insert into our database.

 

However, we need to write some JavaScipt code to create video content or video playlist and to create a list of categories to be sent to the server.

 

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

<link rel="stylesheet" href="/static/styles/backend/index.css" />

<section class="Index">
    <header>
        <div class="inner region">
            <div class="page-title">{{ data["pageTitle"] }}</div>
            <form action="/admin/search" method="post">
                <select name="searchtype">
                    <option>Post</option>
                    <option>Category</option>
                    <option>User</option>
                </select>
                <input type="text" name="q" required />
                <input type="submit" value="Search" />
            </form>
            <div class="logout">
                {{ data["username"]}} | <a href="/">Home</a> | <a href="/login/logout">Logout</a>
            </div>
        </div>
    </header>

    <div class="main region">
        <div class="sidebar">
            <div class="inner">
                <a href="/admin/post"><img src="/static/images/movie.png" /></a>
                <a href="/admin/post">Post</a>

                <a href="/admin/category"><img src="/static/images/category.png" /></a>
                <a href="/admin/category">Category</a>

                <a href="/admin/upload"><img src="/static/images/upload.png" /></a>
                <a href="/admin/upload">Upload</a>

                <a href="/admin/user"><img src="/static/images/users.png" /></a>
                <a href="/admin/user">User</a>

                <a href="/admin/setting"><img src="/static/images/setting.png" /></a>
                <a href="/admin/setting">Settings</a>
            </div>
        </div>
        <div class="content">
            <%
            if("/post" in data["route"]):
                include("backend/post.tpl")
            end
            %>
        </div>
    </div>

    <div class="footer region">
        <div class="info">Total number of items:</div>
        <ul></ul>
        <div class="pagination">
            <img onclick="paginate(`{{ data['route'] }}`)" src="/static/images/load.png" />
        </div>

        <div class="credit">
            <a href="https://khmerweb.vercel.app/">&copy Khmer Web 2022</a>
        </div>
    </div>
</section>

 

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

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

<section class="Post">
    <form action="/admin/post" method="post" name="form" onSubmit="submitForm(event)">
        <input type="text" name="tilte" required placeholder="Post title" />
        <textarea name="content" id="editor"></textarea>
        <input type="text" name="categories" required placeholder="Categories" />
        <div class="wrapper">
            <select id="category" onChange="getCategory()">
                <option>Slect a category</option>
                <option>News</option>
                <option>Entertainment</option>
                <option>Movie</option>
            </select>
            <input type="text" name="thumb" required placeholder="Thumbnail" />
            <input type="datetime-local" name="datetime" required />
            <input type="submit" value="Publish" />
        </div>
        <input name='videos' value='' type='hidden' />
    </form>
    <div class="video-wrapper" >
        <select name="type">
          <option>YouTube</option>
          <option>YouTubePL</option>
          <option>Facebook</option>
          <option>OK</option>
        </select>
        <input type="text" name="videoid" required placeholder="Video id" />
        <select name="status">
          <option>End</option>
          <option>Continue</option>
          <option>~ End</option>
        </select>
        <input onclick="genJson()" type="submit" value="Insert video" />
    </div>

    <div class='viddata'>
        <div></div>
    </div>

</section>
<script src="/static/scripts/ckeditor/config.js"></script>

 

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

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

.Post input, .Post select{
    font: var(--body-font);
    padding: 2px 5px;
}

.Post input{
    width: 100%;
}

.Post form .wrapper, 
.Post .video-wrapper,
.Post .viddata div{
    display: grid;
    grid-template-columns: 20% 40% auto 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: 3px 5px;
    background: rgb(208, 216, 228);
    border: 1px solid grey;
    text-align: center;
    color: black;
}

.Post .viddata input{
    background: white;
}

 

// 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>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)
    }
}

 

// 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)
}

 

GitHub: https://github.com/Sokhavuth/TV-Channel 

Vercel: https://khmerweb-tv-channel.vercel.app/login