<commit_before>const ContentNodeResource = require('kolibri').resources.ContentNodeResource;
const ChannelResource = require('kolibri').resources.ChannelResource;
const constants = require('./state/constants');
const PageNames = constants.PageNames;
const cookiejs = require('js-cookie');
const router = require('router');

/**
 * Vuex State Mappers
 *
 * The methods below help map data from
 * the API to state in the Vuex store
 */

function _crumbState(ancestors) {
  // skip the root node
  return ancestors.slice(1).map(ancestor => ({
    id: ancestor.pk,
    title: ancestor.title,
  }));
}

function _topicState(data) {
  const state = {
    id: data.pk,
    title: data.title,
    description: data.description,
    breadcrumbs: _crumbState(data.ancestors),
  };
  return state;
}

function _contentState(data) {
  let progress;
  if (!data.progress_fraction) {
    progress = 'unstarted';
  } else if (data.progress_fraction < 1) {
    progress = 'partial';
  } else {
    progress = 'complete';
  }
  const state = {
    id: data.pk,
    title: data.title,
    kind: data.kind,
    description: data.description,
    thumbnail: data.thumbnail,
    available: data.available,
    files: data.files,
    progress,
    content_id: data.content_id,
    breadcrumbs: _crumbState(data.ancestors),
  };
  return state;
}

function _collectionState(data) {
  const topics = data
    .filter((item) => item.kind === 'topic')
    .map((item) => _topicState(item));
  const contents = data
    .filter((item) => item.kind !== 'topic')
    .map((item) => _contentState(item));
  return { topics, contents };
}

/*
* Returns the promise that fetches the channel list.
*/
function _getChannelList() {
  let returnChannelList = null;
  return new Promise((resolve, reject) => {
    ChannelResource.getCollection({}).fetch()
      .then((channelList) => {
        if (channelList.length) {
          returnChannelList = channelList;
        }
        resolve(returnChannelList);
      });
  });
}

/*
 * Returns a promise that fetches the current channel id.
 */
function _getCurrentChannelId() {
  let currentChannelId = null;
  return new Promise((resolve, reject) => {
    const channelListPromise = _getChannelList();
    Promise.all([channelListPromise])
    .then(([channelList]) => {
      if (channelList.length) {
        const cookieCurrentChannelId = cookiejs.get('currentChannel');
        if (channelList.some((channel) => channel.id === cookieCurrentChannelId)) {
          currentChannelId = cookieCurrentChannelId;
        } else {
          currentChannelId = channelList[0].id;
        }
      }
      resolve(currentChannelId);
    })
    .catch((error) => {

    });
  });
}

/*
* Returns a promise that fetches the the root topic id of the current channel.
*/
function _getCurrentChannelRootTopicId() {
  let currentChannelRootTopicId = null;
  return new Promise((resolve, reject) => {
    const currentChannelIdPromise = _getCurrentChannelId();
    const channelListPromise = _getChannelList();
    Promise.all([currentChannelIdPromise, channelListPromise])
    .then(([currentChannelId, channelList]) => {
      if (currentChannelId && channelList) {
        for (const channel in channelList) {
          if (channelList[channel].id === currentChannelId) {
            currentChannelRootTopicId = channelList[channel].root_pk;
            break;
          }
        }
      }
      resolve(currentChannelRootTopicId);
    })
    .catch((error) => {

    });
  });
}

/**
 * Actions
 *
 * These methods are used to update client-side state
 */

