// controllers/front/post.js

import config from '../../config.js'
import post from '../../views/front/post.jsx'
import postdb from '../../models/postdb.ts'

class Post{
    async getOneItem(req, res){
        this.config = await config()
        this.config.pageTitle = 'ទំព័រ​ការផ្សាយ'
        this.config.route = '/'

        let {item} = await postdb.getItem(req, 0)
        this.config.post = item

        const html = await post(this.config)
        res.send(html)
    }
}

export default new Post()

 

// models/postdb.js

interface PostSchema {
    _id: ObjectId;
    id: string; 
    title: string;
    content: string;
    categories: string[];
    thumb: string;
    postdate: string;
    video: string;
    userid: string;
}

class Postdb{
    async count(req, query={}){
        const posts = req.mydb.collection<PostSchema>("posts")
        return await posts.countDocuments(query)
    }

    async insertPost(req){
        const id = Date.now() + Math.round(Math.random() * 1E9).toString()

        if(req.body.categories.includes(',')){
            var categories: string[] = req.body.categories.split(',')
        }else{
            var categories: string[] = [req.body.categories]
        }

        const user_id = await req.session.get('user-id')
        
        let newPost = {
            id: id, 
            title: req.body.title,
            content: req.body.content,
            categories: categories,
            thumb: req.body.thumb,
            postdate: req.body.datetime,
            video: req.body.video,
            userid: user_id,
        }
 
        const posts = req.mydb.collection<PostSchema>("posts")
        await posts.insertOne(newPost)
    }

    async getItem(req, amount, query={}){
        const posts = req.mydb.collection<PostSchema>("posts")
        let item = null
        let items = null

        if(req.params.id){
            item = await posts.findOne({id: req.params.id})
        }

        if(amount){
            items = await posts.find(query).sort({date:-1,_id:-1}).limit(amount).toArray()
        }
        
        return {item:item, items:items}
    }

    async editPost(req){
        if(req.body.categories.includes(',')){
            var categories: string[] = req.body.categories.split(',')
        }else{
            var categories: string[] = [req.body.categories]
        }

        let editPost = {$set:{
            title: req.body.title,
            content: req.body.content,
            categories: categories,
            thumb: req.body.thumb,
            postdate: req.body.datetime,
            video: req.body.video,
        }}
        
        const posts = req.mydb.collection<PostSchema>("posts")
        await posts.updateOne({id: req.params.id}, editPost)
    }

    async deletePost(req){
        const posts = req.mydb.collection<PostSchema>("posts")

        if(req.params.id){
            var item = await posts.findOne({id: req.params.id})
        }

        const user_id = await req.session.get('user-id')

        const user_role = await req.session.get('user-role')
        if(user_role in {'Admin':1,'Editor':1,'Author':1}){
            if((user_role === 'Admin') || (user_id === item.userid)){
                await posts.deleteOne({id: req.params.id})
            }
        }
    }
}

export default new Postdb

 

// views/front/post.jsx

/** @jsx h */
import { h, renderSSR } from "../../deps.ts"

