// routes/admin/post/[name]/[id].tsx

/** @jsx h */
import { h } from "preact";
import { Handlers, PageProps } from "$fresh/server.ts";
import VPost from '../../../../components/admin/post.tsx';
import CPost from "../../../../controllers/admin/post_edit_delete.ts";


export const handler: Handlers = {
    async GET(req, ctx){
        return await CPost.editDeletePost(req, ctx);
    },


    async POST(req, ctx) {
        return await CPost.updatePost(req, ctx);
    },
}


export default function Template(props: PageProps) {
    return (
        <VPost data={props.data} />
    )
}

 

// controllers/admin/post_edit_delete.ts

import { getCookies, deleteCookie } from "cookies";
import { setting, secret_key, myredis } from 'setting';
import { verify } from "jwt";
import postdb from "../../models/post.ts";


class PostEditDelete{
    async editDeletePost(req, ctx){
        const cookies = getCookies(req.headers);
        if((cookies)&&(cookies.session_id)){
            const jwt = await myredis.get(cookies.session_id);
            try{
                const payload = await verify(jwt, secret_key, "HS512")
                if(payload.user){
                    const config = setting();
                    config.page_title = "កែប្រែ​ការផ្សាយ";
                    config.username = payload.user.title;
                    config.count = await postdb.count();
                
                    if(ctx.params.name === 'edit'){
                        config.item = await postdb.getPost(ctx.params.id);
                    }else if(ctx.params.name === 'delete'){
                        const post = await postdb.getPost(ctx.params.id);
                        if((payload.user.role in {'Admin':1})||(payload.user.id === post.userid)){
                            await postdb.deletePost(ctx.params.id);
                        }
                        return new Response(undefined, { headers: {location: `/admin/post`}, status: 302 });
                    }else{
                        console.log('');
                    }
                    
                    config.items = await postdb.getPosts(config.post_amount);

                    return await ctx.render({"setting": config});
                }
            }catch(error){
                console.log(error)
                const resp = new Response(undefined, { headers: {location: `/login`}, status: 302 });
                deleteCookie(resp.headers, "session_id");
                return resp;
            }
        }

        return new Response(undefined, { headers: {location: `/login`}, status: 302 });
    }

    async updatePost(req, ctx){
        const cookies = getCookies(req.headers);
        if((cookies)&&(cookies.session_id)){
            const jwt = await myredis.get(cookies.session_id);
            try{
                const payload = await verify(jwt, secret_key, "HS512");
                const post = await postdb.getPost(ctx.params.id);
                if((post.userid === payload.user.id)||(payload.user.role in {'Admin':1,'Editor':1})){
                    if(ctx.params.name === 'edit'){
                        await postdb.updatePost(req, ctx.params.id);
                    }
                    return new Response(undefined, { headers: {location: `/admin/post`}, status: 302 });
                }
            }catch(error){
                console.log(error);
                const resp = new Response(undefined, { headers: {location: `/login`}, status: 302 });
                deleteCookie(resp.headers, "session_id");
                return resp;
            }
        }

        return new Response(undefined, { headers: {location: `/login`}, status: 302 });
    }
}

export default new PostEditDelete();

 

// models/post.ts

import { mydb } from "setting"

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

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

    async insertPost(req, user_id: string){
        const id = crypto.randomUUID()
        const formData = await req.formData()

        let categories: string[]

        if(formData.get("categories").includes(',')){
            categories = formData.get("categories").split(',')
        }else{
            categories = [formData.get("categories")]
        }
        
        const new_post = {
            id: id, 
            title: formData.get("title"),
            content: formData.get("content"),
            categories: categories,
            thumb: formData.get("thumb"),
            date: formData.get("datetime"),
            videos: formData.get("videos"),
            userid: user_id,
        }
 
        const posts = mydb.collection<PostSchema>("posts")
        await posts.insertOne(new_post)
    }

    async getPosts(amount: number, query={}){
        const posts = mydb.collection<PostSchema>("posts")
        return await posts.find(query).sort({date:-1,_id:-1}).limit(amount).toArray()
    }

    async getPost(post_id: string){
        const posts = mydb.collection<PostSchema>("posts")
        return await posts.findOne({id: post_id})
    }

    async updatePost(req, post_id: string){
        const formData = await req.formData()

        let categories: string[]

        if(formData.get("categories").includes(',')){
            categories = formData.get("categories").split(',')
        }else{
            categories = [formData.get("categories")]
        }

        const edited_post = {$set:{
            title: formData.get("title"),
            content: formData.get("content"),
            categories: categories,
            thumb: formData.get("thumb"),
            date: formData.get("datetime"),
            videos: formData.get("videos"),
        }}

        const posts = mydb.collection<PostSchema>("posts")
        await posts.updateOne({id: post_id}, edited_post)
    }

    async deletePost(post_id: string){
        const posts = mydb.collection<PostSchema>("posts")
        await posts.deleteOne({id: post_id})
    }

}

