Usually, programming database is the process of Create, Read, Update, and Delete data in the database. We call these four fundamental programming approaches as CRUD.

 

We have been already using one database programming approach when we created posts in the dashboard. Now, we will use “R” approach to read or pull posts from MongoDB database. For that, we are going to use HTTP GET method on the route “users/post” to read or pull posts from the database. As the HTTP GET method on the route “users/post” was already defined, what we have to do is to add a statement in the getPage method in the controller Post class to achieve this goal.

 

We will send  the posts we pulled from the database to the template page post.jsx for it to forward this data to the index.jsx page to create a number of post items to display in the footer.

 

// controllers/users/post.js

import post from "../../views/users/post.jsx";
import postdb from "../../models/post.ts";


class Post{
    async getPage(req, res){
        const config = req.mysetting();
        config.page_title = "Post Page";
        config.route = "/users/post";
        config.username = (await req.mysession.get("user")).title;
        config.type = "post";
        config.count = await postdb.count(req);
        config.items = await postdb.getPosts(req, config.dasPostAmount);
        
        const html = await post(config);
        res.send(html);
    }

    async createPost(req, res){
        if((await req.mysession.get("user")).role in {'Admin':1,'Editor':1,'Author':1}){
            await postdb.createPost(req);
        }

        res.redirect("/users/post");
    }
}


export default new Post();

 

// models/post.ts


interface PostSchema {
    _id: ObjectId;
    id: string; 
    title: string;
    content: string;
    categories: string[];
    location: string;
    payable: string;
    postdate: Date;
    closedate: string;
    userid: string;
    thumb: string;
}

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

    async createPost(req){
        const id = crypto.randomUUID();

        let categories: string[];

        if(req.body.categories.includes(',')){
            categories = req.body.categories.split(',');
        }else{
            categories = [req.body.categories]
        }
        
        const new_post = {
            id: id, 
            title: req.body.title,
            content: req.body.content,
            categories: categories,
            location: req.body.location,
            payable: req.body.payable,
            postdate: new Date(),
            closedate: req.body.datetime,
            userid: (await req.mysession.get("user")).id,
            thumb: req.body.thumb,
        }
 
        const posts = req.mydb.collection<PostSchema>("posts")
        await posts.insertOne(new_post)
    }

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

export default new Post();

 

// views/users/index.jsx

/** @jsx h */
import { h } from "../../deps.ts";
import Base from "../base.jsx";


function IndexJsx(props){
    const Page = props.data.pageInner;
    const items = props.data.items;
    
    const listItems = items.map((item) =>
    <li>
      <a class="thumb" href={`/post/${item.id}`}>
        <img src={item.thumb} />
      </a>
      <div class="title">
        <a href={`/${props.data.type}/${item.id}`}>{item.title}</a>
        <div>{(new Date(item.closedate)).toLocaleDateString('it-IT')}</div>
      </div>
      <div class="edit">
        <a href={`/users/${props.data.type}/edit/${item.id}`}><img src={`/images/edit.png`} /></a>
        <a href={`/users/${props.data.type}/delete/${item.id}`}><img src={`/images/delete.png`} /></a>
      </div>
    </li>
    )
    
    return(
        <section class="Index">
            <link rel="stylesheet" href="/css/users/index.css" />
            <header>
                <div class="inner region">
                    <div class="title">{props.data.page_title}</div>
                    <form action="/admin/search" method="post">
                        <select name="admin_search">
                            <option>All</option>
                            <option>Category</option>
                        </select>
                        <input type="text" name="admin_q" required placeholder="Search" />
                        <input type="submit" value="Search" />
                    </form>
                    <div class="logout"><span>{props.data.username}</span> | <a href="/">Home</a> | <a href="/users/logout">Logout</a></div>
                </div>
            </header>

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

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

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

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

                        <a href="/users/setting"><img src="/images/setting.png" /></a>
                        <a href="/users/setting">Setting</a>
                    </div>
                </div>
                <div class="content">
                    <Page data={props.data} />
                </div>
            </div>

            <div class="footer region">
                <div class="info">Total amount of items: {props.data.count}</div>
                <ul class="list">
                    { listItems }
                </ul>
                <div class="pagination" dangerouslySetInnerHTML={{__html: `
                    <img onclick="paginate('${props.data.route}')" src="/images/load-more.png" />
                `}}/>
            
                <div class="credit">&copy; <a href="https://khmerweb.vercel.app/">Khmer Web 2022</a></div>
            </div>
        </section>
    )
}

export default function Index(props){
    props.data.page = IndexJsx;
    return(<Base data={ props.data } />);
}

 

GitHub: https://github.com/Sokhavuth/opine-job 

Deno Deploy: https://khmerweb-job.deno.dev/users/post