function PostJsx(props){


    return(

        <html>
        <head>
          <meta charset="UTF-8"/>
          <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
          <title>{props.config.siteTitle} | {props.config.pageTitle}</title>
          <link href="/images/siteLogo.png" rel="icon" />
          <link href="/styles/base.css" rel="stylesheet" />
          <link href="/fonts/setup.css" rel="stylesheet" />
          <script src="/scripts/jquery.js"></script>
          <link rel="stylesheet" href="/styles/front/home.css" />
          <link rel="stylesheet" href="/styles/front/menu.css" />
          <link rel="stylesheet" href="/styles/front/single.css" />
          <script src="/scripts/setPlayer.js"></script>
        </head>
        <body>
        <section class="Home">
        <header>
              <div class="inner region">
                <div class="title"><a href="/">{props.config.siteTitle}</a></div>
                <form action="/search" method="post">
                  <select name='category'>
                    <option>ការផ្សាយ</option>
                  </select>
                  <input type="text" name="q" required placeholder="Search" />
                  <input type="submit" value="ស្វែងរក" />
                </form>
                <div class="login"><a href="/login">ចូល​ក្នុង</a> | <a href="#register">ចុះ​ឈ្មោះ</a></div>
              </div>
            </header>

            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
            <div class="menu">
              <div class="innner region">
              <div class="topnav" id="myTopnav">
                <a href="/" class="active">Home</a>
                <a href="#news">News</a>
                <a href="#contact">Contact</a>
                <a href="#about">About</a>
                <span dangerouslySetInnerHTML={{__html: `
                    <a href="javascript:void(0);" class="icon" onclick='myFunction()'>
                      <i class="fa fa-bars"></i>
                    </a>
                `}}/>
              </div>
              </div>
            </div>
            <script dangerouslySetInnerHTML={{__html: `
              function myFunction() {
                var x = document.getElementById("myTopnav");
                if (x.className === "topnav") {
                x.className += " responsive";
                } else {
                x.className = "topnav";
                }
              }
            `}}/>

            <div class="main region">
                <div class="content">
                <div class="Post">
                    <div class="title">{props.config.post.title}</div>
                    <div class="date">
                        {(new Date(props.config.post.postdate)).toLocaleDateString('it-IT')}
                    </div>
                    <div class="category">ជំពូកៈ {(props.config.post.categories).toString()}</div>
                    
                <div class="video">
                    <div class="screen"></div>
                    <div class="playlist"></div>
                </div>

                <script dangerouslySetInnerHTML={{__html: `
                    const videos = JSON.parse('${ props.config.post.video }')
                    videos.reverse()
                    
                    let clicked = 0
                    
                    for(let index in videos){
                        let ending = ''
                        if(index == videos.length-1){
                            ending = videos[index].status
                        }

                        let title = videos[index].title
                        
                        let html = '<div id="part'+index+'" class="part" onClick="setScreen(videos['+index+'],'+index+',true)">${ props.config.post.title } ភាគ​ '+(++index)+' '+ending+'</div>'
                        $('.playlist').append(html)
                    }

                    setScreen(videos[0],0,false)
                    `}}/>

                    <div class="text-content" dangerouslySetInnerHTML={{__html: `
                        ${props.config.post.content}
                    `}}/>
                </div>
                </div>
                <div class="sidebar">Sidebar</div>
            </div>
        </section>
        </body>
      </html>
    )
}

function Post(config){
    const str = renderSSR(<PostJsx config={config} />)
    const html = `<!DOCTYPE html>${str}`
    return html
  }
  
  export default Post

 

//asset/js/setPlayer.js

function setScreen(entry,id,click){
    if(entry['type'] == 'OK'){
        var url = `//ok.ru/videoembed/${entry['id']}`
    }else if(entry['type'] == 'YouTube'){
        var url = `https://www.youtube.com/embed/${entry['id']}`
    }else if(entry['type'] == 'YouTubePlaylist'){
        var url = `https://www.youtube.com/embed/videoseries?list=${entry['id']}`
    }else if(entry['type'] === "Facebook"){
        var url = `https://www.facebook.com/watch/?v=${entry['id']}`
    }else if(entry['type'] === "GoogleDrive"){
        var url = `https://docs.google.com/file/d/${entry['id']}/preview`
    }else if(entry['type'] === "Vimeo"){
        var url = `https://player.vimeo.com/video/${entry['id']}`
    }else if(entry['type'] === "Dailymotion"){
        var url = `https://www.dailymotion.com/embed/video/${entry['id']}`
    }

    if(entry['type'] !== 'Facebook'){
        var iframe = `<div>
        <iframe id="video-player" src="${url}" frameborder="0" allowfullscreen></iframe>
        </div>`;
      }else{
        var iframe = `<div class="fb-video" data-href="${url}" data-width="auto" data-show-captions="true"></div>`;
    }

    if(click){
        $('.Post .video .playlist #part'+clicked)
            .css({'background':'var(--background-light)','color':'black'})
    }
    $('.Post .video .playlist #part'+id)
        .css({'background':'var(--background)','color':'white'})


    $('.Post .video .screen').html(iframe)
    if((entry['type'] === "Facebook")&&(fb_api)){
        FB.XFBML.parse()
    }  

    clicked = id
}

 

/* static/styles/front/single.css */

.Post .title{
    font: 25px/1.5 Oswald, Limonf3;
    padding-bottom: 20px;
}

.Post .category{
    padding-bottom: 30px;
}

.Post .video{
    padding-bottom: 20px;
}

.Post .video .screen{
    position: relative;
    padding-top: 56.25%;
}

.Post .video .screen iframe{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.Post .video .playlist{
    max-height: 361px;
    overflow: auto;
}

.Post .video .playlist .part{
    padding: 10px;
    font: bold 16px/1.5 Courgette, HandWriting;
    background: lightgrey;
    border: 1px solid grey;
    border-top: none;
    color: rgb(71, 71, 71);
}

.Post .video .playlist .part:first-child{
    border-top: 1px solid grey;
}

.Post .video .playlist .part:hover{
    cursor: pointer;
    opacity: .7;
}

 

GitHub: https://github.com/Sokhavuth/khmerweb-deno

Deno Deploy: https://khmerweb-blog.deno.dev