Search code examples
apostrophe-cms

Submit Piece with Permissions "False" not updated to Draft Mode. Only Available in Live Mode


This project is using Apostrophe-Workflow . Therefore , I created my own custom module for comment system with permissions false (Follow this comment system but adjust the piece myself for non-logged user submission). It was successful and submitted to database with non-logged user viewer. However , when I logged in and see pieces items submitted from non-logged user , it's empty/isn't there. And apostrophe-workflow asking me to commit without non-logged user submitted . To be clear , in Live Mode , I can see submitted comments. But in Draft Mode , nothing. And it prompts me to commit the changes (Which means to commit/delete non-logged user comments). Here is my piece and piece-widgets .

Here is an example for Live Mode (Successful submitted comment for non-logged user - Public) :

Live Mode

But When view in Draft Mode , you can't see the public comments and it asking for commit without public comments (When click commit , the button does not disappear) :

enter image description here

In modules/comments/index.js :

module.exports = {
    extend : 'apostrophe-pieces',
    name : 'comments',
    label : 'Comment Form',
    alias : 'commentForm',
    pluralLabel : 'All Comments',
    addFields : [
    {
        name: 'comments',
        label: 'Comments',
        type: 'array',
        sortify : true,
        schema: [
        {
            name: 'date',
            label: 'Date',
            type: 'date'
        },
        {
            name: 'readerName',
            label: 'Reader\'s Name',
            type: 'string',
            required: true
        }, {
            name: 'comment',
            label: 'Comment',
            type: 'string',
            textarea: true,
            required: true
        }]
    }],
    arrangeFields : [{
            name: 'comment',
            label: 'Comment',
            fields: ['comments']
        },
        {
            name: 'config',
            label: 'Comment Configuration',
            fields: ['title', 'slug', 'published', 'tags'],
            last: true
        }
    ],
    permissionsFields: false,
    construct: function (self, options) {

        self.addTask('update', 'Update Cursor for comment with data permissions false', function (apos, argv, callback) {
            var year = new Date().getFullYear();
            var month = (new Date().getMonth() < 12) ? "0" + new Date().getMonth() : new Date().getMonth();
            var day = (new Date().getDay() < 10) ? "0" + new Date().getDay() : new Date().getDay();
            var date = [
                [year],
                [month],
                [day]
            ];
            date.join('-');
            console.log("Array to string" , date.join('-'));

            const req = apos.tasks.getAnonReq();

            const idPiece = self.generate(1);

            self.apos.docs.getManager('comments').find(req)
                .criteria({
                    _id: idPiece
                })
                .sort({
                    updatedAt: 1
                })
                .log(true)
                .toArray(function (err, docs) {
                    if (err) {
                        return callback(null);
                    }
                    // fetch comment req.body
                    // generate new commentId

                    var comment = {
                        _id: self.apos.utils.generateId(),
                        date: date,
                        readerName: 'Reader Amin',
                        comment: 'Some comment'
                    };

                    // Hack method - Make it published when sucessful update
                    docs.published = true;

                    docs.forEach(doc => {
                        doc.comments.push(comment);
                        console.log("Success");
                        return self.apos.modules['comments']
                            .update(req, doc, {
                                permissions: false
                            }, function () {
                                console.log("Doc Update :", doc);
                                // Testing begins
                                self.apos.docs.getManager('comments').find(req)
                                    .criteria({
                                        _id: idPiece
                                    })
                                    .projection({
                                        title: 1,
                                        slug: 1,
                                        comments: 1,
                                        permissions: 1
                                    })
                                    .toArray((err, doc) => {
                                        if (err) {
                                            return setImmediate(callback);
                                        }
                                        doc.forEach(element => {
                                            console.log("element : ", element);
                                            return callback(null , element);
                                        })
                                    });
                                // End testing
                            });

                        // Then should update the module here using .update()
                    });
                });

        });

        self.addTask('list', 'List all comments with sorting', function (apos, argv, callback) {
            const req = apos.tasks.getAnonReq();
            return self.apos.modules['comments'].find(req)
                .sort({
                    updatedAt: 1
                })
                .projection({
                    title: 1,
                    type: 1,
                    slug: 1,
                    comments: 1,
                    permissions: 1
                })
                .toArray().then((doc) => {
                    // When anything output in array , you can do forEach
                    doc.forEach(element => {
                        // console.log("All comments", doc);
                        console.log("All comments", element);
                        return callback();
                    });
                });
        });

        // Create a post route /modules/comment-form/submit
        self.route('post' , 'submit' , function(req , res){
            // Get by pieces id
            self.apos.docs.getManager('comments').find(req)
            .criteria({
                _id: req.body.pieceId
            })
            .sort({
                createdAt : 1
            })
            .log(true)
            .toArray(function(err , docs){
                // fetch comment req.body
                // generate new commentId

                var comment = {
                    _id : self.apos.utils.generateId(),
                    date : req.body.date ,
                    readerName: req.body.readerName,
                    comment : req.body.comment,
                };

                // get docs . It will output as array.
                // therefore , it's easier to use forEach
                // Hack method - Make it published when sucessful update
                docs.published = true;

                docs.forEach(doc => {
                    doc.comments.push(comment);
                    self.apos.modules['comments']
                        .update(req, doc, {permissions : false}, function () {
                            console.log("Doc Update :" , doc);
                            return res.json({
                                status: 'okay'
                            });
                        });

                    // Then should update the module here using .update()
                });
            });
        });

    }
}

