define(['react', 'prop-types', 'react-redux', 'sanitize.css/sanitize.css', 'react-helmet', 'react-intl', 'react-infinite-scroller', 'redux', 'reselect', 'react-bootstrap/ListGroup', 'react-icons/fa', 'react-bootstrap/Row', 'react-bootstrap/Col', 'react-bootstrap/Container', 'styled-components', 'hoist-non-react-statics', 'invariant', 'lodash', 'connected-react-router', 'immer', 'history', 'redux-saga/effects', 'redux-saga'], function (React, PropTypes, reactRedux, sanitize_css, reactHelmet, reactIntl, InfiniteScroll, redux, reselect, ListGroup, fa, Row, Col, Container, styled, hoistNonReactStatics, invariant, lodash, connectedReactRouter, produce, history$1, effects, createSagaMiddleware) { 'use strict';

  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
  var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
  var InfiniteScroll__default = /*#__PURE__*/_interopDefaultLegacy(InfiniteScroll);
  var ListGroup__default = /*#__PURE__*/_interopDefaultLegacy(ListGroup);
  var Row__default = /*#__PURE__*/_interopDefaultLegacy(Row);
  var Col__default = /*#__PURE__*/_interopDefaultLegacy(Col);
  var Container__default = /*#__PURE__*/_interopDefaultLegacy(Container);
  var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled);
  var invariant__default = /*#__PURE__*/_interopDefaultLegacy(invariant);
  var produce__default = /*#__PURE__*/_interopDefaultLegacy(produce);
  var createSagaMiddleware__default = /*#__PURE__*/_interopDefaultLegacy(createSagaMiddleware);

  const CounterText = styled__default['default'].div.withConfig({
    displayName: "TopicListItem__CounterText",
    componentId: "sc-9of5q8-0"
  })(["font-size:0.7rem;"]);

  function TopicListItem(props) {
    return /*#__PURE__*/React__default['default'].createElement(ListGroup__default['default'].Item, {
      action: true,
      onClick: props.onClick
    }, /*#__PURE__*/React__default['default'].createElement(Container__default['default'], null, /*#__PURE__*/React__default['default'].createElement(Row__default['default'], null, /*#__PURE__*/React__default['default'].createElement(Col__default['default'], {
      md: 1
    }, /*#__PURE__*/React__default['default'].createElement(fa.FaComments, {
      size: 32
    })), /*#__PURE__*/React__default['default'].createElement(Col__default['default'], {
      md: 10
    }, /*#__PURE__*/React__default['default'].createElement("h4", null, props.item.title), props.item.description), /*#__PURE__*/React__default['default'].createElement(Col__default['default'], {
      md: 1
    }, /*#__PURE__*/React__default['default'].createElement(CounterText, null, props.item.threads_counter), /*#__PURE__*/React__default['default'].createElement(CounterText, null, "Threads")))));
  }

  TopicListItem.propTypes = {
    item: PropTypes__default['default'].any,
    onClick: PropTypes__default['default'].func
  };

  const H2 = styled__default['default'].h2.withConfig({
    displayName: "H2",
    componentId: "sc-1ujnxqo-0"
  })(["font-size:1.5em;"]);

  function _defineProperty(obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  }

  /**
   * Validate the shape of redux store
   */

  function checkStore(store) {
    const shape = {
      dispatch: lodash.isFunction,
      subscribe: lodash.isFunction,
      getState: lodash.isFunction,
      replaceReducer: lodash.isFunction,
      runSaga: lodash.isFunction,
      injectedReducers: lodash.isObject,
      injectedSagas: lodash.isObject
    };
    invariant__default['default'](lodash.conformsTo(store, shape), '(app/utils...) injectors: Expected a valid redux store');
  }

  /*
   * AppConstants
   * Each action has a corresponding type, which the reducer knows and picks up on.
   * To avoid weird typos between the reducer and the actions, we save them as
   * constants here. We prefix them with 'yourproject/YourComponent' so we avoid
   * reducers accidentally picking up actions they shouldn't.
   *
   * Follow this format:
   * export const YOUR_ACTION_CONSTANT = 'yourproject/YourContainer/YOUR_ACTION_CONSTANT';
   */
  const LOAD_REPOS = 'boilerplate/App/LOAD_REPOS';
  const LOAD_REPOS_SUCCESS = 'boilerplate/App/LOAD_REPOS_SUCCESS';
  const LOAD_REPOS_ERROR = 'boilerplate/App/LOAD_REPOS_ERROR';
  const LOAD_SIGNED_IN_USER = 'boilerplate/App/LOAD_SIGNED_IN_USER';
  const LOAD_SIGNED_IN_USER_SUCCESS = 'boilerplate/App/LOAD_SIGNED_IN_USER_SUCCESS';
  const LOAD_SIGNED_IN_USER_ERROR = 'boilerplate/App/LOAD_SIGNED_IN_USER_ERROR';

  /*
   * AppReducer (global)
   *
   * The reducer takes care of our data. Using actions, we can
   * update our application state. To add a new action,
   * add it to the switch statement in the reducer function
   *
   */

  const initialState$3 = {
    loading: false,
    error: false,
    currentUser: false,
    userData: {
      repositories: false
    },
    signedInUser: false
  };
  /* eslint-disable default-case, no-param-reassign */

  const appReducer = (state = initialState$3, action) => produce__default['default'](state, draft => {
    switch (action.type) {
      case LOAD_REPOS:
        draft.loading = true;
        draft.error = false;
        draft.userData.repositories = false;
        break;

      case LOAD_REPOS_SUCCESS:
        draft.userData.repositories = action.repos;
        draft.loading = false;
        draft.currentUser = action.username;
        break;

      case LOAD_REPOS_ERROR:
        draft.error = action.error;
        draft.loading = false;
        break;

      case LOAD_SIGNED_IN_USER:
        draft.loading = true;
        draft.error = false;
        draft.signedInUser = false;
        break;

      case LOAD_SIGNED_IN_USER_SUCCESS:
        draft.userData.repositories = action.repos;
        draft.loading = false;
        draft.signedInUser = action.signedInUser;
        break;

      case LOAD_SIGNED_IN_USER_ERROR:
        draft.error = action.error;
        draft.loading = false;
        break;
    }
  });

  /*
   *
   * LanguageProvider constants
   *
   */
  const CHANGE_LOCALE = 'app/LanguageToggle/CHANGE_LOCALE';

  var en = {
  	"boilerplate.components.Footer.author.message": "Made with love by {author}.",
  	"boilerplate.components.Footer.license.message": "This project is licensed under the MIT license.",
  	"boilerplate.components.Header.features": "Features",
  	"boilerplate.components.Header.home": "Home",
  	"boilerplate.containers.FeaturePage.css.header": "Features",
  	"boilerplate.containers.FeaturePage.css.message": "Next generation CSS",
  	"boilerplate.containers.FeaturePage.feedback.header": "Instant feedback",
  	"boilerplate.containers.FeaturePage.feedback.message": "Enjoy the best DX and code your app at the speed of thought! Your\n    saved changes to the CSS and JS are reflected instantaneously\n    without refreshing the page. Preserve application state even when\n    you update something in the underlying code!",
  	"boilerplate.containers.FeaturePage.header": "Features",
  	"boilerplate.containers.FeaturePage.internationalization.header": "Complete i18n Standard Internationalization & Pluralization",
  	"boilerplate.containers.FeaturePage.internationalization.message": "Scalable apps need to support multiple languages, easily add and support multiple languages with `react-intl`.",
  	"boilerplate.containers.FeaturePage.javascript.header": "Next generation JavaScript",
  	"boilerplate.containers.FeaturePage.javascript.message": "Use template strings, object destructuring, arrow functions, JSX\n    syntax and more, today.",
  	"boilerplate.containers.FeaturePage.network.header": "Offline-first",
  	"boilerplate.containers.FeaturePage.network.message": "The next frontier in performant web apps: availability without a\n      network connection from the instant your users load the app.",
  	"boilerplate.containers.FeaturePage.routing.header": "Industry-standard routing",
  	"boilerplate.containers.FeaturePage.routing.message": "Write composable CSS that's co-located with your components for\n    complete modularity. Unique generated class names keep the\n    specificity low while eliminating style clashes. Ship only the\n    styles that are on the page for the best performance.",
  	"boilerplate.containers.FeaturePage.scaffolding.header": "Quick scaffolding",
  	"boilerplate.containers.FeaturePage.scaffolding.message": "Automate the creation of components, containers, routes, selectors\n  and sagas - and their tests - right from the CLI!",
  	"boilerplate.containers.FeaturePage.state_management.header": "Predictable state management",
  	"boilerplate.containers.FeaturePage.state_management.message": "Unidirectional data flow allows for change logging and time travel\n    debugging.",
  	"boilerplate.containers.HomePage.start_project.header": "Start your next react project in seconds",
  	"boilerplate.containers.HomePage.start_project.message": "A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices",
  	"boilerplate.containers.HomePage.tryme.atPrefix": "@",
  	"boilerplate.containers.HomePage.tryme.header": "Try me!",
  	"boilerplate.containers.HomePage.tryme.message": "Show Github repositories by",
  	"boilerplate.containers.LocaleToggle.de": "de",
  	"boilerplate.containers.LocaleToggle.en": "en",
  	"boilerplate.containers.NotFoundPage.header": "Page not found."
  };

  var enTranslationMessages = /*#__PURE__*/Object.freeze({
    __proto__: null,
    'default': en
  });

  var de = {
  	"boilerplate.components.Footer.author.message": "Mit Liebe gemacht von {author}.",
  	"boilerplate.components.Footer.license.message": "Dieses Projekt wird unter der MIT-Lizenz veröffentlicht.",
  	"boilerplate.components.Header.features": "",
  	"boilerplate.components.Header.home": "",
  	"boilerplate.containers.FeaturePage.css.header": "",
  	"boilerplate.containers.FeaturePage.css.message": "Die nächste Generation von CSS",
  	"boilerplate.containers.FeaturePage.feedback.header": "Sofortiges Feedback",
  	"boilerplate.containers.FeaturePage.feedback.message": "Genießen Sie die beste Entwicklungserfahrung und programmieren Sie Ihre App so schnell wie noch nie! Ihre Änderungen an dem CSS und JavaScript sind sofort reflektiert, ohne die Seite aktualisieren zu müssen. So bleibt der Anwendungszustand bestehen, auch wenn Sie etwas in dem darunter liegenden Code aktualisieren!",
  	"boilerplate.containers.FeaturePage.header": "",
  	"boilerplate.containers.FeaturePage.internationalization.header": "Komplette i18n Standard-Internationalisierung und Pluralisierung",
  	"boilerplate.containers.FeaturePage.internationalization.message": "Das Internet ist global. Mehrsprachige- und Pluralisierungsunterstützung ist entscheidend für große Web-Anwendungen.",
  	"boilerplate.containers.FeaturePage.javascript.header": "Das Internet ist global. Mehrsprachige- und Pluralisierungsunterstützung ist entscheidend für große Web-Anwendungen.",
  	"boilerplate.containers.FeaturePage.javascript.message": "Benutzen Sie ES6 template strings, object destructuring, arrow functions, JSX syntax und mehr, heute.",
  	"boilerplate.containers.FeaturePage.network.header": "",
  	"boilerplate.containers.FeaturePage.network.message": "The next frontier in performant web apps: availability without a\n      network connection from the instant your users load the app.",
  	"boilerplate.containers.FeaturePage.routing.header": "Standard Routing",
  	"boilerplate.containers.FeaturePage.routing.message": "Schreiben Sie CSS, das am selben Ort wie ihre Komponenten ist. Deterministisch generierte, einzigartige Klassennamen halten die Spezifität niedrig während styling Konflikte vermieden werden. Senden Sie nur das CSS an ihre Benutzer welches dann wirklich sichtbar ist für die schnellste Performance!",
  	"boilerplate.containers.FeaturePage.scaffolding.header": "Schnelles Scaffolding",
  	"boilerplate.containers.FeaturePage.scaffolding.message": "Automatisieren Sie die Kreation von Komponenten, Containern, Routen, Selektoren und Sagas – und ihre Tests – direkt von dem Terminal!",
  	"boilerplate.containers.FeaturePage.state_management.header": "Berechenbare Stateverwaltung",
  	"boilerplate.containers.FeaturePage.state_management.message": "Unidirectional data flow erlaubt uns alle Änderungen ihrer Applikation zu loggen und time travel debugging einzusetzen.",
  	"boilerplate.containers.HomePage.start_project.header": "Beginnen Sie Ihr nächstes React Projekt in Sekunden",
  	"boilerplate.containers.HomePage.start_project.message": "Ein skalierendes, offline-first Fundament mit der besten DX und einem Fokus auf Performance und bewährte Methoden",
  	"boilerplate.containers.HomePage.tryme.atPrefix": "",
  	"boilerplate.containers.HomePage.tryme.header": "Probiere mich!",
  	"boilerplate.containers.HomePage.tryme.message": "Zeige die Github Repositories von",
  	"boilerplate.containers.LocaleToggle.de": "",
  	"boilerplate.containers.LocaleToggle.en": "",
  	"boilerplate.containers.NotFoundPage.header": "Seite nicht gefunden."
  };

  var deTranslationMessages = /*#__PURE__*/Object.freeze({
    __proto__: null,
    'default': de
  });

  /**
   * i18n.js
   *
   * This will setup the i18n language files and locale data for your app.
   *
   *   IMPORTANT: This file is used by the internal build
   *   script `extract-intl`, and must use CommonJS module syntax
   *   You CANNOT use import/export in this file.
   */
  const addLocaleData = require('react-intl').addLocaleData; //eslint-disable-line


  const enLocaleData = require('react-intl/locale-data/en');

  const deLocaleData = require('react-intl/locale-data/de'); // const enTranslationMessages = require('./translations/en.json')
  addLocaleData(enLocaleData);
  addLocaleData(deLocaleData);
  const DEFAULT_LOCALE = 'en'; // prettier-ignore
  const formatTranslationMessages = (locale, messages) => {
    const defaultFormattedMessages = locale !== DEFAULT_LOCALE ? formatTranslationMessages(DEFAULT_LOCALE, enTranslationMessages) : {};

    const flattenFormattedMessages = (formattedMessages, key) => {
      const formattedMessage = !messages[key] && locale !== DEFAULT_LOCALE ? defaultFormattedMessages[key] : messages[key];
      return Object.assign(formattedMessages, {
        [key]: formattedMessage
      });
    };

    return Object.keys(messages).reduce(flattenFormattedMessages, {});
  };
  ({
    en: formatTranslationMessages('en', enTranslationMessages),
    de: formatTranslationMessages('de', deTranslationMessages)
  }); // exports.appLocales = appLocales
  // exports.formatTranslationMessages = formatTranslationMessages
  // exports.translationMessages = translationMessages
  // exports.DEFAULT_LOCALE = DEFAULT_LOCALE

  /*
   *
   * LanguageProvider reducer
   *
   */
  const initialState$2 = {
    locale: DEFAULT_LOCALE
  };
  /* eslint-disable default-case, no-param-reassign */

  const languageProviderReducer = (state = initialState$2, action) => produce__default['default'](state, draft => {
    switch (action.type) {
      case CHANGE_LOCALE:
        draft.locale = action.locale;
        break;
    }
  });

  let ROOT_URL = '';
  const conf$1 = window.REACT_COMMENTS_DJANGO_CONFIG;

  if (conf$1) {
    ({
      ROOT_URL
    } = conf$1);
  }

  const history = history$1.createBrowserHistory({
    basename: ROOT_URL
  });

  function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

  function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$1(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
  /**
   * Merges the main reducer with the router state and dynamically injected reducers
   */

  function createReducer(injectedReducers = {}) {
    const rootReducer = redux.combineReducers(_objectSpread$1({
      global: appReducer,
      language: languageProviderReducer,
      router: connectedReactRouter.connectRouter(history)
    }, injectedReducers));
    return rootReducer;
  }

  function injectReducerFactory(store, isValid) {
    return function injectReducer(key, reducer) {
      if (!isValid) checkStore(store);
      invariant__default['default'](lodash.isString(key) && !lodash.isEmpty(key) && lodash.isFunction(reducer), '(app/utils...) injectReducer: Expected `reducer` to be a reducer function'); // Check `store.injectedReducers[key] === reducer` for hot reloading when a key is the same but a reducer is different

      if (Reflect.has(store.injectedReducers, key) && store.injectedReducers[key] === reducer) return;
      store.injectedReducers[key] = reducer; // eslint-disable-line no-param-reassign

      store.replaceReducer(createReducer(store.injectedReducers));
    };
  }
  function getInjectors$1(store) {
    checkStore(store);
    return {
      injectReducer: injectReducerFactory(store, true)
    };
  }

  const useInjectReducer = ({
    key,
    reducer
  }) => {
    const context = React__default['default'].useContext(reactRedux.ReactReduxContext);
    React__default['default'].useEffect(() => {
      getInjectors$1(context.store).injectReducer(key, reducer);
    }, []);
  };

  const RESTART_ON_REMOUNT = '@@saga-injector/restart-on-remount';
  const DAEMON = '@@saga-injector/daemon';
  const ONCE_TILL_UNMOUNT = '@@saga-injector/once-till-unmount'; // const conf = window.REACT_COMMENTS_DJANGO_CONFIG

  const conf = window.REACT_COMMENTS_DJANGO_CONFIG;
  let API_URL_POSTFIX = '';

  if (conf) {
    ({
      API_URL_POSTFIX
    } = conf);
  }

  const API_PREFIX = `/api/v1/${API_URL_POSTFIX}`;

  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
  const allowedModes = [RESTART_ON_REMOUNT, DAEMON, ONCE_TILL_UNMOUNT];

  const checkKey = key => invariant__default['default'](lodash.isString(key) && !lodash.isEmpty(key), '(app/utils...) injectSaga: Expected `key` to be a non empty string');

  const checkDescriptor = descriptor => {
    const shape = {
      saga: lodash.isFunction,
      mode: mode => lodash.isString(mode) && allowedModes.includes(mode)
    };
    invariant__default['default'](lodash.conformsTo(descriptor, shape), '(app/utils...) injectSaga: Expected a valid saga descriptor');
  };

  function injectSagaFactory(store, isValid) {
    return function injectSaga(key, descriptor = {}, args) {
      if (!isValid) checkStore(store);

      const newDescriptor = _objectSpread(_objectSpread({}, descriptor), {}, {
        mode: descriptor.mode || DAEMON
      });

      const {
        saga,
        mode
      } = newDescriptor;
      checkKey(key);
      checkDescriptor(newDescriptor);
      let hasSaga = Reflect.has(store.injectedSagas, key);

      if (process.env.NODE_ENV !== 'production') {
        const oldDescriptor = store.injectedSagas[key]; // enable hot reloading of daemon and once-till-unmount sagas

        if (hasSaga && oldDescriptor.saga !== saga) {
          oldDescriptor.task.cancel();
          hasSaga = false;
        }
      }

      if (!hasSaga || hasSaga && mode !== DAEMON && mode !== ONCE_TILL_UNMOUNT) {
        /* eslint-disable no-param-reassign */
        store.injectedSagas[key] = _objectSpread(_objectSpread({}, newDescriptor), {}, {
          task: store.runSaga(saga, args)
        });
        /* eslint-enable no-param-reassign */
      }
    };
  }
  function ejectSagaFactory(store, isValid) {
    return function ejectSaga(key) {
      if (!isValid) checkStore(store);
      checkKey(key);

      if (Reflect.has(store.injectedSagas, key)) {
        const descriptor = store.injectedSagas[key];

        if (descriptor.mode && descriptor.mode !== DAEMON) {
          descriptor.task.cancel(); // Clean up in production; in development we need `descriptor.saga` for hot reloading

          if (process.env.NODE_ENV === 'production') {
            // Need some value to be able to detect `ONCE_TILL_UNMOUNT` sagas in `injectSaga`
            store.injectedSagas[key] = 'done'; // eslint-disable-line no-param-reassign
          }
        }
      }
    };
  }
  function getInjectors(store) {
    checkStore(store);
    return {
      injectSaga: injectSagaFactory(store, true),
      ejectSaga: ejectSagaFactory(store, true)
    };
  }

  const useInjectSaga = ({
    key,
    saga,
    mode
  }) => {
    const context = React__default['default'].useContext(reactRedux.ReactReduxContext);
    React__default['default'].useEffect(() => {
      const injectors = getInjectors(context.store);
      injectors.injectSaga(key, {
        saga,
        mode
      });
      return () => {
        injectors.ejectSaga(key);
      };
    }, []);
  };

  /*
   * AppConstants
   * Each action has a corresponding type, which the reducer knows and picks up on.
   * To avoid weird typos between the reducer and the actions, we save them as
   * constants here. We prefix them with 'yourproject/YourComponent' so we avoid
   * reducers accidentally picking up actions they shouldn't.
   *
   * Follow this format:
   * export const YOUR_ACTION_CONSTANT = 'yourproject/YourContainer/YOUR_ACTION_CONSTANT';
   */
  const LOAD_TOPICS = 'djeddit/Topics/LOAD_TOPICS';
  const LOAD_TOPICS_SUCCESS = 'djeddit/Topics/LOAD_TOPICS_SUCCESS';
  const LOAD_TOPICS_ERROR = 'djeddit/Topics/LOAD_TOPICS_ERROR';
  const LOAD_TOPIC = 'djeddit/Topics/LOAD_TOPIC';
  const LOAD_TOPIC_SUCCESS = 'djeddit/Topics/LOAD_TOPIC_SUCCESS';
  const LOAD_TOPIC_ERROR = 'djeddit/Topics/LOAD_TOPIC_ERROR';

  /*
   * TopicListReducer
   *
   * The reducer takes care of our data. Using actions, we can
   * update our application state. To add a new action,
   * add it to the switch statement in the reducer function
   *
   */

  const initialState$1 = {
    topicsList: false,
    topic: false
  };
  /* eslint-disable default-case, no-param-reassign */

  const topicsListReducer = (state = initialState$1, action) => produce__default['default'](state, draft => {
    switch (action.type) {
      case LOAD_TOPICS:
        draft.loading = true;
        draft.error = false;
        draft.topicsList = false;
        break;

      case LOAD_TOPICS_SUCCESS:
        draft.topicsList = action.topicsList;
        draft.loading = false;
        break;

      case LOAD_TOPICS_ERROR:
        draft.error = action.error;
        draft.loading = false;
        break;

      case LOAD_TOPIC:
        draft.loading = true;
        draft.error = false;
        draft.topic = false;
        break;

      case LOAD_TOPIC_SUCCESS:
        draft.topic = action.topic;
        draft.loading = false;
        break;

      case LOAD_TOPIC_ERROR:
        draft.error = action.error;
        draft.loading = false;
        break;
    }
  });

  /**
   * topics list selectors
   */

  const selectTopics = state => state.topics || initialState$1;

  const makeSelectTopicsList = () => reselect.createSelector(selectTopics, topicsState => topicsState.topicsList);

  const Section = styled__default['default'].section.withConfig({
    displayName: "Section",
    componentId: "glq6sp-0"
  })(["margin:3em auto;&:first-child{margin-top:0;}"]);

  const CenteredSection = styled__default['default'](Section).withConfig({
    displayName: "CenteredSection",
    componentId: "sc-1hnw32i-0"
  })(["text-align:center;"]);

  /*
   * HomePage Messages
   *
   * This contains all the text for the HomePage component.
   */
  const scope = 'boilerplate.containers.HomePage';
  var messages = reactIntl.defineMessages({
    topicsList: {
      id: `${scope}.topics`,
      defaultMessage: 'Topics'
    }
  });

  /*
   * App Actions
   *
   * Actions change things in your application
   * Since this boilerplate uses a uni-directional data flow, specifically redux,
   * we have these actions which are the only way your application interacts with
   * your application state. This guarantees that your state is up to date and nobody
   * messes it up weirdly somewhere.
   *
   * To add a new Action:
   * 1) Import your constant
   * 2) Add a function like this:
   *    export function yourAction(var) {
   *        return { type: YOUR_ACTION_CONSTANT, var: var }
   *    }
   */
  /**
   * Load the topics List, this action starts the request saga
   *
   * @return {object} An action object with a type of LOAD_TOPICS
   */

  function loadTopics(nextHref) {
    return {
      type: LOAD_TOPICS,
      nextHref
    };
  }
  /**
   * Dispatched when the topics List are loaded by the request saga
   *
   * @param  {array} topicsList The topics List data
   *
   * @return {object}      An action object with a type of LOAD_TOPICS_SUCCESS passing the topicsList
   */

  function topicsListLoaded(topicsList) {
    return {
      type: LOAD_TOPICS_SUCCESS,
      topicsList
    };
  }
  /**
   * Dispatched when loading the topicsListitories fails
   *
   * @param  {object} error The error
   *
   * @return {object}       An action object with a type of LOAD_TOPICS_ERROR passing the error
   */

  function topicsListLoadingError(error) {
    return {
      type: LOAD_TOPICS_ERROR,
      error
    };
  }
  function loadTopic(slug) {
    return {
      type: LOAD_TOPIC,
      slug
    };
  }
  function topicLoaded(topic) {
    return {
      type: LOAD_TOPIC_SUCCESS,
      topic
    };
  }
  function topicLoadingError(error) {
    return {
      type: LOAD_TOPIC_ERROR,
      error
    };
  }

  var loadTopicsActionsCreator = /*#__PURE__*/Object.freeze({
    __proto__: null,
    loadTopics: loadTopics,
    topicsListLoaded: topicsListLoaded,
    topicsListLoadingError: topicsListLoadingError,
    loadTopic: loadTopic,
    topicLoaded: topicLoaded,
    topicLoadingError: topicLoadingError
  });

  /**
   * Parses the JSON returned by a network request
   *
   * @param  {object} response A response from a network request
   *
   * @return {object}          The parsed JSON from the request
   */
  function parseJSON(response) {
    if (response.status === 204 || response.status === 205) {
      return null;
    }

    return response.json();
  }
  /**
   * Checks if a network request came back fine, and throws an error if not
   *
   * @param  {object} response   A response from a network request
   *
   * @return {object|undefined} Returns either the response, or throws an error
   */


  function checkStatus(response) {
    if (response.status >= 200 && response.status < 300) {
      return response;
    }

    const error = new Error(response.statusText);
    error.response = response;
    throw error;
  }
  /**
   * Requests a URL, returning a promise
   *
   * @param  {string} url       The URL we want to request
   * @param  {object} [options] The options we want to pass to "fetch"
   *
   * @return {object}           The response data
   */


  function request(url, options) {
    return fetch(url, options).then(checkStatus).then(parseJSON);
  }

  function getTopics(nextHref) {
    let url;

    if (nextHref) {
      url = nextHref;
    } else {
      url = `${API_PREFIX}topics/`;
    }

    return request(url, {
      method: 'GET',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
      }
    });
  }

  function getTopic$1(slug) {
    const url = `${API_PREFIX}topics/${slug}/`;
    return request(url, {
      method: 'GET',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
      }
    });
  }

  const Api = {
    getTopics,
    getTopic: getTopic$1
  };

  function* getTopicsList(sagaArgs) {
    const {
      nextHref
    } = sagaArgs;

    try {
      const topicsList = yield effects.call(Api.getTopics, nextHref);
      yield effects.put(topicsListLoaded(topicsList));
    } catch (err) {
      yield effects.put(topicsListLoadingError(err));
    }
  }
  function* getTopic(sagaArgs) {
    const {
      slug
    } = sagaArgs;

    try {
      const topic = yield effects.call(Api.getTopic, slug);
      yield effects.put(topicLoaded(topic));
    } catch (err) {
      yield effects.put(topicLoadingError(err));
    }
  }
  /**
   * Root saga manages watcher lifecycle
   */

  function* topicsData() {
    // Watches for LOAD_REPOS actions and calls getTopicsList when one comes in.
    // By using `takeLatest` only the result of the latest API call is applied.
    // It returns task descriptor (just like fork) so we can continue execution
    // It will be cancelled automatically on component unmount
    // yield takeLatest(LOAD_TOPICS, getTopicsList)
    // yield takeLatest(LOAD_TOPIC, getTopic)
    yield effects.all([effects.takeLatest(LOAD_TOPICS, getTopicsList), effects.takeLatest(LOAD_TOPIC, getTopic)]);
  }

  /*
   * TopicsPage
   *
   * This is the first thing users see of our App, at the '/' route
   */
  const key = 'topics';
  function TopicsList({
    topicListActions,
    topicsList
  }) {
    useInjectReducer({
      key,
      reducer: topicsListReducer
    });
    useInjectSaga({
      key,
      saga: topicsData
    });
    const [topics, setTopics] = React.useState([]);
    const [hasMoreItems, setHasMoreItems] = React.useState(false);
    const [nextHref, setNextHref] = React.useState(null);
    React.useEffect(() => {
      // refresh topics from server
      topicListActions.loadTopics();
      return () => {
        // clear topics list while unmount
        topicListActions.topicsListLoaded(false);
      };
    }, []);

    const loadNextPage = () => {
      if (hasMoreItems) {
        // if we call next page setHasMore item false and waiting for a server response
        setHasMoreItems(Boolean(false));
        topicListActions.loadTopics(nextHref);
      }
    };

    const onTopicClick = (e, slug) => {
      history.push(`/topics/${slug}`);
    };

    React.useEffect(() => {
      if (topicsList) {
        setTopics([...topics, ...topicsList.results]);
        setHasMoreItems(Boolean(topicsList.next));
        setNextHref(topicsList.next);
      }
    }, [topicsList]);
    let items = [];

    if (topics) {
      items = topics.map(item => /*#__PURE__*/React__default['default'].createElement(TopicListItem, {
        onClick: e => {
          onTopicClick(e, item.slug);
        },
        key: item.slug,
        item: item
      }));
    }

    return /*#__PURE__*/React__default['default'].createElement("article", null, /*#__PURE__*/React__default['default'].createElement(reactHelmet.Helmet, null, /*#__PURE__*/React__default['default'].createElement("title", null, "Topics List"), /*#__PURE__*/React__default['default'].createElement("meta", {
      name: "description",
      content: "React comments Django topics List"
    })), /*#__PURE__*/React__default['default'].createElement("div", null, /*#__PURE__*/React__default['default'].createElement(CenteredSection, null, /*#__PURE__*/React__default['default'].createElement(H2, null, /*#__PURE__*/React__default['default'].createElement(reactIntl.FormattedMessage, messages.topicsList))), /*#__PURE__*/React__default['default'].createElement(Section, null, /*#__PURE__*/React__default['default'].createElement(InfiniteScroll__default['default'], {
      pageStart: 0,
      loadMore: loadNextPage,
      hasMore: hasMoreItems // loader={<div key={this.state.nextHref} style={{clear: 'both'}} />} // fix https://github.com/CassetteRocks/react-infinite-scroller/issues/14#issuecomment-225835845

    }, /*#__PURE__*/React__default['default'].createElement(ListGroup__default['default'], null, items)))));
  }
  TopicsList.propTypes = {
    topicListActions: PropTypes__default['default'].shape({
      loadTopics: PropTypes__default['default'].func.isRequired,
      topicsListLoaded: PropTypes__default['default'].func.isRequired
    }).isRequired,
    topicsList: PropTypes__default['default'].oneOfType([PropTypes__default['default'].object, PropTypes__default['default'].bool])
  };
  const mapStateToProps = reselect.createStructuredSelector({
    topicsList: makeSelectTopicsList() // username: makeSelectUsername(),
    // loading: makeSelectLoading(),
    // error: makeSelectError(),

  });
  function mapDispatchToProps(dispatch) {
    return {
      topicListActions: redux.bindActionCreators(loadTopicsActionsCreator, dispatch)
    };
  }
  const withConnect = reactRedux.connect(mapStateToProps, mapDispatchToProps);
  var TopicsList$1 = redux.compose(withConnect, React.memo)(TopicsList);

  /**
   * Create the store with dynamic reducers
   */
  function configureStore(initialState = {}, history) {
    let composeEnhancers = redux.compose;
    const reduxSagaMonitorOptions = {}; // If Redux Dev Tools and Saga Dev Tools Extensions are installed, enable them

    /* istanbul ignore next */

    if (process.env.NODE_ENV !== 'production' && typeof window === 'object') {
      /* eslint-disable no-underscore-dangle */
      if (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}); // NOTE: Uncomment the code below to restore support for Redux Saga
      // Dev Tools once it supports redux-saga version 1.x.x
      // if (window.__SAGA_MONITOR_EXTENSION__)
      //   reduxSagaMonitorOptions = {
      //     sagaMonitor: window.__SAGA_MONITOR_EXTENSION__,
      //   };

      /* eslint-enable */
    }

    const sagaMiddleware = createSagaMiddleware__default['default'](reduxSagaMonitorOptions); // Create the store with two middlewares
    // 1. sagaMiddleware: Makes redux-sagas work
    // 2. routerMiddleware: Syncs the location/URL path to the state

    const middlewares = [sagaMiddleware, connectedReactRouter.routerMiddleware(history)];
    const enhancers = [redux.applyMiddleware(...middlewares)];
    const store = redux.createStore(createReducer(), initialState, composeEnhancers(...enhancers)); // Extensions

    store.runSaga = sagaMiddleware.run;
    store.injectedReducers = {}; // Reducer registry

    store.injectedSagas = {}; // Saga registry
    // Make reducers hot reloadable, see http://mxs.is/googmo

    /* istanbul ignore next */

    if (module.hot) {
      module.hot.accept('./reducers', () => {
        store.replaceReducer(createReducer(store.injectedReducers));
      });
    }

    return store;
  }

  /**
   * This is the entry file for the threads list component,
   */

  const initialState = {};
  const store = configureStore(initialState);
  /** *
   * @param anonUserObject use anonUserObject if true with is_anonymous attr {"is_anonymous":true}
   * @returns {*}
   * @constructor
   */

  function TopicsListComponent() {
    return /*#__PURE__*/React__default['default'].createElement(reactRedux.Provider, {
      store: store
    }, /*#__PURE__*/React__default['default'].createElement(TopicsList$1, null));
  }

  TopicsListComponent.propTypes = {
    anonAsUserObject: PropTypes__default['default'].bool
  };

  return TopicsListComponent;

});
//# sourceMappingURL=TopicsListComponent.js.map
