Building Blog Based on Al egg Framework: Editing Articles

Keywords: Javascript SQL MySQL git

Related articles

Blog Building Based on Al egg Framework (1) - Development Preparations
Building Blog Based on Al egg Framework (2) - Hello World
Building Blog Based on Al egg Framework (3) - Registration and Login
Blog Building Based on Al egg Framework (4) - Privilege Control
Building Blog Based on Al egg Framework (5) - Top Navigation Bar
Building Blog Based on Al egg Framework (6) - Browsing and Publishing Articles
Blog Building Based on Al egg Framework (7) - Editing Articles

git

https://github.com/ZzzSimon/e...
Just give me a compliment if you like it.

text

To edit an article, you must first get the original content of the article, and then put it on the edit page to show the user a "semi-finished" state, which can save the article again.

Page design

My article page

Edit page

functional design

  1. The title of my article page shows whether it is confidential or not, and there is an edit button after the title.
  2. Click the Edit button to go to the Edit page to re-edit the article.

Front-end code

myarticle.tpl My article page

We create the / app/view/article/myarticle.tpl page:

{% extends "parent.tpl" %}

{% block head %}
<!--Note: The template has been added bootstrap Relevant head-->
<title>My article</title>
{% endblock %}

{% block content %}
<h1>My article</h1>
<ul class="article-view view">
    {% for item in list %}
    <li class="item">
        <dl>
            <dt>
                <small style="color: red">{{helper.formatInvisible(item.invisible)}}</small>
                <a href="{{ item.url }}">{{ item.title }}</a>
                <a class="btn btn-link" href='/modify/{{item.id}}.htm'>edit</a>
            </dt>
            <dd><small>{{item.author}}</small> Last updated in {{helper.formatTime(item.update_time)}}  </dd>
            <dd></dd>
        </dl>
    </li>
    {% endfor %}
</ul>
{% endblock %}

Here we need to pay attention to one point:

  1. The two methods, helper.formatInvisible and helper.formatTime, serve to format the parameters returned by the back end. Of course, you can also execute these logic in the back-end code, but I prefer the back-end code to be as concise as possible. Formatting should belong to the front-end category. If the rendering of the template belongs to the back-end logic, then when I don't say ==.

About helper usage: https://eggjs.org/zh-cn/basic...

helper.js

const moment = require('moment');

//Time Formatting
exports.formatTime = time => moment(time).format('YYYY-MM-DD HH:mm:ss');
exports.formatInvisible = invisible => invisible===1 ? 'secrecy':'';

modify.tpl Edit Page

We create the / app/view/article/modify.tpl page:

{% extends "parent.tpl" %}

{% block head %}
<title>Editing articles</title>
<link rel="stylesheet" href="/public/editormd/editormd.css">
<script type="text/javascript" src="/public/editormd/editormd.js"></script>
{% endblock %}

{% block content %}
<div class="row">
    <div class="form-group">
        <label for="title">Title:</label>
        <input id="title" type="text" class="form-control" value="{{article.title}}">
    </div>
    <div class="checkbox ">
        <label>
            <input id="invisible" type="checkbox" >secrecy(After the selection<strong style="color: red">No display</strong>List of articles)
        </label>
    </div>
    <div id="detail" style="visibility: hidden">{{article.detail}}</div>
    <div class="form-group pull-right">
        <button id="save" class="btn btn-success ">Preservation</button>
    </div>
</div>
<div class="row">
    <div id="layout">
        <div id="test-editormd"></div>
    </div>
</div>
{% endblock %}

{% block script %}
<script type="text/javascript">

    $('#invisible').prop('checked','{{article.invisible}}' === '1' ? 'checked':'');
    const markdown = $('#detail').text();
    let testEditor = editormd("test-editormd", {
        width: "100%",
        height: 740,
        path: '/public/editormd/lib/',
        markdown: markdown,
        codeFold: true,
        saveHTMLToTextarea: true,    // Save HTML to Textarea
        searchReplace: true,
        htmlDecode: "style,script,iframe|on*",            // Open HTML tag parsing by default for security
        emoji: true,
        taskList: true,
        tocm: true,         // Using [TOCM]
        tex: true,                   // Turn on TeX language support for scientific formulas and turn off by default
        flowChart: true,             // Turn on flow chart support and turn off by default
        sequenceDiagram: true,       // Turn on Sequence/Sequence Diagram Support and turn off by default.
        imageUpload: true,
        imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
        imageUploadURL: "/edit/uploadPic?_csrf={{ ctx.csrf | safe }}",
        onload: function () {
            console.log('onload', this);
        }
    });

    $('#save').bind('click', function () {
        data = {
            article: {
                id: '{{article.id}}',
                title: $('#title').val(),
                detail: testEditor.getMarkdown(),
                invisible: $('#invisible').prop('checked')  ? 1:0
            }
        };

        $.post('/edit/modify?_csrf={{ ctx.csrf | safe }}', data, function (resp) {
            if (resp.flag === '1') {
                window.location.href = resp.url;
            }else {
                alert(resp)
            }
        })
    })
</script>
{% endblock %}

Backend code

ArticleController

Let's add the following:

    async myarticle(){
        const ctx = this.ctx;
        const articleList = await ctx.service.article.getArticleByAuthor(ctx.session.user.username);
        await ctx.render('article/myarticle.tpl', { list: articleList });
    }

EditController

Let's add the following:

    async modifyHtm(){
        const {ctx, service} = this;
        const article = await service.article.getArticleById(ctx.params.id);
        await ctx.render('article/modify.tpl',{article:article})
    }

    async modify(){
        const {ctx, service} = this;
        const article = ctx.request.body.article;
        const nowTime = new Date();
        article.update_time = nowTime;
        const result = await service.article.modify(article);
        if (result) {
            ctx.body = {flag:'1',msg:'Save successfully',url:'/article/'+article.id+'.htm'}
        }else {
            ctx.body = {flag:'0',msg:'Save failed'}
        }
    }

ArticleService

Let's add the following:

    async modify(article = {}){
        const res = await this.app.mysql.update('article',article);
        return res.affectedRows === 1;
    }

    async getArticleByAuthor(author){
        const sql = "SELECT id,url,title,author,update_time,invisible FROM article WHERE author = ?";
        const list =await this.app.mysql.query(sql, [author]);
        return list;
    }

    async getArticleById(id){
        const sql = "SELECT id,title,detail,invisible FROM article WHERE id = ?";
        const list =await this.app.mysql.query(sql, [id]);
        return list[0];
    }

Ending

If you find it useful after reading, please give the author a favorite! Thank you!

Posted by synted on Mon, 14 Oct 2019 00:11:37 -0700