In my /modules/comments-widgets/public/js/always.js :

apos.define('comments-widgets' , {
    extend  :'apostrophe-widgets',
    construct : function(self , options){
        self.play = function($widget , data, options){
            // get form
            $widget.find("[data-button-submit]").on('click' , function(){
                var year = new Date().getFullYear();
                var month = (new Date().getMonth() < 12) ? "0" + new Date().getMonth() : new Date().getMonth();
                var day = (new Date().getDay() < 10) ? "0" + new Date().getDay() : new Date().getDay();
                var date = [
                    [year],
                    [month],
                    [day]
                ];
                date.join('-');
                var data = {
                    pieceId: $widget.find("form").attr("id"),
                    date :date.join('-'),
                    readerName: $widget.find("input[name='readerName']").val(),
                    comment: $widget.find("textarea[name='comment']").val()
                }

                var value = $widget.find("textarea[name='comment']").val();
                console.log("Comment Value" , value);
                $.ajax({
                    url : '/modules/comments/submit',
                    method : 'POST',
                    data : data,
                    success: function (result, status, xhr) {
                        console.log("Success POST" , result);
                    },
                    error: function (xhr, status, error){
                        console.log("Failed to POST");
                    }
                }).done(function(msg){
                    apos.change($widget);
                });

            });

        }
    }
})

In /modules/comments-widgets/views/widget.html :

{% for piece in data.widget._pieces %}
<form class="comment-widget" id="{{ piece._id }}" data-apos-pieces-submit-form>
<h4 class="Mont-Bold leave-comment">Leave a comment</h4>
    <input type="text" name="readerName" placeholder="Reader's Name">
    {# Must use fieldset with data.name on schema.name object #}
    <textarea name="comment" id="textarea-comment" cols="10" placeholder="Write a comment"></textarea>
<button class="submit" data-button-submit>Submit</button>
<div class="thank-you" data-apos-pieces-submit-thank-you>
    <h1>Done</h1>
</div>
</form>
<div class="comment-container">
    {% for piece in piece.comments %}
    <div class="comment-piece">
        <h4 class="reader-comment Mont-Heavy">{{ piece.readerName }} <span class="Mont-Regular" style="color : #0F58FF; font-size :14px ; letter-spacing : 0.20px; line-height : 19px;">- {{ piece.date | date("Do MMM YYYY") }}</span></h4>
        <p class="comment-paragraph Mont-Regular">{{ piece.comment }}</p>
    </div>
    {% endfor %}
</div>
{% endfor %}

Step By Step on how I create add Comment Piece on Page

1.Create/Add Comment Form & Add a Title Add Comment Form Create Comment Form

2.On Pieces-Pages , Select Comment Widget & Browse Individually Browse

3.Select my comment piece that created the title and DONE ! Select Comment


Updated

This code does not work . It somehow successful update but both live and draft are not updated . Here is my code using your solution :

self.route('post', 'submit', function (req, res) {
      // Get by pieces id

        // get docs . It will output as array.
        // therefore , it's easier to use forEach
        // Hack method - Make it published when sucessful update

        self.apos.docs.getManager('comments').find(req)
            .criteria({
                _id: req.body.pieceId
            })
            .sort({
                createdAt: 1
            })
            .log(true)
            .toArray(function (err, docs) {
                // fetch comment req.body
                // generate new commentId

                var comment = {
                    _id: self.apos.utils.generateId(),
                    date: req.body.date,
                    readerName: req.body.readerName,
                    comment: req.body.comment,
                };

                // get docs . It will output as array.
                // therefore , it's easier to use forEach
                // Hack method - Make it published when sucessful update
                docs.published = true;

                self.apos.docs.db.update({
                    workflowGuid: self.apos.launder.id(req.query.workflowGuid)
                }, {
                    $push: {
                        comments: comment
                    }
                }, {
                    multi: true
                }, function (err, lol) {
                    if (err) {
                        return res.json({
                            status: 'error'
                        })
                    }
                    console.log(lol);
                    return res.json({
                        status: 'ok'
                    })
                });

                // docs.forEach(doc => {
                //     doc.comments.push(comment);
                //     self.apos.modules['comments']
                //         .update(req, doc, {
                //             permissions: false
                //         }, function () {
                //             console.log("Doc Update :", doc);
                //             return res.json({
                //                 status: 'okay'
                //             });
                //         });

                //     // Then should update the module here using .update()
                // });
            });
    })

Solution

  • Well , I think Tom Boutell was right . Draft and Live mode is a different docs. However , I can't access my public comments data unless I do excludeTypes as below code. Now I understands , If you want to submit your form or comments or likes pieces WHILE using your Apostrophe-Workflow . In live mode , you can access the data if you set this on your app.js file :

        // WORKFLOW
        'apostrophe-workflow': {
          excludeTypes: ['comments' , 'likes' , 'contact-form'],
          alias: 'workflow'
        },

    enter image description here

    Then I can access all LIVE when trying to submit any form in LIVE mode ! So when using Apostrophe-Workflow , makes sure that you set any types or properties to exclude it for accessing data in LIVE MODE . If you submit your form in draft mode , you only get those data in draft mode , never in LIVE mode. And it will prompt you to submit/commit everytime you submit the form. You don't want that.