function redirectToExploreChannel(store) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_ROOT);

  const currentChannelIdPromise = _getCurrentChannelId();
  const currentChannelRootTopicIdPromise = _getCurrentChannelRootTopicId();

  Promise.all([currentChannelIdPromise, currentChannelRootTopicIdPromise])
    .then(([currentChannelId, currentRootTopicId]) => {
      store.dispatch('CORE_SET_ERROR', null);
      if (currentChannelId) {
        store.dispatch('SET_CURRENT_CHANNEL', currentChannelId);
        store.dispatch('SET_ROOT_TOPIC_ID', currentRootTopicId);
        cookiejs.set('currentChannel', currentChannelId);
        router.go({
          name: constants.PageNames.EXPLORE_CHANNEL,
          params: {
            channel_id: currentChannelId,
          },
        });
      } else {
        router.go({ name: constants.PageNames.CONTENT_UNAVAILABLE });
      }
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function redirectToLearnChannel(store) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_ROOT);

  const currentChannelIdPromise = _getCurrentChannelId();
  const currentChannelRootTopicIdPromise = _getCurrentChannelRootTopicId();

  Promise.all([currentChannelIdPromise, currentChannelRootTopicIdPromise])
    .then(([currentChannelId, currentRootTopicId]) => {
      store.dispatch('CORE_SET_ERROR', null);
      if (currentChannelId) {
        store.dispatch('SET_CURRENT_CHANNEL', currentChannelId);
        store.dispatch('SET_ROOT_TOPIC_ID', currentRootTopicId);
        cookiejs.set('currentChannel', currentChannelId);
        router.go({
          name: constants.PageNames.LEARN_CHANNEL,
          params: {
            channel_id: currentChannelId,
          },
        });
      } else {
        router.go({ name: constants.PageNames.CONTENT_UNAVAILABLE });
      }
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showExploreChannel(store, channelId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_CHANNEL);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);
  ContentNodeResource.setChannel(channelId);

  const currentChannelRootTopicIdPromise = _getCurrentChannelRootTopicId();
  Promise.all([currentChannelRootTopicIdPromise])
    .then(([rootTopicId]) => {
      store.dispatch('SET_ROOT_TOPIC_ID', rootTopicId);
      const attributesPromise = ContentNodeResource.getModel(rootTopicId).fetch();
      const childrenPromise = ContentNodeResource.getCollection({ parent: rootTopicId }).fetch();
      const channelPromise = ChannelResource.getCollection({}).fetch();
      Promise.all([attributesPromise, childrenPromise, channelPromise])
        .then(([attributes, children, channelList]) => {
          const pageState = { rootTopicId };
          pageState.topic = _topicState(attributes);
          const collection = _collectionState(children);
          pageState.subtopics = collection.topics;
          pageState.contents = collection.contents;
          store.dispatch('SET_PAGE_STATE', pageState);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('SET_CHANNEL_LIST', channelList);
        })
        .catch((error) => {
          store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
          store.dispatch('CORE_SET_PAGE_LOADING', false);
        });
    })
    .catch((error) => {

    });
}

function showExploreTopic(store, channelId, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_CHANNEL);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);

  const attributesPromise = ContentNodeResource.getModel(id).fetch();
  const childrenPromise = ContentNodeResource.getCollection({ parent: id }).fetch();
  const channelPromise = ChannelResource.getCollection({}).fetch();
  Promise.all([attributesPromise, childrenPromise, channelPromise])
    .then(([attributes, children, channelList]) => {
      const pageState = { id };
      pageState.topic = _topicState(attributes);
      const collection = _collectionState(children);
      pageState.subtopics = collection.topics;
      pageState.contents = collection.contents;
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showExploreContent(store, channelId, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_CONTENT);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);

  const attributesPromise = ContentNodeResource.getModel(id).fetch();
  const channelPromise = ChannelResource.getCollection({}).fetch();

  Promise.all([attributesPromise, channelPromise])
    .then(([attributes, channelList]) => {
      const pageState = { content: _contentState(attributes) };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showLearnChannel(store, channelId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_CHANNEL);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);
  ContentNodeResource.setChannel(channelId);

  const recommendedPromise =
  ContentNodeResource.getCollection({ recommendations: '' }).fetch({}, true);
  const channelPromise = ChannelResource.getCollection({}).fetch();
  Promise.all([recommendedPromise, channelPromise])
    .then(([recommendations, channelList]) => {
      const pageState = { recommendations: recommendations.map(_contentState) };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showLearnContent(store, channelId, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_CONTENT);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);

  const attributesPromise = ContentNodeResource.getModel(id).fetch();
  const recommendedPromise = ContentNodeResource.getCollection({ recommendations_for: id }).fetch();
  const channelPromise = ChannelResource.getCollection({}).fetch();

  Promise.all([attributesPromise, recommendedPromise, channelPromise])
    .then(([attributes, recommended, channelList]) => {
      const pageState = {
        content: _contentState(attributes),
        recommended: recommended.map(_contentState),
      };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function triggerSearch(store, searchTerm) {
  if (!searchTerm) {
    const searchState = {
      searchTerm,
      topics: [],
      contents: [],
    };
    store.dispatch('SET_SEARCH_STATE', searchState);
    return;
  }

  store.dispatch('SET_SEARCH_LOADING');

  const contentCollection = ContentNodeResource.getPagedCollection({ search: searchTerm });
  const searchResultsPromise = contentCollection.fetch();

  searchResultsPromise.then((results) => {
    const searchState = { searchTerm };
    const collection = _collectionState(results);
    searchState.topics = collection.topics;
    searchState.contents = collection.contents;
    store.dispatch('SET_SEARCH_STATE', searchState);
  })
    .catch((error) => {
      // TODO - how to parse and format?
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
    });
}

function toggleSearch(store) {
  store.dispatch('TOGGLE_SEARCH');
}

function showScratchpad(store) {
  store.dispatch('SET_PAGE_NAME', PageNames.SCRATCHPAD);
  store.dispatch('SET_PAGE_STATE', {});
  store.dispatch('CORE_SET_PAGE_LOADING', false);
  store.dispatch('CORE_SET_ERROR', null);
}

function showContentUnavailable(store) {
  store.dispatch('SET_PAGE_NAME', PageNames.CONTENT_UNAVAILABLE);
  store.dispatch('SET_PAGE_STATE', {});
  store.dispatch('CORE_SET_PAGE_LOADING', false);
  store.dispatch('CORE_SET_ERROR', null);
}

module.exports = {
  redirectToExploreChannel,
  redirectToLearnChannel,
  showExploreChannel,
  showExploreTopic,
  showExploreContent,
  showLearnChannel,
  showLearnContent,
  showScratchpad,
  showContentUnavailable,
  triggerSearch,
  toggleSearch,
};
<commit_msg>Promises shorthand<commit_after>const ContentNodeResource = require('kolibri').resources.ContentNodeResource;
const ChannelResource = require('kolibri').resources.ChannelResource;
const constants = require('./state/constants');
const PageNames = constants.PageNames;
const cookiejs = require('js-cookie');
const router = require('router');

/**
 * Vuex State Mappers
 *
 * The methods below help map data from
 * the API to state in the Vuex store
 */

function _crumbState(ancestors) {
  // skip the root node
  return ancestors.slice(1).map(ancestor => ({
    id: ancestor.pk,
    title: ancestor.title,
  }));
}

function _topicState(data) {
  const state = {
    id: data.pk,
    title: data.title,
    description: data.description,
    breadcrumbs: _crumbState(data.ancestors),
  };
  return state;
}

function _contentState(data) {
  let progress;
  if (!data.progress_fraction) {
    progress = 'unstarted';
  } else if (data.progress_fraction < 1) {
    progress = 'partial';
  } else {
    progress = 'complete';
  }
  const state = {
    id: data.pk,
    title: data.title,
    kind: data.kind,
    description: data.description,
    thumbnail: data.thumbnail,
    available: data.available,
    files: data.files,
    progress,
    content_id: data.content_id,
    breadcrumbs: _crumbState(data.ancestors),
  };
  return state;
}

function _collectionState(data) {
  const topics = data
    .filter((item) => item.kind === 'topic')
    .map((item) => _topicState(item));
  const contents = data
    .filter((item) => item.kind !== 'topic')
    .map((item) => _contentState(item));
  return { topics, contents };
}

/*
 * Returns the promise that fetches the channel list.
 */
function _getChannelList() {
  let returnChannelList = null;
  return new Promise((resolve, reject) => {
    ChannelResource.getCollection({}).fetch()
      .then((channelList) => {
        if (channelList.length) {
          returnChannelList = channelList;
        }
        resolve(returnChannelList);
      });
  });
}

/*
 * Returns a promise that fetches the current channel id.
 */
function _getCurrentChannelId() {
  let currentChannelId = null;
  return new Promise((resolve, reject) => {
    _getChannelList()
      .then((channelList) => {
        if (channelList.length) {
          const cookieCurrentChannelId = cookiejs.get('currentChannel');
          if (channelList.some((channel) => channel.id === cookieCurrentChannelId)) {
            currentChannelId = cookieCurrentChannelId;
          } else {
            currentChannelId = channelList[0].id;
          }
        }
        resolve(currentChannelId);
      })
      .catch((error) => {

      });
  });
}

/*
 * Returns a promise that fetches the the root topic id of the current channel.
 */
function _getCurrentChannelRootTopicId() {
  let currentChannelRootTopicId = null;
  return new Promise((resolve, reject) => {
    const currentChannelIdPromise = _getCurrentChannelId();
    const channelListPromise = _getChannelList();
    Promise.all([currentChannelIdPromise, channelListPromise])
    .then(([currentChannelId, channelList]) => {
      if (currentChannelId && channelList) {
        for (const channel in channelList) {
          if (channelList[channel].id === currentChannelId) {
            currentChannelRootTopicId = channelList[channel].root_pk;
            break;
          }
        }
      }
      resolve(currentChannelRootTopicId);
    })
    .catch((error) => {

    });
  });
}

/**
 * Actions
 *
 * These methods are used to update client-side state
 */

function redirectToExploreChannel(store) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_ROOT);

  _getCurrentChannelId()
    .then((currentChannelId) => {
      store.dispatch('CORE_SET_ERROR', null);
      if (currentChannelId) {
        store.dispatch('SET_CURRENT_CHANNEL', currentChannelId);
        cookiejs.set('currentChannel', currentChannelId);
        router.go({
          name: constants.PageNames.EXPLORE_CHANNEL,
          params: {
            channel_id: currentChannelId,
          },
        });
      } else {
        router.go({ name: constants.PageNames.CONTENT_UNAVAILABLE });
      }
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function redirectToLearnChannel(store) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_ROOT);

  _getCurrentChannelId()
    .then((currentChannelId) => {
      store.dispatch('CORE_SET_ERROR', null);
      if (currentChannelId) {
        store.dispatch('SET_CURRENT_CHANNEL', currentChannelId);
        cookiejs.set('currentChannel', currentChannelId);
        router.go({
          name: constants.PageNames.LEARN_CHANNEL,
          params: {
            channel_id: currentChannelId,
          },
        });
      } else {
        router.go({ name: constants.PageNames.CONTENT_UNAVAILABLE });
      }
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showExploreChannel(store, channelId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_CHANNEL);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);
  ContentNodeResource.setChannel(channelId);

  _getCurrentChannelRootTopicId()
    .then((rootTopicId) => {
      store.dispatch('SET_ROOT_TOPIC_ID', rootTopicId);
      const attributesPromise = ContentNodeResource.getModel(rootTopicId).fetch();
      const childrenPromise = ContentNodeResource.getCollection({ parent: rootTopicId }).fetch();
      const channelPromise = ChannelResource.getCollection({}).fetch();
      Promise.all([attributesPromise, childrenPromise, channelPromise])
        .then(([attributes, children, channelList]) => {
          const pageState = { rootTopicId };
          pageState.topic = _topicState(attributes);
          const collection = _collectionState(children);
          pageState.subtopics = collection.topics;
          pageState.contents = collection.contents;
          store.dispatch('SET_PAGE_STATE', pageState);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('SET_CHANNEL_LIST', channelList);
        })
        .catch((error) => {
          store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
          store.dispatch('CORE_SET_PAGE_LOADING', false);
        });
    })
    .catch((error) => {

    });
}

function showExploreTopic(store, channelId, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_CHANNEL);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);

  const attributesPromise = ContentNodeResource.getModel(id).fetch();
  const childrenPromise = ContentNodeResource.getCollection({ parent: id }).fetch();
  const channelPromise = ChannelResource.getCollection({}).fetch();
  Promise.all([attributesPromise, childrenPromise, channelPromise])
    .then(([attributes, children, channelList]) => {
      const pageState = { id };
      pageState.topic = _topicState(attributes);
      const collection = _collectionState(children);
      pageState.subtopics = collection.topics;
      pageState.contents = collection.contents;
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showExploreContent(store, channelId, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_CONTENT);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);

  const attributesPromise = ContentNodeResource.getModel(id).fetch();
  const channelPromise = ChannelResource.getCollection({}).fetch();

  Promise.all([attributesPromise, channelPromise])
    .then(([attributes, channelList]) => {
      const pageState = { content: _contentState(attributes) };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showLearnChannel(store, channelId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_CHANNEL);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);
  ContentNodeResource.setChannel(channelId);

  const recommendedPromise =
  ContentNodeResource.getCollection({ recommendations: '' }).fetch({}, true);
  const channelPromise = ChannelResource.getCollection({}).fetch();
  Promise.all([recommendedPromise, channelPromise])
    .then(([recommendations, channelList]) => {
      const pageState = { recommendations: recommendations.map(_contentState) };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function showLearnContent(store, channelId, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_CONTENT);
  store.dispatch('SET_CURRENT_CHANNEL', channelId);
  cookiejs.set('currentChannel', channelId);

  const attributesPromise = ContentNodeResource.getModel(id).fetch();
  const recommendedPromise = ContentNodeResource.getCollection({ recommendations_for: id }).fetch();
  const channelPromise = ChannelResource.getCollection({}).fetch();

  Promise.all([attributesPromise, recommendedPromise, channelPromise])
    .then(([attributes, recommended, channelList]) => {
      const pageState = {
        content: _contentState(attributes),
        recommended: recommended.map(_contentState),
      };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_CHANNEL_LIST', channelList);
    })
    .catch((error) => {
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    });
}

function triggerSearch(store, searchTerm) {
  if (!searchTerm) {
    const searchState = {
      searchTerm,
      topics: [],
      contents: [],
    };
    store.dispatch('SET_SEARCH_STATE', searchState);
    return;
  }

  store.dispatch('SET_SEARCH_LOADING');

  const contentCollection = ContentNodeResource.getPagedCollection({ search: searchTerm });
  const searchResultsPromise = contentCollection.fetch();

  searchResultsPromise.then((results) => {
    const searchState = { searchTerm };
    const collection = _collectionState(results);
    searchState.topics = collection.topics;
    searchState.contents = collection.contents;
    store.dispatch('SET_SEARCH_STATE', searchState);
  })
    .catch((error) => {
      // TODO - how to parse and format?
      store.dispatch('CORE_SET_ERROR', JSON.stringify(error, null, '\t'));
    });
}

function toggleSearch(store) {
  store.dispatch('TOGGLE_SEARCH');
}

function showScratchpad(store) {
  store.dispatch('SET_PAGE_NAME', PageNames.SCRATCHPAD);
  store.dispatch('SET_PAGE_STATE', {});
  store.dispatch('CORE_SET_PAGE_LOADING', false);
  store.dispatch('CORE_SET_ERROR', null);
}

function showContentUnavailable(store) {
  store.dispatch('SET_PAGE_NAME', PageNames.CONTENT_UNAVAILABLE);
  store.dispatch('SET_PAGE_STATE', {});
  store.dispatch('CORE_SET_PAGE_LOADING', false);
  store.dispatch('CORE_SET_ERROR', null);
}

module.exports = {
  redirectToExploreChannel,
  redirectToLearnChannel,
  showExploreChannel,
  showExploreTopic,
  showExploreContent,
  showLearnChannel,
  showLearnContent,
  showScratchpad,
  showContentUnavailable,
  triggerSearch,
  toggleSearch,
};
<|endoftext|>


<commit_before>const Resources = require('kolibri').resources.ContentNodeResource;
const constants = require('./constants');

const PageModes = constants.PageModes;
const PageNames = constants.PageNames;

function _crumbState(ancestors) {
  return ancestors.map((ancestor, index) => {
    if (index === 0) {
      return { id: 'root', title: 'Home' }; // TODO - I18N
    }
    return {
      id: ancestor.pk,
      title: ancestor.title,
    };
  });
}

function _topicState(data, includeCrumbs = true) {
  const state = {
    id: data.pk,
    title: data.title,
    description: data.description,
  };
  if (includeCrumbs) {
    state.breadcrumbs = _crumbState(data.ancestors);
  }
  return state;
}

function _contentState(data, includeCrumbs = true) {
  const state = {
    id: data.pk,
    title: data.title,
    description: data.description,
    thumbnail: data.thumbnail,
    files: data.files,
    progress: data.description ? data.description : 'unstarted',
  };
  if (includeCrumbs) {
    state.breadcrumbs = _crumbState(data.ancestors);
  }
  return state;
}

function navToExploreTopic(store, id) {
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_ROOT);
  store.dispatch('SET_PAGE_MODE', PageModes.EXPLORE);
  store.dispatch('SET_LOADING');

  const pageState = { id };

  Resources.getModel(id).fetch()
    .then((topicAttributes) => {
      pageState.topic = _topicState(topicAttributes);
      return Resources.getCollection({ parent: id }).fetch();
    })
    .then((topicChildren) => {
      pageState.subtopics = topicChildren
        .filter((item) => item.kind === 'topic')
        .map((item) => _topicState(item, false));
      pageState.contents = topicChildren
        .filter((item) => item.kind !== 'topic')
        .map((item) => _contentState(item, false));
      store.dispatch('SET_PAGE_STATE', pageState);
    })
    .catch((error) => {
      // TODO - how to parse and format?
      store.dispatch('SET_PAGE_ERROR', JSON.stringify(error, null, '\t'));
    });
}

function navToLearnRoot(store, toRoute, fromRoute) {
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_ROOT);
  store.dispatch('SET_PAGE_MODE', PageModes.LEARN);
}

function temp(store, toRoute, fromRoute) {
  console.log(store, toRoute, fromRoute);
}

module.exports = {
  navToExploreTopic,
  navToLearnRoot,
  temp,
};
<commit_msg>send requests in parallel<commit_after>const Resources = require('kolibri').resources.ContentNodeResource;
const constants = require('./constants');

const PageModes = constants.PageModes;
const PageNames = constants.PageNames;

function _crumbState(ancestors) {
  return ancestors.map((ancestor, index) => {
    if (index === 0) {
      return { id: 'root', title: 'Home' }; // TODO - I18N
    }
    return {
      id: ancestor.pk,
      title: ancestor.title,
    };
  });
}

function _topicState(data, includeCrumbs = true) {
  const state = {
    id: data.pk,
    title: data.title,
    description: data.description,
  };
  if (includeCrumbs) {
    state.breadcrumbs = _crumbState(data.ancestors);
  }
  return state;
}

function _contentState(data, includeCrumbs = true) {
  const state = {
    id: data.pk,
    title: data.title,
    description: data.description,
    thumbnail: data.thumbnail,
    files: data.files,
    progress: data.description ? data.description : 'unstarted',
  };
  if (includeCrumbs) {
    state.breadcrumbs = _crumbState(data.ancestors);
  }
  return state;
}

function navToExploreTopic(store, id) {
  store.dispatch('SET_PAGE_NAME', PageNames.EXPLORE_ROOT);
  store.dispatch('SET_PAGE_MODE', PageModes.EXPLORE);
  store.dispatch('SET_LOADING');

  const attributesPromise = Resources.getModel(id).fetch();
  const childrenPromise = Resources.getCollection({ parent: id }).fetch();

  Promise.all([attributesPromise, childrenPromise])
    .then(([attributes, children]) => {
      const pageState = { id };
      pageState.topic = _topicState(attributes);
      pageState.subtopics = children
        .filter((item) => item.kind === 'topic')
        .map((item) => _topicState(item, false));
      pageState.contents = children
        .filter((item) => item.kind !== 'topic')
        .map((item) => _contentState(item, false));
      store.dispatch('SET_PAGE_STATE', pageState);
    })
    .catch((error) => {
      // TODO - how to parse and format?
      store.dispatch('SET_PAGE_ERROR', JSON.stringify(error, null, '\t'));
    });
}

function navToLearnRoot(store, toRoute, fromRoute) {
  store.dispatch('SET_PAGE_NAME', PageNames.LEARN_ROOT);
  store.dispatch('SET_PAGE_MODE', PageModes.LEARN);
}

function temp(store, toRoute, fromRoute) {
  console.log(store, toRoute, fromRoute);
}

module.exports = {
  navToExploreTopic,
  navToLearnRoot,
  temp,
};
<|endoftext|>


<commit_before>/**
 * Mailvelope - secure email with OpenPGP encryption for Webmail
 * Copyright (C) 2012  Thomas Oberndörfer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

var mvelo = mvelo || null;

(function() {
  // communication to background page
  var port;
  // shares ID with DecryptFrame
  var id;
  var watermark;
  var spinnerTimer;
  var commonPath;
  var l10n;

  function init() {
    //console.log('init decryptInline.js');
    var qs = jQuery.parseQuerystring();
    id = 'dDialog-' + qs.id;
    // open port to background page
    port = mvelo.extension.connect({name: id});
    port.onMessage.addListener(messageListener);
    port.postMessage({event: 'decrypt-inline-init', sender: id});
    if (mvelo.crx) {
      commonPath = '../../..';
    } else if (mvelo.ffa) {
      commonPath = mvelo.extension._dataPath + 'common';

      var styleMvelo = $('<link/>', { rel: 'stylesheet', href: commonPath + '/ui/mvelo.css' });
      var styleBootstrap = $('<link/>', { rel: 'stylesheet', href: commonPath + '/dep/bootstrap/css/bootstrap.css' });
      var styleDecryptInline = $('<link/>', { rel: 'stylesheet', href: commonPath + '/ui/inline/dialogs/decryptInline.css' });
      $(document).contents().find('head').append(styleBootstrap);
      $(document).contents().find('head').append(styleMvelo);
      $(document).contents().find('head').append(styleDecryptInline);
    }
    addWrapper();
    addAttachmentPanel();
    addSandbox();
    mvelo.extension.sendMessage({event: "get-security-token"}, function(token) {
      $('#watermark').html(mvelo.util.encodeHTML(token.code));
    });
    $(window).on('resize', resizeFont);
    addErrorView();
    // show spinner
    spinnerTimer = setTimeout(showSpinner, 600);
    mvelo.l10n.getMessages([
      'alert_header_error'
    ], function(result) {
      l10n = result;
    });
  }

  function showSpinner() {
    $('body').addClass('spinner');
    if ($('body').height() + 2 > mvelo.LARGE_FRAME) {
      $('body').addClass('spinner-large');
    }
  }

  function addWrapper() {
    var wrapper = $('<div/>', {id: 'wrapper'});
    watermark = $('<div/>', {id: 'watermark'});
    watermark.appendTo(wrapper);
    wrapper.appendTo('body');
  }

  function addAttachmentPanel() {
    var attachments = $('<div/>', {
      id: 'attachments'
    });
    $('#wrapper').append(attachments);
  }

  function addSandbox() {
    var sandbox = $('<iframe/>', {
      id: 'decryptmail',
      sandbox: 'allow-same-origin',
      frameBorder: 0
    });
    var content = $('<div/>', {
      id: 'content',
      css: {
        position: 'absolute',
        top: '0',
        left: 0,
        right: 0,
        bottom: 0,
        padding: '3px',
        //'margin-top': '40px',
        'background-color': 'rgba(0,0,0,0)',
        overflow: 'auto'
      }
    });
    var style = $('<link/>', {
      rel: 'stylesheet',
      href: commonPath + '/dep/bootstrap/css/bootstrap.css'
    });
    sandbox.on('load', function() {
      $(this).contents().find('head').append(style);
      $(this).contents().find('body').css('background-color', 'rgba(0,0,0,0)');
      $(this).contents().find('body').append(content);
    });
    $('#wrapper').append(sandbox);
  }

  function addErrorView() {
    var errorbox = $('<div/>', {id: 'errorbox'});
    $('<div/>', {id: 'errorwell', class: 'well span5'}).appendTo(errorbox);
    errorbox.appendTo('body');
    if ($('body').height() + 2 > mvelo.LARGE_FRAME) {
      $('#errorbox').addClass('errorbox-large');
    }
  }

  function showMessageArea() {
    $('html, body').addClass('hide_bg');
    $('body').removeClass('spinner');
    $('#wrapper').addClass('fade-in');
    resizeFont();
  }

  function showErrorMsg(msg) {
    $('body').removeClass('spinner');
    clearTimeout(spinnerTimer);
    $('#errorbox').show();
    $('#errorwell').showAlert(l10n.alert_header_error, msg, 'danger')
                   .find('.alert').prepend($('<button/>', {type: 'button', class: 'close', html: '×'}))
                   .find('button').click(function() {
                      port.postMessage({event: 'decrypt-dialog-cancel', sender: id});
                    });
  }

  function resizeFont() {
    watermark.css('font-size', Math.floor(Math.min(watermark.width() / 3, watermark.height())));
  }

  function addAttachment(filename, content, mimeType, attachmentId) {
    var fileNameNoExt = mvelo.util.extractFileNameWithoutExt(filename);
    var fileExt = mvelo.util.extractFileExtension(filename);
    var extClass = mvelo.util.getExtensionClass(fileExt);

    var $extensionButton = $('<span/>', {
      "class": 'label attachmentExtension ' + extClass
    }).append(fileExt);

    var objectURL = "#";

    // workarround until ff36 is out, using addonsdk for file saving
    if (mvelo.crx) {
      var contentLength = Object.keys(content).length;
      var uint8Array = new Uint8Array(contentLength);
      for (var i = 0; i < contentLength; i++) {
        uint8Array[i] = content[i];
      }
      var blob = new Blob([uint8Array], { type: mimeType });
      objectURL = window.URL.createObjectURL(blob);
    }

    var $fileName = $('<span/>', {
      "class": 'filename'
    }).append(fileNameNoExt);

    var $fileUI = $('<a/>', {
        "download": filename,
        "href": objectURL,
        "title": filename,
        "class": 'attachmentButton'
      })
        .append($extensionButton)
        .append($fileName)
        .on("click", function(e) {
          // workarround for Firefox, using addonsdk for file saving
          //var version = navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox/") + 8, navigator.userAgent.length);
          if (mvelo.ffa) {
            e.preventDefault();
            port.postMessage({event: 'get-attachment', sender: id, attachmentId: attachmentId});
          }
        });

    $('#attachments').append($fileUI);
  }

  function messageListener(msg) {
    //console.log('decrypt dialog messageListener: ', JSON.stringify(msg));
    switch (msg.event) {
      case 'decrypted-message':
        showMessageArea();
        // js execution is prevented by Content Security Policy directive: "script-src 'self' chrome-extension-resource:"
        msg.message = $.parseHTML(msg.message);
        $('#decryptmail').contents().find('#content').append(msg.message);
        break;
      case 'add-decrypted-attachment':
        //console.log('popup adding decrypted attachment: ', JSON.stringify(msg.message));
        showMessageArea();
        addAttachment(msg.message.filename, msg.message.content, msg.message.mimeType, msg.message.attachmentId);
        break;
      case 'error-message':
        showErrorMsg(msg.error);
        break;
      default:
        console.log('unknown event');
    }
  }

  $(document).ready(init);

}());
<commit_msg>implementing attachment download in two different ways according to the ff version (ie < v36) removing unneeded css inclusion<commit_after>/**
 * Mailvelope - secure email with OpenPGP encryption for Webmail
 * Copyright (C) 2012  Thomas Oberndörfer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

var mvelo = mvelo || null;

(function() {
  // communication to background page
  var port;
  // shares ID with DecryptFrame
  var id;
  var watermark;
  var spinnerTimer;
  var commonPath;
  var l10n;

  function init() {
    //console.log('init decryptInline.js');
    var qs = jQuery.parseQuerystring();
    id = 'dDialog-' + qs.id;
    // open port to background page
    port = mvelo.extension.connect({name: id});
    port.onMessage.addListener(messageListener);
    port.postMessage({event: 'decrypt-inline-init', sender: id});
    if (mvelo.crx) {
      commonPath = '../../..';
    } else if (mvelo.ffa) {
      commonPath = mvelo.extension._dataPath + 'common';
    }
    addWrapper();
    addAttachmentPanel();
    addSandbox();
    mvelo.extension.sendMessage({event: "get-security-token"}, function(token) {
      $('#watermark').html(mvelo.util.encodeHTML(token.code));
    });
    $(window).on('resize', resizeFont);
    addErrorView();
    // show spinner
    spinnerTimer = setTimeout(showSpinner, 600);
    mvelo.l10n.getMessages([
      'alert_header_error'
    ], function(result) {
      l10n = result;
    });
  }

  function showSpinner() {
    $('body').addClass('spinner');
    if ($('body').height() + 2 > mvelo.LARGE_FRAME) {
      $('body').addClass('spinner-large');
    }
  }

  function addWrapper() {
    var wrapper = $('<div/>', {id: 'wrapper'});
    watermark = $('<div/>', {id: 'watermark'});
    watermark.appendTo(wrapper);
    wrapper.appendTo('body');
  }

  function addAttachmentPanel() {
    var attachments = $('<div/>', {
      id: 'attachments'
    });
    $('#wrapper').append(attachments);
  }

  function addSandbox() {
    var sandbox = $('<iframe/>', {
      id: 'decryptmail',
      sandbox: 'allow-same-origin',
      frameBorder: 0
    });
    var content = $('<div/>', {
      id: 'content',
      css: {
        position: 'absolute',
        top: '0',
        left: 0,
        right: 0,
        bottom: 0,
        padding: '3px',
        //'margin-top': '40px',
        'background-color': 'rgba(0,0,0,0)',
        overflow: 'auto'
      }
    });
    var style = $('<link/>', {
      rel: 'stylesheet',
      href: commonPath + '/dep/bootstrap/css/bootstrap.css'
    });
    sandbox.on('load', function() {
      $(this).contents().find('head').append(style);
      $(this).contents().find('body').css('background-color', 'rgba(0,0,0,0)');
      $(this).contents().find('body').append(content);
    });
    $('#wrapper').append(sandbox);
  }

  function addErrorView() {
    var errorbox = $('<div/>', {id: 'errorbox'});
    $('<div/>', {id: 'errorwell', class: 'well span5'}).appendTo(errorbox);
    errorbox.appendTo('body');
    if ($('body').height() + 2 > mvelo.LARGE_FRAME) {
      $('#errorbox').addClass('errorbox-large');
    }
  }

  function showMessageArea() {
    $('html, body').addClass('hide_bg');
    $('body').removeClass('spinner');
    $('#wrapper').addClass('fade-in');
    resizeFont();
  }

  function showErrorMsg(msg) {
    $('body').removeClass('spinner');
    clearTimeout(spinnerTimer);
    $('#errorbox').show();
    $('#errorwell').showAlert(l10n.alert_header_error, msg, 'danger')
                   .find('.alert').prepend($('<button/>', {type: 'button', class: 'close', html: '×'}))
                   .find('button').click(function() {
                      port.postMessage({event: 'decrypt-dialog-cancel', sender: id});
                    });
  }

  function resizeFont() {
    watermark.css('font-size', Math.floor(Math.min(watermark.width() / 3, watermark.height())));
  }

  function addAttachment(filename, content, mimeType, attachmentId) {
    var fileNameNoExt = mvelo.util.extractFileNameWithoutExt(filename);
    var fileExt = mvelo.util.extractFileExtension(filename);
    var extClass = mvelo.util.getExtensionClass(fileExt);

    var $extensionButton = $('<span/>', {
      "class": 'label attachmentExtension ' + extClass
    }).append(fileExt);

    var objectURL = "#";

    var contentLength = Object.keys(content).length;
    var uint8Array = new Uint8Array(contentLength);
    for (var i = 0; i < contentLength; i++) {
      uint8Array[i] = content[i];
    }
    var blob = new Blob([uint8Array], { type: mimeType });
    objectURL = window.URL.createObjectURL(blob);

    var $fileName = $('<span/>', {
      "class": 'filename'
    }).append(fileNameNoExt);

    var $fileUI = $('<a/>', {
        "download": filename,
        "href": objectURL,
        "title": filename,
        "class": 'attachmentButton'
      })
        .append($extensionButton)
        .append($fileName);

    //var firefoxVersion = parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox/") + 8, navigator.userAgent.length));
    if (mvelo.ffa && mvelo.getFirefoxVersion() < 36) {
      $fileUI.on("click", function(e) {
        e.preventDefault();
        port.postMessage({event: 'get-attachment', sender: id, attachmentId: attachmentId});
      });
    }

    $('#attachments').append($fileUI);
  }

  function messageListener(msg) {
    //console.log('decrypt dialog messageListener: ', JSON.stringify(msg));
    switch (msg.event) {
      case 'decrypted-message':
        showMessageArea();
        // js execution is prevented by Content Security Policy directive: "script-src 'self' chrome-extension-resource:"
        msg.message = $.parseHTML(msg.message);
        $('#decryptmail').contents().find('#content').append(msg.message);
        break;
      case 'add-decrypted-attachment':
        //console.log('popup adding decrypted attachment: ', JSON.stringify(msg.message));
        showMessageArea();
        addAttachment(msg.message.filename, msg.message.content, msg.message.mimeType, msg.message.attachmentId);
        break;
      case 'error-message':
        showErrorMsg(msg.error);
        break;
      default:
        console.log('unknown event');
    }
  }

  $(document).ready(init);

}());
<|endoftext|>


<commit_before>import React from 'react';
import { TYPE_NAME } from 'constants/replyType';
import ArticleReplySummary from './ArticleReplySummary';

export default {
  title: 'ArticleReplySummary',
  component: 'ArticleReplySummary',
};

const MOCK_USER = {
  level: 10,
  id: 'test-user',
  name: 'The user',
};

export const DifferentReplyTypes = () => (
  <>
    <ArticleReplySummary
      articleReply={{
        replyType: 'NOT_RUMOR',
        user: MOCK_USER,
      }}
    />
    <ArticleReplySummary
      articleReply={{
        replyType: 'RUMOR',
        user: MOCK_USER,
      }}
    />
    <ArticleReplySummary
      articleReply={{
        replyType: 'OPINIONATED',
        user: MOCK_USER,
      }}
    />
    <ArticleReplySummary
      articleReply={{
        replyType: 'NOT_ARTICLE',
        user: MOCK_USER,
      }}
    />
  </>
);

export const NoValidUser = () => (
  <ArticleReplySummary
    articleReply={{
      replyType: 'NOT_RUMOR',
      user: null,
    }}
  />
);
<commit_msg>[ArticleReplySummary] remove redundant import in storybook<commit_after>import React from 'react';
import ArticleReplySummary from './ArticleReplySummary';

export default {
  title: 'ArticleReplySummary',
  component: 'ArticleReplySummary',
};

const MOCK_USER = {
  level: 10,
  id: 'test-user',
  name: 'The user',
};

export const DifferentReplyTypes = () => (
  <>
    <ArticleReplySummary
      articleReply={{
        replyType: 'NOT_RUMOR',
        user: MOCK_USER,
      }}
    />
    <ArticleReplySummary
      articleReply={{
        replyType: 'RUMOR',
        user: MOCK_USER,
      }}
    />
    <ArticleReplySummary
      articleReply={{
        replyType: 'OPINIONATED',
        user: MOCK_USER,
      }}
    />
    <ArticleReplySummary
      articleReply={{
        replyType: 'NOT_ARTICLE',
        user: MOCK_USER,
      }}
    />
  </>
);

export const NoValidUser = () => (
  <ArticleReplySummary
    articleReply={{
      replyType: 'NOT_RUMOR',
      user: null,
    }}
  />
);
<|endoftext|>


<commit_before>import React from "react";
import { FormattedMessage } from "react-intl";
import PropTypes from "prop-types";
import ComponentTypeIcons from "./ComponentTypeIcons";
import ComponentSummaryList from "./ComponentSummaryList";

class ListItemComponents extends React.Component {
  constructor() {
    super();
    this.state = { expanded: false };
  }

  componentWillReceiveProps(newProps) {
    // compare old value to new value, and if this component is getting new data,
    // then get the current expand state of the new value as it is in the old dom
    // and apply that expand state to this component
    const olditem = this.props.listItem.name;
    const newitem = newProps.listItem.name;
    const parent = this.props.listItemParent;
    if (olditem !== newitem) {
      if ($(`.${parent} [data-component="${newitem.name}"]`).hasClass("active")) {
        this.setState({ expanded: true });
      } else {
        this.setState({ expanded: false });
      }
    }
    if (this.state.expanded === true && newProps.listItem.dependencies === undefined) {
      this.props.fetchDetails(newProps.listItem);
    }
  }

  handleExpandComponent(event) {
    // the user clicked a list item in the blueprint contents area to expand or collapse
    if (!$(event.target).is("button, a, input, .fa-ellipsis-v")) {
      const expandState = !this.state.expanded;
      this.setState(prevState => ({ expanded: !prevState.expanded }));
      if (expandState === true && this.props.listItem.dependencies === undefined) {
        this.props.fetchDetails(this.props.listItem);
      }
    }
  }

  render() {
    const { listItem, noEditComponent, handleComponentDetails, handleRemoveComponent } = this.props;
    const { expanded } = this.state;
    return (
      <div className={`list-pf-item ${expanded ? "active" : ""}`} data-component={listItem.name}>

 this.handleExpandComponent(e)} role="presentation">

            <span className={`fa ${expanded ? "fa-angle-down" : "fa-angle-right"}`} />

            <input type="checkbox" />

              <ComponentTypeIcons
                componentType={listItem.ui_type}
                componentInBlueprint={listItem.inBlueprint}
                isSelected={listItem.userSelected}
              />

                   handleComponentDetails(e, listItem)}>
                    {listItem.name}

{listItem.summary}

                  <FormattedMessage
                    defaultMessage="Version {version}"
                    values={{
                      version: {listItem.version}
                    }}
                  />

                  <FormattedMessage
                    defaultMessage="Release {release}"
                    values={{
                      release: {listItem.release}
                    }}
                  />

            {noEditComponent !== true && (

                  <button
                    className="btn btn-link dropdown-toggle"
                    type="button"
                    id="dropdownKebabRight9"
                    data-toggle="dropdown"
                    aria-haspopup="true"
                    aria-expanded="true"
                  >

                  </button>

                       handleComponentDetails(e, listItem)}>
                        <FormattedMessage defaultMessage="View" />

                    {listItem.inBlueprint && listItem.userSelected && (

                         handleRemoveComponent(e, listItem.name)}>
                          <FormattedMessage defaultMessage="Remove" />

                    )}

            )}

        <div className={`list-pf-expansion collapse ${expanded ? "in" : ""}`}>

                        <FormattedMessage defaultMessage="Version" />

{listItem.version ? listItem.version :  }

                        <FormattedMessage defaultMessage="Release" />

{listItem.release ? listItem.release :  }

URL

                      {(listItem.homepage != null && (

                            {listItem.homepage}

                      )) ||

}

                    {listItem.dependencies && <ComponentSummaryList listItems={listItem.dependencies} />}

    );
  }
}

ListItemComponents.propTypes = {
  listItem: PropTypes.shape({
    arch: PropTypes.string,
    epoch: PropTypes.number,
    inBlueprint: PropTypes.bool,
    name: PropTypes.string,
    summary: PropTypes.string,
    release: PropTypes.string,
    ui_type: PropTypes.string,
    userSelected: PropTypes.bool,
    version: PropTypes.string,
    homepage: PropTypes.arrayOf(PropTypes.string),
    dependencies: PropTypes.arrayOf(PropTypes.object)
  }),
  listItemParent: PropTypes.string,
  componentDetailsParent: PropTypes.shape({
    active: PropTypes.bool,
    group_type: PropTypes.string,
    inBlueprint: PropTypes.bool,
    name: PropTypes.string,
    release: PropTypes.string,
    releaseSelected: PropTypes.string,
    summary: PropTypes.string,
    ui_type: PropTypes.string,
    userSelected: PropTypes.bool,
    version: PropTypes.string,
    versionSelected: PropTypes.string
  }),
  handleComponentDetails: PropTypes.func,
  handleRemoveComponent: PropTypes.func,
  noEditComponent: PropTypes.bool,
  fetchDetails: PropTypes.func
};

ListItemComponents.defaultProps = {
  listItem: {},
  listItemParent: "",
  componentDetailsParent: {},
  handleComponentDetails: function() {},
  handleRemoveComponent: function() {},
  noEditComponent: false,
  fetchDetails: function() {}
};

export default ListItemComponents;
<commit_msg>Fix wrong PropType for homepage<commit_after>import React from "react";
import { FormattedMessage } from "react-intl";
import PropTypes from "prop-types";
import ComponentTypeIcons from "./ComponentTypeIcons";
import ComponentSummaryList from "./ComponentSummaryList";

class ListItemComponents extends React.Component {
  constructor() {
    super();
    this.state = { expanded: false };
  }

  componentWillReceiveProps(newProps) {
    // compare old value to new value, and if this component is getting new data,
    // then get the current expand state of the new value as it is in the old dom
    // and apply that expand state to this component
    const olditem = this.props.listItem.name;
    const newitem = newProps.listItem.name;
    const parent = this.props.listItemParent;
    if (olditem !== newitem) {
      if ($(`.${parent} [data-component="${newitem.name}"]`).hasClass("active")) {
        this.setState({ expanded: true });
      } else {
        this.setState({ expanded: false });
      }
    }
    if (this.state.expanded === true && newProps.listItem.dependencies === undefined) {
      this.props.fetchDetails(newProps.listItem);
    }
  }

  handleExpandComponent(event) {
    // the user clicked a list item in the blueprint contents area to expand or collapse
    if (!$(event.target).is("button, a, input, .fa-ellipsis-v")) {
      const expandState = !this.state.expanded;
      this.setState(prevState => ({ expanded: !prevState.expanded }));
      if (expandState === true && this.props.listItem.dependencies === undefined) {
        this.props.fetchDetails(this.props.listItem);
      }
    }
  }

  render() {
    const { listItem, noEditComponent, handleComponentDetails, handleRemoveComponent } = this.props;
    const { expanded } = this.state;
    return (
      <div className={`list-pf-item ${expanded ? "active" : ""}`} data-component={listItem.name}>

 this.handleExpandComponent(e)} role="presentation">

            <span className={`fa ${expanded ? "fa-angle-down" : "fa-angle-right"}`} />

            <input type="checkbox" />

              <ComponentTypeIcons
                componentType={listItem.ui_type}
                componentInBlueprint={listItem.inBlueprint}
                isSelected={listItem.userSelected}
              />

                   handleComponentDetails(e, listItem)}>
                    {listItem.name}

{listItem.summary}

                  <FormattedMessage
                    defaultMessage="Version {version}"
                    values={{
                      version: {listItem.version}
                    }}
                  />

                  <FormattedMessage
                    defaultMessage="Release {release}"
                    values={{
                      release: {listItem.release}
                    }}
                  />

            {noEditComponent !== true && (

                  <button
                    className="btn btn-link dropdown-toggle"
                    type="button"
                    id="dropdownKebabRight9"
                    data-toggle="dropdown"
                    aria-haspopup="true"
                    aria-expanded="true"
                  >

                  </button>

                       handleComponentDetails(e, listItem)}>
                        <FormattedMessage defaultMessage="View" />

                    {listItem.inBlueprint && listItem.userSelected && (

                         handleRemoveComponent(e, listItem.name)}>
                          <FormattedMessage defaultMessage="Remove" />

                    )}

            )}

        <div className={`list-pf-expansion collapse ${expanded ? "in" : ""}`}>

                        <FormattedMessage defaultMessage="Version" />

{listItem.version ? listItem.version :  }

                        <FormattedMessage defaultMessage="Release" />

{listItem.release ? listItem.release :  }

URL

                      {(listItem.homepage != null && (

                            {listItem.homepage}

                      )) ||

}

                    {listItem.dependencies && <ComponentSummaryList listItems={listItem.dependencies} />}

    );
  }
}

ListItemComponents.propTypes = {
  listItem: PropTypes.shape({
    arch: PropTypes.string,
    epoch: PropTypes.number,
    inBlueprint: PropTypes.bool,
    name: PropTypes.string,
    summary: PropTypes.string,
    release: PropTypes.string,
    ui_type: PropTypes.string,
    userSelected: PropTypes.bool,
    version: PropTypes.string,
    homepage: PropTypes.string,
    dependencies: PropTypes.arrayOf(PropTypes.object)
  }),
  listItemParent: PropTypes.string,
  componentDetailsParent: PropTypes.shape({
    active: PropTypes.bool,
    group_type: PropTypes.string,
    inBlueprint: PropTypes.bool,
    name: PropTypes.string,
    release: PropTypes.string,
    releaseSelected: PropTypes.string,
    summary: PropTypes.string,
    ui_type: PropTypes.string,
    userSelected: PropTypes.bool,
    version: PropTypes.string,
    versionSelected: PropTypes.string
  }),
  handleComponentDetails: PropTypes.func,
  handleRemoveComponent: PropTypes.func,
  noEditComponent: PropTypes.bool,
  fetchDetails: PropTypes.func
};

ListItemComponents.defaultProps = {
  listItem: {},
  listItemParent: "",
  componentDetailsParent: {},
  handleComponentDetails: function() {},
  handleRemoveComponent: function() {},
  noEditComponent: false,
  fetchDetails: function() {}
};

export default ListItemComponents;
<|endoftext|>


<commit_before>Polymer({
  is: 'oudjo-library',

  ready: function() {
    this.tab = 'songs';
  }
});
<commit_msg>oudjo-library fetches library data<commit_after>Polymer({
  is: 'oudjo-library',

  properties: {
    library: {
      type: Array
    }
  },

  ready: function() {
    this.tab = 'songs';

    fetch('/library')
      .then(function(response) {
        return response.json();
      }).then(function(json) {
        this.library = json;
      }.bind(this));
  }
});
<|endoftext|>


<commit_before>define(["github/adioo/bind/v0.2.0/bind", "github/adioo/events/v0.1.0/events", "/jquery.js"], function(Bind, Events) {

    function List(module) {

        var self;
        var config;
        var container;
        var template;

        function processConfig(config) {
            config.options = config.options || {};
            config.template.binds = config.template.binds || [];

            var optClasses = config.options.classes || {}
            optClasses.item = optClasses.item || "item";
            optClasses.selected = optClasses.selected || "selected";
            config.options.classes = optClasses;

            return config;
        }

        function init(conf) {

            // initialize the globals
            self = this;
            config = processConfig(conf);
            if (config.container) {
                container = $(config.container, module.dom);
            } else {
                container = module.dom;
            }
            template = $(config.template.value, module.dom);

            // **************************************
            // generate general binds from the config
            var binds = [];

            for (var i in config.controls) {
                switch (i) {
                    case "add":
                        binds.push({
                            target: ".create",
                            context: ".controls",
                            on: [{
                                name: "click",
                                emit: "requestNewItem"
                            }]
                        });
                        break;
                    case "delete":
                        binds.push({
                            target: ".delete",
                            context: ".controls",
                            on: [{
                                name: "click",
                                handler: "removeSelected"
                            }]
                        });
                        break;
                }
            }

            // run the internal binds
            for (var i in binds) {
                Bind.call(self, binds[i]);
            }

            // run the binds
            for (var i in config.binds) {
                Bind.call(self, config.binds[i]);
            }

            self.on("newItem", createItem);

            Events.call(self, config);

            if (config.options.autofetch) {
                self.read();
            }
        }

        function render(item) {
            switch (config.template.type) {
                case "selector":
                    renderSelector.call(self, item);
                case "html":
                    // TODO
                case "url":
                    // TODO
            }
        }

        function renderSelector(item) {
            var newItem = $(template).clone();
            newItem
                .removeClass("template")
                .addClass(config.options.classes.item)
                .appendTo(container)
                .show();

            for (var i in config.template.binds) {
                var bindObj = config.template.binds[i];
                bindObj.context = newItem;
                Bind.call(self, bindObj, item);
            }
        }

        function clearList() {
            $("." + config.options.classes.item, container).remove();
        }

        // ********************************
        // Public functions ***************
        // ********************************

        function read(data) {

            clearList();

            self.link(config.crud.read, { data: data }, function(err, data) {

                if (err) { return; }

                for (var i in data) {
                    render.call(self, data[i]);
                }
            });
        }

        function createItem(itemData) {
            self.link(config.crud.create, { data: itemData }, function(err, data) {
                if (err) { return; }
            });
        }

        function removeItem(itemData) {
            self.link(config.crud.delete, { data: { id: itemData.id } }, function(err, data) {
                if (err) { return; }
                $("#" + itemData.id).remove();
            });
        }

        function removeSelected() {
            var ids = [];
            var selectedClass = config.options.classes.selected;
            $("." + selectedClass, container).each(function() {
                ids.push($(this).attr("id"));
            });

            self.link(config.crud.delete, { data: { ids: ids } }, function(err, data) {
                if (err) { return; }
                $("." + selectedClass, container).remove();
            });
        }

        function selectItem(dataItem) {
            var selectedClass = config.options.classes.selected;

            switch (config.options.selection) {

                case "single":
                    var currentItem = $("#" + dataItem.id, container);
                    if (currentItem.hasClass(selectedClass)) {
                        break;
                    }

                    $("." + selectedClass, container).removeClass(selectedClass);
                    $("#" + dataItem.id, container).addClass(selectedClass);
                    self.emit("selectionChanged", dataItem);
                    break;

                case "multiple":
                    $("#" + dataItem.id, module.dom).toggleClass(selectedClass);
                    break;

                default: // none
            }
        }

        function show() {
            $(self.dom).parent().show();
        }

        function hide() {
            $(self.dom).parent().hide();
        }

         return {
            init: init,
            read: read,
            removeItem: removeItem,
            removeSelected: removeSelected,
            selectItem: selectItem,
            show: show,
            hide: hide
        };
    }

    return function(module, config) {

        var list = new List(module);
        for (var i in list) {
            list[i] = module[i] || list[i];
        }
        list = Object.extend(list, module);

        list.init(config);

        return list;
    }
});

<commit_msg>exporting createItem; reading 'controls' classes from the configuration<commit_after>define(["github/adioo/bind/v0.2.0/bind", "github/adioo/events/v0.1.0/events", "/jquery.js"], function(Bind, Events) {

    function List(module) {

        var self;
        var config;
        var container;
        var template;

        function processConfig(config) {
            config.options = config.options || {};
            config.template.binds = config.template.binds || [];

            var optClasses = config.options.classes || {}
            optClasses.item = optClasses.item || "item";
            optClasses.selected = optClasses.selected || "selected";
            config.options.classes = optClasses;

            return config;
        }

        function init(conf) {

            // initialize the globals
            self = this;
            config = processConfig(conf);
            if (config.container) {
                container = $(config.container, module.dom);
            } else {
                container = module.dom;
            }
            template = $(config.template.value, module.dom);

            // **************************************
            // generate general binds from the config
            var binds = [];

            for (var i in config.controls) {
                switch (i) {
                    case "add":
                        binds.push({
                            target: config.controls[i],
                            context: ".controls",
                            on: [{
                                name: "click",
                                emit: "requestNewItem"
                            }]
                        });
                        break;
                    case "delete":
                        binds.push({
                            target: config.controls[i],
                            context: ".controls",
                            on: [{
                                name: "click",
                                handler: "removeSelected"
                            }]
                        });
                        break;
                }
            }

            // run the internal binds
            for (var i in binds) {
                Bind.call(self, binds[i]);
            }

            // run the binds
            for (var i in config.binds) {
                Bind.call(self, config.binds[i]);
            }

            Events.call(self, config);

            if (config.options.autofetch) {
                self.read();
            }
        }

        function render(item) {
            switch (config.template.type) {
                case "selector":
                    renderSelector.call(self, item);
                case "html":
                    // TODO
                case "url":
                    // TODO
            }
        }

        function renderSelector(item) {
            var newItem = $(template).clone();
            newItem
                .removeClass("template")
                .addClass(config.options.classes.item)
                .appendTo(container)
                .show();

            for (var i in config.template.binds) {
                var bindObj = config.template.binds[i];
                bindObj.context = newItem;
                Bind.call(self, bindObj, item);
            }
        }

        function clearList() {
            $("." + config.options.classes.item, container).remove();
        }

        // ********************************
        // Public functions ***************
        // ********************************

        function read(data) {

            clearList();

            self.link(config.crud.read, { data: data }, function(err, data) {

                if (err) { return; }

                for (var i in data) {
                    render.call(self, data[i]);
                }
            });
        }

        function createItem(itemData) {
            self.link(config.crud.create, { data: itemData }, function(err, data) {
                if (err) { return; }
                render.call(self, data);
            });
        }

        function removeItem(itemData) {
            self.link(config.crud.delete, { data: { id: itemData.id } }, function(err, data) {
                if (err) { return; }
                $("#" + itemData.id).remove();
            });
        }

        function removeSelected() {
            var ids = [];
            var selectedClass = config.options.classes.selected;
            $("." + selectedClass, container).each(function() {
                ids.push($(this).attr("id"));
            });

            self.link(config.crud.delete, { data: { ids: ids } }, function(err, data) {
                if (err) { return; }
                $("." + selectedClass, container).remove();
            });
        }

        function selectItem(dataItem) {
            var selectedClass = config.options.classes.selected;

            switch (config.options.selection) {

                case "single":
                    var currentItem = $("#" + dataItem.id, container);
                    if (currentItem.hasClass(selectedClass)) {
                        break;
                    }

                    $("." + selectedClass, container).removeClass(selectedClass);
                    $("#" + dataItem.id, container).addClass(selectedClass);
                    self.emit("selectionChanged", dataItem);
                    break;

                case "multiple":
                    $("#" + dataItem.id, module.dom).toggleClass(selectedClass);
                    break;

                default: // none
            }
        }

        function show() {
            $(self.dom).parent().show();
        }

        function hide() {
            $(self.dom).parent().hide();
        }

         return {
            init: init,
            read: read,
            createItem: createItem,
            removeItem: removeItem,
            removeSelected: removeSelected,
            selectItem: selectItem,
            show: show,
            hide: hide
        };
    }

    return function(module, config) {

        var list = new List(module);
        for (var i in list) {
            list[i] = module[i] || list[i];
        }
        list = Object.extend(list, module);

        list.init(config);

        return list;
    }
});

<|endoftext|>


<commit_before>//Requires for the other roles and modules

//Roles
var roleHarvester = require('role.harvester');
var roleMiner = require('role.miner');
var roleHauler = require('role.hauler');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepair = require('role.repair');
var roleArchitect = require('role.architect');
var roleFeeder = require('role.feeder');

//Modules
var modSpawning = require('module.spawning');
var modCommon = require('module.common');
var modStructures = require('module.structures');

//Initial memory JSON for the roles
//includes counters for roles and maxes
var initialRolesMem = {
    "numCreeps":0,
    "numHarvesters":0,
    "maxHarvesters":1,
    "numUpgraders":0,
    "maxUpgraders":0,
    "numBuilders":0,
    "maxBuilders":1,
    "numRepair":0,
    "maxRepair":1,
    "numArchitects":0,
    "betterHarvesters1":0,
    "betterHarvesters2":0,
    "numMiners":0,
    "maxMiners":0,
    "numHaulers":0,
    "maxHaulers":1,
    "numFeeders":0,
    "maxFeeders":1

};

//Tower initial memory JSON
var initialTowerMem = {
  "target":null,
  "mode":"attack",
  "fixe":null
};

//Set all the above JSONs into memeory on first start
function initialize(){
  //TODO make these per room
  Memory.roles = initialRolesMem;
  Memory.towersMem = initialTowerMem;
  Memory.initialized = true;
  Memory.conservation = false;
  Memory.fortify = false;
}

//Gets the number of living harvester Creeps
function getNumHarvesters(creepList){
  var harvesters = _.filter(creepList, (creep) => creep.memory.role == 'harvester');
  var hL = harvesters.length;
  if(Memory.roles.numHarvesters != hL){
    Memory.roles.numHarvesters = hL;
    console.log('Harvesters: ' + hL);
  }
  return hL;
}

//Gets the number of living upgrader Creeps
function getNumUpgraders(creepList){
  var upgraders = _.filter(creepList, (creep) => creep.memory.role == 'upgrader');
  var uL = upgraders.length;
  if(Memory.roles.numUpgraders != uL){
    Memory.roles.numUpgraders = uL;
    console.log('Upgraders: ' + uL);
  }
  return uL;
}

//Gets the number of living builder Creeps
function getNumBuilders(creepList){
  var builders = _.filter(creepList, (creep) => creep.memory.role == 'builder');
  var bL = builders.length;
  if(Memory.roles.numBuilders != bL){
    Memory.roles.numBuilders = bL;
    console.log('Builders: ' + bL);
  }
  return bL;
}

//Gets the number of living Repair Creeps
function getNumRepair(creepList){
  var repair = _.filter(creepList, (creep) => creep.memory.role == 'repair');
  var rL = repair.length;
  if(Memory.roles.numRepair != rL){
    Memory.roles.numRepair = rL;
    console.log('Repair: ' + rL);
  }
  return rL;
}

//Gets the number of living architect Creeps
function getNumArchitects(creepList){
  var architects = _.filter(creepList, (creep) => creep.memory.role == 'architect');
  var aL = architects.length;
  if(Memory.roles.numArchitects != aL){
    Memory.roles.numArchitects = aL;
    console.log('Architects: ' + aL);
  }
  return aL;
}

//Gets the number of living miner Creeps
function getNumMiners(creepList){
  var miners = _.filter(creepList, (creep) => creep.memory.role == 'miner');
  var mL = miners.length;
  if(Memory.roles.numMiners != mL){
    Memory.roles.numMiners = mL;
    console.log('Miners: ' + mL);
  }
  return mL;
}

//Gets the number of living hauler Creeps
function getNumHaulers(creepList){
  var haulers = _.filter(creepList, (creep) => creep.memory.role == 'hauler');
  var haulL = haulers.length;
  if(Memory.roles.numHaulers != haulL){
    Memory.roles.numHaulers = haulL;
    console.log('Haulers: ' + haulL);
  }
  return haulL;
}

function getNumFeeders(creepList){
  var feeders = _.filter(creepList, (creep) => creep.memory.role == 'feeder');
  var feedL = feeders.length;
  if(Memory.roles.numFeeders != feedL){
    Memory.roles.numFeeders = feedL;
    console.log('Haulers: ' + feedL);
  }
  return feedL;
}

//main loop
module.exports.loop = function () {

  //Only initialize if it hasnt been done (or it was manually set to false)
  if(Memory.initialized!==true){
    initialize();
  }

  //Loop to check each room that is visible to the script
  for(var roomName in Game.rooms){
    var room = Game.rooms[roomName];

    if(Memory.fortify && (!room.controller.safeMode || room.controller.safeMode<1000)){
      Memory.fortify = false;
    }

    //Creep lists in each room, comparing lengths shows if there are 'others'
    var allCreepList = room.find(FIND_CREEPS);
    var myCreepList = _.filter(allCreepList, (creep) => (creep.owner && creep.owner.username ==="PCarton"));
    var enemyPresent = allCreepList.length>myCreepList.length;

    //Al the structures in the room that are controlled by the player
    var allStructs = room.find(FIND_MY_STRUCTURES);
    var towers = _.filter(allStructs, (struct) => struct.structureType === STRUCTURE_TOWER);

    //calculates the breakdown of creeps by roles
    /* var h  = getNumHarvesters(myCreepList);
    var u = getNumUpgraders(myCreepList);
    var b = getNumBuilders(myCreepList);
    var r = getNumRepair(myCreepList);
    var a = getNumArchitects(myCreepList);
    var m = getNumMiners(myCreepList);
    var ha = getNumHaulers(myCreepList);
    var f = getNumFeeders(myCreepList);
    Memory.roles.numCreeps = h + u + b + r + a + m + ha + f;
    */

    //Clear dead creeps from memory
    modCommon.clearDead();

    //assign the right run method to each creep based on its role
    for(var name in myCreepList) {
        var creep = myCreepList[name];

        //Has the non-military creeps retreat
        //Mining creeps are considered military - like the supply line
        if(enemyPresent && creep.memory.military !== true){
          modCommon.retreat(creep);
        }
        //If there are no enemies, run the appropriate role method
        else if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        else if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        else if(creep.memory.role == 'builder'){
          roleBuilder.run(creep);
        }
        else if(creep.memory.role == 'repair'){
          roleRepair.run(creep);
        }
        else if(creep.memory.role == 'architect'){
          roleArchitect.run(creep);
        }
        else if(creep.memory.role == 'miner'){
          roleMiner.run(creep);
        }
        else if(creep.memory.role == 'hauler'){
          roleHauler.run(creep);
        }
        else if(creep.memory.role == 'feeder'){
          roleFeeder.run(creep);
        }
    }

    //determine if new creeps need to be spawned and pick an appropriate spawner
    //Spawn logic is in a seperate module
    if(Memory.roles.numCreeps < modSpawning.maxCreeps){
        for(var spawn in Game.spawns){
          var spawner = Game.spawns[spawn];
          var controllerLvl= spawner.room.controller.level;
          var energyCapacity = spawner.room.energyCapacityAvailable;
          modSpawning.spawn(spawner,energyCapacity,controllerLvl);

        }
    }

    var control = room.controller;

    if(enemyPresent && modCommon.playerAttack(allCreepList) && !(control.safeMode || control.safeModeCooldown) && control.safeModeAvailable > 0 ){
      control.activateSafeMode();
      Memory.fortify = true;
      Game.notify("Activated Safe Mode");
    }

    //Variable to keep track of which enemy to shoot
    var target = Game.getObjectById(Memory.towersMem.target);

    //Notify the user on enemies or switch to healing and repairing
    if(enemyPresent){
      Memory.towersMem.mode = "attack";
      Game.notify("EnemyFound at "+ Game.time.toString(),60);
    }else{
      Memory.towersMem.mode = "heal";
    }

    //Run through the towers, picking a target if needed
    for(var towerName in towers){
      var t = towers[towerName];
      if(enemyPresent && (target===null || target.room !== t.room)){
        modStructures.pickTargets(t.room.controller, allCreepList);
      }
      modStructures.runTower(t,allCreepList);
    }
  }
};
<commit_msg>added time notification to Safe Mode<commit_after>//Requires for the other roles and modules

//Roles
var roleHarvester = require('role.harvester');
var roleMiner = require('role.miner');
var roleHauler = require('role.hauler');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepair = require('role.repair');
var roleArchitect = require('role.architect');
var roleFeeder = require('role.feeder');

//Modules
var modSpawning = require('module.spawning');
var modCommon = require('module.common');
var modStructures = require('module.structures');

//Initial memory JSON for the roles
//includes counters for roles and maxes
var initialRolesMem = {
    "numCreeps":0,
    "numHarvesters":0,
    "maxHarvesters":1,
    "numUpgraders":0,
    "maxUpgraders":0,
    "numBuilders":0,
    "maxBuilders":1,
    "numRepair":0,
    "maxRepair":1,
    "numArchitects":0,
    "betterHarvesters1":0,
    "betterHarvesters2":0,
    "numMiners":0,
    "maxMiners":0,
    "numHaulers":0,
    "maxHaulers":1,
    "numFeeders":0,
    "maxFeeders":1

};

//Tower initial memory JSON
var initialTowerMem = {
  "target":null,
  "mode":"attack",
  "fixe":null
};

//Set all the above JSONs into memeory on first start
function initialize(){
  //TODO make these per room
  Memory.roles = initialRolesMem;
  Memory.towersMem = initialTowerMem;
  Memory.initialized = true;
  Memory.conservation = false;
  Memory.fortify = false;
}

//Gets the number of living harvester Creeps
function getNumHarvesters(creepList){
  var harvesters = _.filter(creepList, (creep) => creep.memory.role == 'harvester');
  var hL = harvesters.length;
  if(Memory.roles.numHarvesters != hL){
    Memory.roles.numHarvesters = hL;
    console.log('Harvesters: ' + hL);
  }
  return hL;
}

//Gets the number of living upgrader Creeps
function getNumUpgraders(creepList){
  var upgraders = _.filter(creepList, (creep) => creep.memory.role == 'upgrader');
  var uL = upgraders.length;
  if(Memory.roles.numUpgraders != uL){
    Memory.roles.numUpgraders = uL;
    console.log('Upgraders: ' + uL);
  }
  return uL;
}

//Gets the number of living builder Creeps
function getNumBuilders(creepList){
  var builders = _.filter(creepList, (creep) => creep.memory.role == 'builder');
  var bL = builders.length;
  if(Memory.roles.numBuilders != bL){
    Memory.roles.numBuilders = bL;
    console.log('Builders: ' + bL);
  }
  return bL;
}

//Gets the number of living Repair Creeps
function getNumRepair(creepList){
  var repair = _.filter(creepList, (creep) => creep.memory.role == 'repair');
  var rL = repair.length;
  if(Memory.roles.numRepair != rL){
    Memory.roles.numRepair = rL;
    console.log('Repair: ' + rL);
  }
  return rL;
}

//Gets the number of living architect Creeps
function getNumArchitects(creepList){
  var architects = _.filter(creepList, (creep) => creep.memory.role == 'architect');
  var aL = architects.length;
  if(Memory.roles.numArchitects != aL){
    Memory.roles.numArchitects = aL;
    console.log('Architects: ' + aL);
  }
  return aL;
}

//Gets the number of living miner Creeps
function getNumMiners(creepList){
  var miners = _.filter(creepList, (creep) => creep.memory.role == 'miner');
  var mL = miners.length;
  if(Memory.roles.numMiners != mL){
    Memory.roles.numMiners = mL;
    console.log('Miners: ' + mL);
  }
  return mL;
}

//Gets the number of living hauler Creeps
function getNumHaulers(creepList){
  var haulers = _.filter(creepList, (creep) => creep.memory.role == 'hauler');
  var haulL = haulers.length;
  if(Memory.roles.numHaulers != haulL){
    Memory.roles.numHaulers = haulL;
    console.log('Haulers: ' + haulL);
  }
  return haulL;
}

function getNumFeeders(creepList){
  var feeders = _.filter(creepList, (creep) => creep.memory.role == 'feeder');
  var feedL = feeders.length;
  if(Memory.roles.numFeeders != feedL){
    Memory.roles.numFeeders = feedL;
    console.log('Haulers: ' + feedL);
  }
  return feedL;
}

//main loop
module.exports.loop = function () {

  //Only initialize if it hasnt been done (or it was manually set to false)
  if(Memory.initialized!==true){
    initialize();
  }

  //Loop to check each room that is visible to the script
  for(var roomName in Game.rooms){
    var room = Game.rooms[roomName];

    if(Memory.fortify && (!room.controller.safeMode || room.controller.safeMode<1000)){
      Memory.fortify = false;
    }

    //Creep lists in each room, comparing lengths shows if there are 'others'
    var allCreepList = room.find(FIND_CREEPS);
    var myCreepList = _.filter(allCreepList, (creep) => (creep.owner && creep.owner.username ==="PCarton"));
    var enemyPresent = allCreepList.length>myCreepList.length;

    //Al the structures in the room that are controlled by the player
    var allStructs = room.find(FIND_MY_STRUCTURES);
    var towers = _.filter(allStructs, (struct) => struct.structureType === STRUCTURE_TOWER);

    //calculates the breakdown of creeps by roles
    /* var h  = getNumHarvesters(myCreepList);
    var u = getNumUpgraders(myCreepList);
    var b = getNumBuilders(myCreepList);
    var r = getNumRepair(myCreepList);
    var a = getNumArchitects(myCreepList);
    var m = getNumMiners(myCreepList);
    var ha = getNumHaulers(myCreepList);
    var f = getNumFeeders(myCreepList);
    Memory.roles.numCreeps = h + u + b + r + a + m + ha + f;
    */

    //Clear dead creeps from memory
    modCommon.clearDead();

    //assign the right run method to each creep based on its role
    for(var name in myCreepList) {
        var creep = myCreepList[name];

        //Has the non-military creeps retreat
        //Mining creeps are considered military - like the supply line
        if(enemyPresent && creep.memory.military !== true){
          modCommon.retreat(creep);
        }
        //If there are no enemies, run the appropriate role method
        else if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        else if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        else if(creep.memory.role == 'builder'){
          roleBuilder.run(creep);
        }
        else if(creep.memory.role == 'repair'){
          roleRepair.run(creep);
        }
        else if(creep.memory.role == 'architect'){
          roleArchitect.run(creep);
        }
        else if(creep.memory.role == 'miner'){
          roleMiner.run(creep);
        }
        else if(creep.memory.role == 'hauler'){
          roleHauler.run(creep);
        }
        else if(creep.memory.role == 'feeder'){
          roleFeeder.run(creep);
        }
    }

    //determine if new creeps need to be spawned and pick an appropriate spawner
    //Spawn logic is in a seperate module
    if(Memory.roles.numCreeps < modSpawning.maxCreeps){
        for(var spawn in Game.spawns){
          var spawner = Game.spawns[spawn];
          var controllerLvl= spawner.room.controller.level;
          var energyCapacity = spawner.room.energyCapacityAvailable;
          modSpawning.spawn(spawner,energyCapacity,controllerLvl);

        }
    }

    var control = room.controller;

    if(enemyPresent && modCommon.playerAttack(allCreepList) && !(control.safeMode || control.safeModeCooldown) && control.safeModeAvailable > 0 ){
      control.activateSafeMode();
      Memory.fortify = true;
      Game.notify("Activated Safe Mode at " + Game.time.toString);
    }

    //Variable to keep track of which enemy to shoot
    var target = Game.getObjectById(Memory.towersMem.target);

    //Notify the user on enemies or switch to healing and repairing
    if(enemyPresent){
      Memory.towersMem.mode = "attack";
      Game.notify("EnemyFound at "+ Game.time.toString(),60);
    }else{
      Memory.towersMem.mode = "heal";
    }

    //Run through the towers, picking a target if needed
    for(var towerName in towers){
      var t = towers[towerName];
      if(enemyPresent && (target===null || target.room !== t.room)){
        modStructures.pickTargets(t.room.controller, allCreepList);
      }
      modStructures.runTower(t,allCreepList);
    }
  }
};
<|endoftext|>