Search code examples
apostrophe-cms

Pre-defined widgets on Apostrophe CMS


I have been using Apostrophe CMS and it is great. What I want to do is have widgets pre-defined on the page without the user adding those widgets and for those widgets to have placeholder data. For example, I want apostrophe-images to already be on the page in an area and have a placeholder image. The user would then change the content to suit their needs. Is that possible?


Solution

  • A somewhat brittle way to accomplish this would be to hook into apostrophe-pages beforeInsert method and detect some condition you want to apply the sample data, then populate the appropriate properties with your sample JSON.

    1. Populate a page as you'd like to see it when created for the first time by an editor.

    2. Copy the JSON from your pre-populated properties from the database as Apostrophe would store it (db.aposDocs.find({slug: '/sample'} or whatever).

    3. Anywhere you see an _id field being copied from your sample, replace it with self.apos.utils.generateId() (don't replace id's of content you are actually referencing)

    4. in lib/modules/apostrophe-pages/index.js

    
    module.exports = {
      types: [
        {
          name: 'default',
          label: 'Default'
        }
        // .. other page types
      ],
      construct: function(self, options) {
        self.beforeInsert = function(req, page, options, callback) {
    
          ////////////
          // Should i pre populate this new page with sample data?
          if (page.type === 'default') {
            page.body = {
              "type" : "area",
              "items" : [
                {
                  "by" : "id",
                  "_id" : self.apos.utils.generateId(),
                  "pieceIds" : [
                    "ck2z5b8y0002xs6q7jcthp2ds"
                  ],
                  "relationships" : {
                    "ck2z5b8y0002xs6q7jcthp2ds" : {
                      "left" : null,
                      "top" : null,
                      "width" : null,
                      "height" : null,
                      "x" : null,
                      "y" : null
                    }
                  },
                  "type" : "apostrophe-images"
                },
                {
                  "_id" : self.apos.utils.generateId(),
                  "type" : "apostrophe-rich-text",
                  "content" : "<p><strong><em>Authors often misinterpret the mom as a surest quilt, when in actuality it feels more like a rimless jeep. Far from the truth, an iffy russia without porcupines is truly a sycamore of jessant farmers.</em></strong></p>\n\n<p> </p>\n"
                }
              ]
            }
          }
          return setImmediate(callback);
        };
      }
    };
    

    This would pre populate a page's body property with an area that contains an apostrophe-images widget and a apostrophe-rich-text widget.

    You could further clamp down this behavior by adding a field on your interesting page type that let an editor opt out of this behavior and check it on your beforeInsert condition.

    Again, this example is a bit rigid because you're hardcoding image piece ids into the beforeInsert .. You could further get fancy by running a query for images with a certain tag ('sample'), generating lorem ipsum text with external modules, etc. before populating your property.