Liferay.Loader.define("portal-portlet-bridge-soy-impl@3.0.18/router/SoyPortletRouter", ['module', 'exports', 'require', 'frontend-js-web', 'frontend-js-metal-web$metal-dom', 'frontend-js-metal-web$metal-path-parser', 'frontend-js-metal-web$metal-router', 'frontend-js-metal-web$metal-state', 'frontend-js-spa-web$senna'], function (module, exports, require) {
  var define = undefined;
  var global = window;
  {
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.default = void 0;

    var _frontendJsWeb = require("frontend-js-web");

    var _metalDom = _interopRequireDefault(require("frontend-js-metal-web$metal-dom"));

    var _metalPathParser = require("frontend-js-metal-web$metal-path-parser");

    var _metalRouter = _interopRequireDefault(require("frontend-js-metal-web$metal-router"));

    var _metalState = _interopRequireDefault(require("frontend-js-metal-web$metal-state"));

    var _senna = require("frontend-js-spa-web$senna");

    function _interopRequireDefault(obj) {
      return obj && obj.__esModule ? obj : { default: obj };
    }

    function _typeof(obj) {
      "@babel/helpers - typeof";
      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
        _typeof = function _typeof(obj) {
          return typeof obj;
        };
      } else {
        _typeof = function _typeof(obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
      }return _typeof(obj);
    }

    function _get(target, property, receiver) {
      if (typeof Reflect !== "undefined" && Reflect.get) {
        _get = Reflect.get;
      } else {
        _get = function _get(target, property, receiver) {
          var base = _superPropBase(target, property);if (!base) return;var desc = Object.getOwnPropertyDescriptor(base, property);if (desc.get) {
            return desc.get.call(receiver);
          }return desc.value;
        };
      }return _get(target, property, receiver || target);
    }

    function _superPropBase(object, property) {
      while (!Object.prototype.hasOwnProperty.call(object, property)) {
        object = _getPrototypeOf(object);if (object === null) break;
      }return object;
    }

    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }

    function _defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
      }
    }

    function _createClass(Constructor, protoProps, staticProps) {
      if (protoProps) _defineProperties(Constructor.prototype, protoProps);if (staticProps) _defineProperties(Constructor, staticProps);return Constructor;
    }

    function _possibleConstructorReturn(self, call) {
      if (call && (_typeof(call) === "object" || typeof call === "function")) {
        return call;
      }return _assertThisInitialized(self);
    }

    function _getPrototypeOf(o) {
      _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
      };return _getPrototypeOf(o);
    }

    function _assertThisInitialized(self) {
      if (self === void 0) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
      }return self;
    }

    function _inherits(subClass, superClass) {
      if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function");
      }subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } });if (superClass) _setPrototypeOf(subClass, superClass);
    }

    function _setPrototypeOf(o, p) {
      _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
        o.__proto__ = p;return o;
      };return _setPrototypeOf(o, p);
    }

    /**
     * Specific Router implementation on top of metal-router to target the specific
     * SoyPortlet architecture.
     *
     * Some added features on top of SPA in Liferay Portal are:
     *  - Support for friendly urls (with patterns)
     *  - Pure SPA navigation after first render (json)
     * 	- Deferred view loading
     *  - Global server error management
     */
    var SoyPortletRouter = /*#__PURE__*/function (_State) {
      _inherits(SoyPortletRouter, _State);

      /**
       * @inheritDoc
       */
      function SoyPortletRouter(config) {
        var _this;

        _classCallCheck(this, SoyPortletRouter);

        _this = _possibleConstructorReturn(this, _getPrototypeOf(SoyPortletRouter).call(this, config));

        _this.initializeRoutes_();

        var router = _this.getRouter();

        router.ignoreQueryStringFromRoutePath = false;
        router.on('endNavigate', _this.onEndNavigate_.bind(_assertThisInitialized(_this)));
        router.dispatch();
        var handler = Liferay.once('beforeScreenFlip', function () {
          router.dispose();
          _metalRouter.default.routerInstance = null;
          _metalRouter.default.activeRouter = null;
        });
        Liferay.once("".concat(_this.portletId, ":portletRefreshed"), function () {
          handler.detach();
          router.dispose();
          _metalRouter.default.routerInstance = null;
          _metalRouter.default.activeRouter = null;
        });
        return _this;
      }
      /**
       * Gets the currently active component from the current router.
       * @return {Component}
       * @see {Router.getActiveComponent}
       */

      _createClass(SoyPortletRouter, [{
        key: "getActiveComponent",
        value: function getActiveComponent() {
          return _metalRouter.default.getActiveComponent();
        }
        /**
         * Gets the state for the currently active component.
         * @return {Object}
         * @see {Router.activeState}
         */

      }, {
        key: "getActiveState",
        value: function getActiveState() {
          return _metalRouter.default.activeState;
        }
        /**
         * Returns the single Senna.js application that handles all `Router`
         * instances, creating it if it hasn't been built yet.
         * @return {!App}
         * @see {Router.router}
         */

      }, {
        key: "getRouter",
        value: function getRouter() {
          return _metalRouter.default.router();
        }
        /**
         * Creates the default routing screen for navigation and assigns it as the
         * Router.defaultScreen value
         * @protected
         */

      }, {
        key: "createDefaultScreen_",
        value: function createDefaultScreen_() {
          var instance = this;
          /**
           * Special screen that uses attempts to load the controller in a deferred
           * way after retrieving the new renderState.
           */

          var DeferredComponentScreen = /*#__PURE__*/function (_Router$defaultScreen) {
            _inherits(DeferredComponentScreen, _Router$defaultScreen);

            /**
             * @inheritDoc
             */
            function DeferredComponentScreen(router) {
              _classCallCheck(this, DeferredComponentScreen);

              return _possibleConstructorReturn(this, _getPrototypeOf(DeferredComponentScreen).call(this, router));
            }
            /**
             * Runs before updating the history path to remove the special
             * params added to the URL when calculating the fetch version of
             * the provided one
             * @param {*} args
             * @return {string} The stringified URL
             */

            _createClass(DeferredComponentScreen, [{
              key: "beforeUpdateHistoryPath",
              value: function beforeUpdateHistoryPath() {
                for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
                  args[_key] = arguments[_key];
                }

                var redirect = _senna.RequestScreen.prototype.beforeUpdateHistoryPath.apply(this, args);

                var uri = new URL(redirect, window.location.origin);
                uri.searchParams.delete('p_p_lifecycle');
                uri.searchParams.delete("".concat(instance.portletNamespace, "pjax"));
                uri.searchParams.delete("".concat(instance.portletNamespace, "soy_route"));

                if (uri.searchParams.has("".concat(instance.portletNamespace, "no_p_p_id"))) {
                  uri.searchParams.delete('p_p_id');
                  uri.searchParams.delete("".concat(instance.portletNamespace, "no_p_p_id"));
                }

                return uri.toString();
              }
              /**
               * Overrides the default ComponentScreen flip method to continue
               * only when the controller for the path and all its dependencies
               * have been successfully loaded. If the load fails , then it falls
               * back to an ordinary full page navigation.
               * @return {Promise} A promise to be resolved once the path
               * and its needed controllers have been successully loaded or rejected
               * otherwise
               */

            }, {
              key: "flip",
              value: function flip() {
                var _this2 = this;

                var loadedState = _get(_getPrototypeOf(DeferredComponentScreen.prototype), "maybeParseLastLoadedStateAsJson", this).call(this);

                var deferred = new Promise(function (resolve, reject) {
                  Liferay.Loader.require(loadedState.javaScriptLoaderModule, function (module) {
                    _get(_getPrototypeOf(DeferredComponentScreen.prototype), "maybeRedirectRouter", _this2).call(_this2);

                    var component = module.default;
                    component.RENDERER.setInjectedData(loadedState._INJECTED_DATA_);
                    _this2.router.component = component;
                    resolve();
                  }, function (error) {
                    return reject(error);
                  });
                });
                return deferred.then(function () {
                  return _get(_getPrototypeOf(DeferredComponentScreen.prototype), "flip", _this2).call(_this2);
                });
              }
            }]);

            return DeferredComponentScreen;
          }(_metalRouter.default.defaultScreen);

          DeferredComponentScreen.SYNC_UPDATES = true;
          _metalRouter.default.defaultScreen = DeferredComponentScreen;
        }
        /**
         * Creates a Router for a given route. If the route is the current browser
         * path, it automatically sets the current state as data and disables
         * fetching to avoid an extra request.
         * @param {object} route An object with the route information
         * @param {Function=} pathFn The path matcher to be used by the router
         * @protected
         * @return {Router}
         */

      }, {
        key: "createRouter_",
        value: function createRouter_(route, pathFn) {
          var config = {
            cacheable: false,
            element: this.element,
            fetch: true,
            fetchUrl: this.getFetchUrl_.bind(this),
            path: pathFn || this.matchPath_.bind(this, route.mvcRenderCommandName),
            portletNamespace: this.portletNamespace,
            route: route
          };

          try {
            if (config.path(_senna.utils.getCurrentBrowserPath())) {
              config.data = this.context;
            }
          } catch (e) {}

          return new _metalRouter.default(config, this.portletWrapper);
        }
        /**
         * Converts a regular url to its fetch counterpart for spa navigation
         * @param {string} url The regular url
         * @protected
         * @return {string} The equivalent fetch url
         */

      }, {
        key: "getFetchUrl_",
        value: function getFetchUrl_(url) {
          var uri = new URL(url, window.location.origin);

          if (uri.searchParams.has('p_p_lifecycle')) {
            var original_p_p_lifecyle = uri.searchParams.get('p_p_lifecycle');
            uri.searchParams.set("".concat(this.portletNamespace, "original_p_p_lifecycle"), original_p_p_lifecyle);
          }

          uri.searchParams.set('p_p_lifecycle', '2');
          uri.searchParams.set("".concat(this.portletNamespace, "pjax"), true);
          uri.searchParams.set("".concat(this.portletNamespace, "soy_route"), true);

          if (!uri.searchParams.has('p_p_id')) {
            uri.searchParams.append('p_p_id', this.portletId);
            uri.searchParams.append("".concat(this.portletNamespace, "no_p_p_id"), true);
          }

          return uri.toString();
        }
        /**
         * Creates a path matcher function for a friendly url pattern
         * @param {string} pattern Regex pattern for the friendly url
         * @param {string} mapping Mapping configuration for friendly urls
         * @protected
         * @return {Function} A matcher function
         */

      }, {
        key: "getPathFunctionForFriendlyURLPattern_",
        value: function getPathFunctionForFriendlyURLPattern_(pattern, mapping) {
          var _this3 = this;

          return function (url) {
            var mappingPrefix = "/".concat(mapping);

            if (_this3.friendlyURLPrefix) {
              mappingPrefix = "/-".concat(mappingPrefix);
            }

            var uri = new URL(url, window.location.origin);
            var pathname = uri.pathname;
            var currentPath = pathname.substring(pathname.lastIndexOf(mappingPrefix));
            return currentPath === "".concat(mappingPrefix).concat(pattern);
          };
        }
        /**
         * Creates a path matcher function for a friendly url route
         * @param {string} friendlyURLRoute The friendly url we want to create a
         * matcher for
         * @protected
         * @return {Function} A matcher function
         */

      }, {
        key: "getPathFunctionForFriendlyURLRoute_",
        value: function getPathFunctionForFriendlyURLRoute_(friendlyURLRoute) {
          return this.getPathFunctionForOverriddenParameters_(friendlyURLRoute.overriddenParameters) || this.getPathFunctionForFriendlyURLPattern_(friendlyURLRoute.pattern, this.friendlyURLMapping);
        }
        /**
         * Creates a path matcher function for a pattern-metal-router implicit param
         * @param {object} overriddenParameters Object with the friendly url implicit
         * parameters
         * @protected
         * @return {Function} A matcher function
         */

      }, {
        key: "getPathFunctionForOverriddenParameters_",
        value: function getPathFunctionForOverriddenParameters_(overriddenParameters) {
          var pathFunctionForOverriddenParameters_;

          if (overriddenParameters['pattern-metal-router']) {
            var url = "(.*)/".concat(this.friendlyURLMapping).concat(overriddenParameters['pattern-metal-router']);
            var regex = (0, _metalPathParser.toRegex)(url);
            pathFunctionForOverriddenParameters_ = regex.test.bind(regex);
          }

          return pathFunctionForOverriddenParameters_;
        }
        /**
         * Returns wether the requested MVCRenderCommandName is known or not.
         * @param {string} mvcRenderCommandName The command name
         * @protected
         * @return {boolean}
         */

      }, {
        key: "hasMVCRenderCommandName",
        value: function hasMVCRenderCommandName(mvcRenderCommandName) {
          return this.mvcRenderCommandNames.indexOf(mvcRenderCommandName) > -1;
        }
        /**
         * Initializes routers for all available routes and customizes the default
         * screen to be used to match the SoyPortlet architecture.
         * @protected
         */

      }, {
        key: "initializeRoutes_",
        value: function initializeRoutes_() {
          this.createDefaultScreen_();
          this.initializeActionRouter_();
          this.initializeRouters_();
          this.initializeFriendlyURLRouters_();
          this.initializeDefaultRouter_();
        }
        /**
         * Initializes a router for the action routes of the system.
         * @protected
         */

      }, {
        key: "initializeActionRouter_",
        value: function initializeActionRouter_() {
          var _this4 = this;

          this.createRouter_({}, function pathFn(url) {
            var uri = new URL(url, window.location.origin);
            var lifecycleParam = uri.searchParams.get('p_p_lifecycle');
            var portletIdParam = uri.searchParams.get('p_p_id');
            return lifecycleParam === '1' && portletIdParam === _this4.portletId;
          });
        }
        /**
         * Initializes a router for the default route of the system.
         * @protected
         */

      }, {
        key: "initializeDefaultRouter_",
        value: function initializeDefaultRouter_() {
          var pathFn = this.isDefaultURL_.bind(this);
          this.createRouter_({
            mvcRenderCommandName: '/'
          }, pathFn);
        }
        /**
         * Initializes routers for the friendly url routes available in the system.
         * @protected
         */

      }, {
        key: "initializeFriendlyURLRouters_",
        value: function initializeFriendlyURLRouters_() {
          var routes = this.friendlyURLRoutes.reduce(function (routes, route) {
            routes[route.pattern] = route;
            return routes;
          }, {});
          var keys = Object.keys(routes);

          for (var i = 0, l = keys.length; i < l; i++) {
            var pattern = keys[i];
            var friendlyURLRoute = routes[pattern];
            var implicitParameters = friendlyURLRoute.implicitParameters;
            var mvcRenderCommandName = implicitParameters.mvcRenderCommandName;

            if (!this.hasMVCRenderCommandName(mvcRenderCommandName)) {
              console.warn('Unable to find route for mvcRenderCommandName:', mvcRenderCommandName);
              continue;
            }

            var pathFn = this.getPathFunctionForFriendlyURLRoute_(friendlyURLRoute);
            this.createRouter_({
              mvcRenderCommandName: mvcRenderCommandName
            }, pathFn);
          }
        }
        /**
         * Initializes routers for the regular routes available in the system.
         * @protected
         */

      }, {
        key: "initializeRouters_",
        value: function initializeRouters_() {
          var _this5 = this;

          this.mvcRenderCommandNames.forEach(function (mvcRenderCommandName) {
            return _this5.createRouter_({
              mvcRenderCommandName: mvcRenderCommandName
            });
          });
        }
        /**
         * Detects if the supplied url is of a specific type
         * @param {string} url A path or url
         * @protected
         * @return {boolean} True if the supplied url is a simple default url
         */

      }, {
        key: "isDefaultURL_",
        value: function isDefaultURL_(url) {
          var uri = new URL(url, window.location.origin);

          if (uri.searchParams.get('p_p_lifecycle') === '1') {
            return false;
          }

          if (uri.searchParams.has("".concat(this.portletNamespace, "javax.portlet.action"))) {
            return false;
          }

          if (uri.searchParams.has("".concat(this.portletNamespace, "mvcRenderCommandName"))) {
            return false;
          }

          if (this.isFriendlyURL_(url)) {
            return false;
          }

          var currentURI = new URL(Liferay.currentURL, window.location.origin);

          if (uri.pathname === currentURI.pathname) {
            return true;
          }

          if (uri.pathname === themeDisplay.getLayoutRelativeURL()) {
            return true;
          }

          return false;
        }
        /**
         * Detects if the supplied url is a registered friendly url
         * @param {string} url A path or url
         * @protected
         * @return {boolean} True if the supplied url is a friendly url
         */

      }, {
        key: "isFriendlyURL_",
        value: function isFriendlyURL_(url) {
          var _this6 = this;

          var friendlyURLRoute = this.friendlyURLRoutes.find(function (friendlyURLRoute) {
            return _this6.getPathFunctionForFriendlyURLPattern_(friendlyURLRoute.pattern, _this6.friendlyURLMapping)(url);
          });
          return !!friendlyURLRoute;
        }
        /**
         * Matches a path against a given mvcRenderCommandName to verify if it
         * can be routed in the given setup
         * @param {string} mvcRenderCommandName
         * @param {string} path
         * @protected
         * @return {boolean} True if the path matches the mvcRenderCommandName
         */

      }, {
        key: "matchPath_",
        value: function matchPath_(mvcRenderCommandName, path) {
          var uri = new URL(path, window.location.origin);
          var mvcRenderCommandNameParam = uri.searchParams.get("".concat(this.portletNamespace, "mvcRenderCommandName"));
          var portletIdParam = uri.searchParams.get('p_p_id');
          return mvcRenderCommandNameParam === mvcRenderCommandName && portletIdParam === this.portletId;
        }
        /**
         * Shows a general alert. Alerts are always discarded once a new navigation
         * starts
         * @protected
         * @param {string} message The message that should appear in the alert
         * @param {string} type The type of alert (should be danger, warning or
         * success)
         */

      }, {
        key: "maybeShowAlert_",
        value: function maybeShowAlert_(message) {
          var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'danger';
          var title = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Liferay.Language.get('error');

          if (message) {
            (0, _frontendJsWeb.openToast)({
              message: message,
              title: title,
              type: type
            });
          }
        }
        /**
         * Handles the global sessionMessages after every navigation
         * @param {Event} event The end navigation event
         * @protected
         */

      }, {
        key: "onEndNavigate_",
        value: function onEndNavigate_(event) {
          var _this7 = this;

          if (event.error && (event.error.requestError || event.error.invalidStatus)) {
            window.location.href = event.path;
          } else {
            var activeState = _metalRouter.default.getActiveState();

            if (activeState) {
              var _INJECTED_DATA_ = activeState._INJECTED_DATA_;
              var sessionErrors = _INJECTED_DATA_.sessionErrors,
                  sessionMessages = _INJECTED_DATA_.sessionMessages;

              if (sessionMessages) {
                Object.keys(sessionMessages).forEach(function (key) {
                  return _this7.maybeShowAlert_(sessionMessages[key], 'success', Liferay.Language.get('success'));
                });
              }

              if (sessionErrors) {
                Object.keys(sessionErrors).forEach(function (key) {
                  return _this7.maybeShowAlert_(sessionErrors[key]);
                });
              }
            }
          }
        }
      }]);

      return SoyPortletRouter;
    }(_metalState.default);
    /**
     * State definition.
     * @ignore
     * @type {!Object}
     * @static
     */

    SoyPortletRouter.STATE = {
      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {Object}
       */
      context: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {string}
       */
      element: {
        setter: _metalDom.default.toElement
      },

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {string}
       */
      friendlyURLMapping: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {string}
       */
      friendlyURLPrefix: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {Array<string>}
       */
      friendlyURLRoutes: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {Array<String>}
       */
      mvcRenderCommandNames: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {string}
       */
      portletId: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {string}
       */
      portletNamespace: {},

      /**
       * @instance
       * @memberof SoyPortletRouter
       * @type {string}
       */
      portletWrapper: {
        setter: _metalDom.default.toElement
      }
    };
    var _default = SoyPortletRouter;
    exports.default = _default;
    //# sourceMappingURL=SoyPortletRouter.js.map
  }
});
//# sourceMappingURL=SoyPortletRouter.js.map