all files / addon/services/ route-metadata.js

100% Statements 44/44
100% Branches 30/30
100% Functions 10/10
100% Lines 44/44
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139                  11× 11×                                                       11×                 11×                   14×                             12×   11×     11× 14×                                           11× 11× 11×        
import dsl from '../utils/dsl-route-extend';
import Ember from 'ember';
 
export default Ember.Service.extend({
  _routes: {},
  _attributes: [
    'pageName'
  ],
  init() {
    this._routes = {};
    this._super();
  },
  /**
   * Set the default meta attributes that should be found
   * @param {string[]} attrs Array of strings of the meta property names
   * @return {null} not return value
   */
  setAttrs(attrs) {
    if (attrs && attrs.length) {
      this._attributes = attrs;
    } else {
      throw `Attrs could not be set, the array must contain at least one attribute`;
    }
  },
 
  /**
   * Register route metadata
   * @param {String} route Name of the route to register
   * @param {Object} options attributes for the route
   * @return {object} Returns the route metadata object
   */
  _registerRoute (route, options = {}) {
    if (this._routes[route]) {
      throw `Route ${route} has already been registered`;
    } else {
      this._routes[route] = options;
    }
    return this._routes[route];
  },
  /**
   * Find the parent of the route
   * @param {String} route Name of the route
   * @return {object} Parent of the route if found or null
   */
  _getParentRoute (route = '') {
    return route.substring(0, route.lastIndexOf('.')) || null;
  },
  /**
   * Create a object with only the attr you want
   * @param {Object} metaData metadata object you wish to edit
   * @param {Object} attrs attributes you would like to keep
   * @return {Object} edited metaData object
   */
  _removeUnnecessaryAttrs(metaData, attrs) {
    let obj = {};
    if (metaData) {
      attrs.forEach((key) => {
        obj[key] = metaData[key];
      });
    }
    return metaData ? obj : null;
  },
  /**
   * Get route by route Name
   * @param {String} route Name of route
   * @return {Object} route meta data object
   */
  getRoute(route) {
    return this._routes[route];
  },
  /**
   * Gets the meta data of a route using its name with optional parameter for specific metaData keys.
   * if a route is missing an attribute it will bubble up and take its parent's if applicable
   * Key Values that can be used in this.route()
   * @param {String} route The current route
   * @param {Object} attrs
   * e.g.
   * pageName {String} The name you would like to use for that route
   * pageType {String} The type of page it is, will inherit parents type if not specified
   * section {String} The section that this page belogs too, will inherit parents section if not specified
   * @return {Object} metaData found for specified Route
   */
  getMetaDataByRoute(route, attrs = this._attributes) {
    if (!route) {
      throw 'Route is Null or undefined';
    }
    let metaData = this.getRoute(route),
      parentRoute = this._getParentRoute(route),
      routesLeft = route.split('.');
    if (metaData) {
      let missingAttrs = [];
      attrs.forEach((key) => {
        if (!metaData[key]) {
          missingAttrs.push(key);
        }
      });
      if (missingAttrs.length && routesLeft.length > 1) {
        let parentMeta = this.getMetaDataByRoute(parentRoute, missingAttrs);
        missingAttrs.forEach((key) => {
          metaData[key] = parentMeta[key];
        });
      } else if (missingAttrs.length && routesLeft.length === 1) {
        throw `Route: ${route}. Can't complete metadata object. Missing ${this.optionsToString(missingAttrs)}`;
      }
    } else if (routesLeft.length > 1) {
      metaData = this.getMetaDataByRoute(parentRoute, attrs);
    }
    return this._removeUnnecessaryAttrs(metaData, attrs);
  },
  /**
   * Edit the meta data of a defined route
   * @param {String} route The route you wish to edit edit
   * @param {String} key Key of attribute to change
   * @param {Object} val Attribute to change
   * @return {undefined}
   */
  editRoute(route, key, val) {
    let metaData = this.getRoute(route);
    if (metaData) {
      metaData[key] = val;
    } else {
      throw `Route: ${route} was not found`;
    }
  },
  optionsToString(options) {
    let str = '';
    options.forEach((key) => {
      str += `${key}, `;
    });
    return str;
  },
  destroy() {
    this._routes = {};
    dsl.destroy();
    this._super();
  }
});