Rob McGlade
Rob McGlade

Reputation: 36

Apostrophe-cms cloning a pieces area into another non pieces area

I have an apos pieces collection called templates and in that schema I have an apos area for other widgets, etc.

I have created a standard non-pieces widget with a joinbyone that can pick the area but I can't seem to find a way to clone the items in the pieces area into the non pieces area in the widget.

The idea being I can create templates as pieces and when they are selected I create a copy of that template into an anonymous area so the pieces-area is unchanged. Any help would be greatly appreciated

Upvotes: 0

Views: 86

Answers (2)

alexbea
alexbea

Reputation: 1370

Widgets don't have their own afterSave type event handler because it's not really them that are saved. It's the document that they belong to. You could use the afterSave event handler on the doc type to:

  1. See if the saved document include that widget in an area
  2. See if the template widget has a populated join
  3. Copy the area data from the joined document to the widget area
  4. Clear the widget's join field (so it can see if a new template was selected in the future)

Step 3b is really to update the _id properties of all the widgets in the copied areas. Area widgets have unique _ids for when they are moved or copied, so those should be newly generated for this new context. The cuid utility is useful for that.

This is an unusual case, but it's certainly interesting. I think that might work if you need to do it. And it keeps the data correct rather than doing data work in the template.

Upvotes: 1

Rob McGlade
Rob McGlade

Reputation: 36

I couldn't seem to get a handle on the data server side so I used a template helper to post the data back in, then copied the area from the piece and ran the items through a re-dot-path/docid routine. Works a treat so far!

template.html

 {% import "macros/widgets.html" as widget %}
{%if data.widget%}

{% set section=apos.sectionTemplate.copyme(data.widget) %}

{%endif%}

{{ widget.postWidget(section, 'newnsection') }}

widget.js

const apos = require("apostrophe");

module.exports = {
  extend: 'apostrophe-widgets',
  label: 'Section Template',
  alias: 'sectionTemplate',
  defer: true,
  addFields: [
    {
      name: '_nsection',
      type: 'joinByOne',
      withType: 'templateSections',
      label: 'Template',
      required: true,
      idField: 'id',
      filters: {
        projection: {
          title: 1,
          nsection: 1
        }
      }
    }
    ,
    {
      name: 'newnsection',
      type: 'area',
      label: 'Section',
      contextual: true,
      def: ''
    }
  ],

  construct: function (self, options) {

    self.addHelpers({
      copyme: function (data) {
        if (data.newnsection.items.length == 0) {
          data.newnsection.items = data._nsection.nsection.items
          area = recalcDotPathsAreas(data.newnsection);

          function recalcDotPathsAreas(area) {
            var docId = area._docId;
            var dotPath = area._dotPath;
            area.items.forEach(stlevel);
            function stlevel(value, index, array) {
              var widgetDotPath = dotPath + '.items.' + index;
              try {
                var $widget = value;
                value.__docId = docId;
                value.__dotPath = widgetDotPath;
                recalcDotPathsAreasWidget(value, docId, widgetDotPath);
              } catch (e) {
              }
            };
            return area
          };

          function recalcDotPathsAreasWidget($widget, docId, dotPath) {
            $widget.items.forEach(sclevel);
            function sclevel(value, index, array) {
              var $area = value;
              var areaDocId = value._id;
              if ((areaDocId !== docId) && areaDocId && (areaDocId.substring(0, 1) === 'w')) {
                value._id = docId;
                areaDocId = docId;
              }
              if (areaDocId === docId) {
                var areaDotPath = value._dotPath;
                if (areaDotPath) {
                  var components = areaDotPath.split('.');
                  var name = components.pop();
                  value._dotPath = dotPath + '.' + name;
                  recalculateDotPathsInArea(value);
                }
              }
            };
          };
        }
        return data;
      }
    });

    var superPushAssets = self.pushAssets
    self.pushAssets = function () {
      superPushAssets()
      //  self.pushAsset('stylesheet', 'smart-section', {when: 'always'})
      self.pushAsset('script', 'always', { when: 'always' })
    }

  }

}

Upvotes: 0

Related Questions