export default new Post()

 

// components/admin/post.tsx

/** @jsx h */
import { h } from "preact"
import { PageProps } from "$fresh/server.ts";
import Index from "./index.tsx";


function PostTsx(props: PageProps){
  const item = props.data.setting.item;
  let editor = ``
  let videos = ``

  if(item){
      editor = `
          <form action="/admin/post/edit/${item.id}" name="form" method="post" 
          onSubmit="submitForm(event)">
            <input type="text" name="title" value="${item.title}" required 
            placeholder="ចំណង​ជើង" />
            <textarea id="editor" name="content" >${item.content}</textarea>
            <input type="text" name="categories" value="${item.categories.toString()}" required 
            placeholder="បណ្តា​ជំពូក" />
            <div class="wrapper"> 
                <select id="category" onChange="getCategory()">
                  <option>ជ្រើសរើស​ជំពូក</option>
                  <option>News</option>
                  <option>Movie</option>
                  <option>Entertainment</option>
                  <option>Sport</option>
                </select>
                <input type="text" name="thumb" value="${item.thumb}" required 
                placeholder="តំណរ​ភ្ជាប់​រូប​តំណាង" />
                <input type="datetime-local" value="${item.date}" name="datetime" required />
                <input type="submit" value="បញ្ជូន" />
                <input type="hidden" name="videos" value='${item.videos}' />
            </div>
          </form>
      `
      videos = `
      let is_video = null
      is_video = JSON.parse('${item.videos}')
  
      if((is_video !== '') && (is_video !== '[]')){
        let html = ''
        let episode = is_video.length
      
        for(let video of is_video){
            html += "<div>"
            html += '<input value="'+video.type+'" required />'
            html += '<input value="'+video.id+'" required />'
            html += '<input value="'+video.status+'" required />'
            html += '<p title="Delete" onClick="deleteRow(event)" class="episode">'+(episode--)+'</p>'
            html += "</div>"
        }
  
        if($('.viddata div').html() === ''){
          $('.viddata div').append('<b>ប្រភេទ​</b>')
          $('.viddata div').append('<b>អត្តសញ្ញាណ​</b>')
          $('.viddata div').append('<b>ស្ថានភាព</b>')
          $('.viddata div').append('<b>ភាគ/លុប</b>')
        }
      
        $('.viddata div:eq(0)' ).after(html)
      }
      `
  }else{
      editor = `
          <form action="/admin/post" name="form" method="post" onSubmit="submitForm(event)">
            <input type="text" name="title" required placeholder="ចំណង​ជើង" />
            <textarea id="editor" name="content"></textarea>
            <input type="text" name="categories" required placeholder="បណ្តា​ជំពូក" />
            <div class="wrapper"> 
                <select id="category" onChange="getCategory()">
                  <option>ជ្រើសរើស​ជំពូក</option>
                  <option>News</option>
                  <option>Movie</option>
                  <option>Entertainment</option>
                  <option>Sport</option>
                </select>
                <input type="text" name="thumb" required placeholder="តំណរ​ភ្ជាប់​រូប​តំណាង" />
                <input type="datetime-local" name="datetime" required />
                <input type="submit" value="បញ្ជូន" />
                <input type="hidden" name="videos" value="" />
            </div>
          </form>
      `
      videos = ``
  }

  return(
      <section class="Post">
          <script src="/scripts/ckeditor/ckeditor.js"></script>
          <script src="/scripts/addCategory.js"></script>
          <script src="/scripts/video.js"></script>
          <link rel="stylesheet" href="/styles/admin/post.css" />

          <div dangerouslySetInnerHTML={{__html: `
              ${editor}
          `}}/>
          
          <script src="/scripts/ckeditor/config.js"></script>

          <div class="wrapper" >
              <select name="type">
                <option>YouTube</option>
                <option>YouTubePL</option>
                <option>Facebook</option>
                <option>OK</option>
              </select>
              <input type="text" name="videoid" required placeholder="អត្តសញ្ញាណ​វីដេអូ" />
              <select name="status">
                <option>ចប់</option>
                <option>នៅ​មាន​ត</option>
                <option>~ ចប់</option>
              </select>
              <div dangerouslySetInnerHTML={{__html: `
                  <input onclick="genJson()" type="submit" value="បញ្ចូល​វីដេអូ" />
              `}} />
          </div>

          <div class='viddata'>
            <div></div>
          </div>
          <script dangerouslySetInnerHTML={{__html: `${videos}`}}/>
      </section>
  )
}

export default function Post(props: PageProps){
  props.data.pageInner = PostTsx
  return(
    <Index data={props.data} />
  )
}

 

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

Deno Deploy: https://khmerweb.deno.dev/login