<commit_before>import { createSelector, createStructuredSelector } from 'reselect';
import flatten from 'lodash/flatten';
import isEmpty from 'lodash/isEmpty';
import moment from 'moment';
import flatMap from 'lodash/flatMap';
import sortBy from 'lodash/sortBy';
import { getDayRange } from 'utils/dates';

import { initialState } from './reducers';
import basemaps from './basemaps';

// map state
const selectMapUrlState = state =>
  state.location && state.location.query && state.location.query.map;
const selectMapLoading = state => state.map && state.map.loading;
const selectGeostoreLoading = state => state.geostore && state.geostore.loading;
const selectLatestLoading = state => state.latest && state.latest.loading;
const selectDatasetsLoading = state => state.datasets && state.datasets.loading;
const selectRecentImageryLoading = state =>
  state.recentImagery && state.recentImagery.loading;
const selectMapData = state => state.map && state.map.data;
const selectDatasets = state => state.datasets && state.datasets.data;
const selectLatest = state => state.latest && state.latest.data;
export const selectGeostore = state => state.geostore && state.geostore.data;
const selectActiveLang = state =>
  (state.location &&
    state.location &&
    state.location.query &&
    state.location.query.lang) ||
  JSON.parse(localStorage.getItem('txlive:selectedlang')) ||
  'en';

// CONSTS
export const getBasemaps = () => basemaps;

// SELECTORS
export const getMapSettings = createSelector([selectMapUrlState], urlState => ({
  ...initialState.settings,
  ...urlState
}));

export const getMapViewport = createSelector([getMapSettings], settings => {
  const { zoom, bearing, pitch, center } = settings;
  return {
    zoom,
    bearing,
    pitch,
    latitude: center.lat,
    longitude: center.lng
  };
});

export const getMapZoom = createSelector(
  [getMapSettings],
  settings => settings.zoom
);

export const getMapMinZoom = createSelector(
  [getMapSettings],
  settings => settings.minZoom
);

export const getMapMaxZoom = createSelector(
  [getMapSettings],
  settings => settings.maxZoom
);

export const getBasemapFromState = createSelector(
  getMapSettings,
  settings => settings.basemap
);

export const getBasemap = createSelector(
  [getBasemapFromState],
  basemapState => {
    const basemap = {
      ...basemaps[basemapState.value],
      ...basemapState
    };
    let url = basemap && basemap.url;
    if (url) {
      Object.keys(basemap).forEach(key => {
        if (url.includes(`{${key}}`)) {
          url = url.replace(`{${key}}`, basemap[key]);
        }
      });
    }

    return { ...basemap, url };
  }
);

export const getMapStyle = createSelector(
  getBasemap,
  basemap => basemap.mapStyle
);

export const getMapLabels = createSelector(
  getMapSettings,
  settings => settings.labels
);

export const getMapRoads = createSelector(
  getMapSettings,
  settings => settings.roads
);

export const getDrawing = createSelector(
  [getMapSettings],
  settings => settings.drawing
);

export const getCanBound = createSelector(
  getMapSettings,
  settings => settings.canBound
);

export const getGeostoreBbox = createSelector(
  [selectGeostore],
  geostore => geostore && geostore.bbox
);

export const getStateBbox = createSelector(
  [getMapSettings],
  settings => settings && settings.bbox
);

export const getMapLoading = createSelector(
  [
    selectMapLoading,
    selectGeostoreLoading,
    selectLatestLoading,
    selectDatasetsLoading,
    selectRecentImageryLoading
  ],
  (
    mapLoading,
    geostoreLoading,
    latestLoading,
    datasetsLoading,
    recentLoading
  ) =>
    mapLoading ||
    geostoreLoading ||
    latestLoading ||
    datasetsLoading ||
    recentLoading
);

export const getLoadingMessage = createSelector(
  [selectRecentImageryLoading, selectLatestLoading],
  (recentLoading, latestLoading) => {
    if (recentLoading) return 'Fetching the most recent satellite image...';
    if (latestLoading) return 'Fetching latest data...';
    return '';
  }
);

export const getActiveDatasetsFromState = createSelector(
  getMapSettings,
  settings => settings.datasets
);

export const getActiveDatasetIds = createSelector(
  [getActiveDatasetsFromState],
  activeDatasetsState => {
    if (!activeDatasetsState || !activeDatasetsState.length) return null;
    return activeDatasetsState.map(l => l.dataset);
  }
);

export const getActiveDatasets = createSelector(
  [selectDatasets, getActiveDatasetIds],
  (datasets, datasetIds) => {
    if (isEmpty(datasets) || isEmpty(datasetIds)) return null;
    return datasets.filter(d => datasetIds.includes(d.id));
  }
);

// parse active datasets to add config from url
export const getDatasetsWithConfig = createSelector(
  [getActiveDatasets, getActiveDatasetsFromState, selectLatest],
  (datasets, activeDatasetsState, latestDates) => {
    if (isEmpty(datasets) || isEmpty(activeDatasetsState)) return null;

    return datasets.map(d => {
      const layerConfig =
        activeDatasetsState.find(l => l.dataset === d.id) || {};
      const {
        params,
        sqlParams,
        decodeParams,
        timelineParams,
        layers,
        visibility,
        opacity,
        bbox
      } =
        layerConfig || {};

      return {
        ...d,
        ...layerConfig,
        ...(d.selectorLayerConfig && {
          selectorLayerConfig: {
            ...d.selectorLayerConfig,
            selected: d.selectorLayerConfig.options.find(
              l => l.value === layers[0]
            )
          }
        }),
        layers: d.layers.map(l => {
          const {
            hasParamsTimeline,
            hasDecodeTimeline,
            timelineConfig,
            id
          } = l;
          const maxDate = latestDates[id];
          const { latestFormat } = l.params || {};
          const maxDateFormatted = latestFormat
            ? moment(maxDate).format(latestFormat)
            : maxDate;

          return {
            ...l,
            visibility,
            opacity,
            bbox,
            color: d.color,
            active: layers && layers.includes(l.id),
            ...(!isEmpty(l.params) && {
              params: {
                ...l.params,
                ...(maxDate && {
                  endDate: maxDate
                }),
                ...params,
                ...(maxDateFormatted && {
                  date: maxDateFormatted
                }),
                ...(hasParamsTimeline && {
                  ...timelineParams
                }),
                ...(maxDate && {
                  maxDate
                })
              }
            }),
            ...(!isEmpty(l.sqlParams) && {
              sqlParams: {
                ...l.sqlParams,
                ...sqlParams
              }
            }),
            ...(l.decodeFunction && {
              decodeParams: {
                ...l.decodeParams,
                ...(layers && {
                  confirmedOnly: layers.includes('confirmedOnly') ? 1 : 0
                }),
                ...(maxDate && {
                  endDate: maxDate
                }),
                ...decodeParams,
                ...(hasDecodeTimeline && {
                  ...timelineParams
                }),
                ...(maxDate && {
                  maxDate
                })
              }
            }),
            ...((l.hasParamsTimeline || l.hasDecodeTimeline) && {
              timelineParams: {
                ...timelineConfig,
                ...(l.hasParamsTimeline && {
                  ...l.params
                }),
                ...(l.hasDecodeTimeline && {
                  ...l.decodeParams
                }),
                ...(maxDate && {
                  endDate: maxDate,
                  maxDate,
                  trimEndDate: maxDate
                }),
                ...timelineParams
              }
            })
          };
        })
      };
    });
  }
);

// map active datasets into correct order based on url state (drag and drop)
export const getLayerGroups = createSelector(
  [getDatasetsWithConfig, getActiveDatasetsFromState],
  (datasets, activeDatasetsState) => {
    if (isEmpty(datasets) || isEmpty(activeDatasetsState)) return null;

    return activeDatasetsState.map(layer => {
      const dataset = datasets.find(d => d.id === layer.dataset);
      const { metadata } =
        (dataset && dataset.layers.find(l => l.active)) || {};
      return {
        ...dataset,
        metadata: metadata || (dataset && dataset.metadata)
      };
    });
  }
);

// flatten datasets into layers for the layer manager
export const getAllLayers = createSelector(getLayerGroups, layerGroups => {
  if (isEmpty(layerGroups)) return null;

  return sortBy(
    flatten(layerGroups.map(d => d.layers))
      .filter(l => l && l.active && (!l.isRecentImagery || l.params.url))
      .map((l, i) => {
        let zIndex = 1000 - i;
        if (l.isRecentImagery) zIndex = 500;
        if (l.isBoundary) zIndex = 1050 - i;
        return {
          ...l,
          zIndex
        };
      }),
    'zIndex'
  );
});

// all layers for importing by other components
export const getActiveLayers = createSelector(getAllLayers, layers => {
  if (isEmpty(layers)) return [];
  return layers.filter(l => !l.confirmedOnly);
});

export const getActiveLayersWithDates = createSelector(
  getActiveLayers,
  layers => {
    if (isEmpty(layers)) return [];
    return layers.map(l => {
      const { decodeFunction, decodeParams } = l;
      const { startDate, endDate } = decodeParams || {};

      return {
        ...l,
        ...(decodeFunction &&
          decodeParams && {
          decodeParams: {
            ...decodeParams,
            ...(startDate && {
              startYear: moment(startDate).year(),
              startMonth: moment(startDate).month(),
              startDay: moment(startDate).dayOfYear()
            }),
            ...(endDate && {
              endYear: moment(endDate).year(),
              endMonth: moment(endDate).month(),
              endDay: moment(endDate).dayOfYear()
            }),
            ...getDayRange(decodeParams)
          }
        })
      };
    });
  }
);

export const getInteractiveLayerIds = createSelector(
  getActiveLayers,
  layers => {
    if (isEmpty(layers)) return [];
    const interactiveLayers = layers.filter(
      l => !isEmpty(l.interactionConfig) && l.layerConfig.body.vectorLayers
    );

    return flatMap(
      interactiveLayers.reduce((arr, layer) => {
        const clickableLayers = layer.layerConfig.body.vectorLayers;

        return [
          ...arr,
          clickableLayers.map((l, i) => `${layer.id}-${l.type}-${i}`)
        ];
      }, [])
    );
  }
);

export const getInteractionsState = createSelector(
  [selectMapData],
  mapData => mapData && mapData.interactions
);

export const getInteractionsLatLng = createSelector(
  [getInteractionsState],
  interactionData => interactionData && interactionData.latlng
);

export const getInteractionsData = createSelector(
  [getInteractionsState],
  interactionData => interactionData && interactionData.interactions
);

export const getInteractionSelectedId = createSelector(
  [getInteractionsState],
  interactionData => interactionData && interactionData.selected
);

export const getInteractions = createSelector(
  [getInteractionsData, getActiveLayers],
  (interactions, activeLayers) => {
    if (isEmpty(interactions)) return null;
    return Object.keys(interactions).map(i => {
      const layer = activeLayers.find(l => l.id === i);
      return {
        data: interactions[i].data,
        geometry: interactions[i].geometry,
        layer,
        label: layer && layer.name,
        value: layer && layer.id,
        article:
          layer && layer.interactionConfig && layer.interactionConfig.article
      };
    });
  }
);

export const getInteractionSelected = createSelector(
  [getInteractions, getInteractionSelectedId, getActiveLayers],
  (interactions, selected, layers) => {
    if (isEmpty(interactions)) return null;
    const layersWithoutBoundaries = layers.filter(
      l => !l.isBoundary && !isEmpty(l.interactionConfig)
    );
    const layersWithoutBoundariesIds =
      layersWithoutBoundaries &&
      layersWithoutBoundaries.length &&
      layersWithoutBoundaries.map(l => l.id);
    // if there is an article (icon layer) then choose that
    let selectedData = interactions.find(o => o.data.cluster);
    selectedData = interactions.find(o => o.article);
    // if there is nothing selected get the top layer
    if (!selected && !!layersWithoutBoundaries.length) {
      selectedData = interactions
        .reverse()
        .find(o => o.layer && layersWithoutBoundariesIds.includes(o.layer.id));
    }
    // if only one layer then get that
    if (!selectedData && interactions.length === 1) {
      selectedData = interactions[0];
    }
    // otherwise get based on selected
    if (!selectedData) {
      selectedData = interactions.find(o => o.layer && o.layer.id === selected);
    }

    return selectedData;
  }
);

export const getActiveMapLang = createSelector(selectActiveLang, lang => {
  if (lang === 'pt_BR') return 'pt';
  if (lang === 'es_MX') return 'es';
  if (lang === 'id') return 'en';
  return lang;
});

export const getMapProps = createStructuredSelector({
  viewport: getMapViewport,
  loading: getMapLoading,
  loadingMessage: getLoadingMessage,
  minZoom: getMapMinZoom,
  maxZoom: getMapMaxZoom,
  mapStyle: getMapStyle,
  mapLabels: getMapLabels,
  mapRoads: getMapRoads,
  drawing: getDrawing,
  canBound: getCanBound,
  geostoreBbox: getGeostoreBbox,
  stateBbox: getStateBbox,
  interaction: getInteractionSelected,
  interactiveLayerIds: getInteractiveLayerIds,
  basemap: getBasemap,
  lang: getActiveMapLang
});
<commit_msg>set default transition duration animation time for map transitions<commit_after>import { createSelector, createStructuredSelector } from 'reselect';
import flatten from 'lodash/flatten';
import isEmpty from 'lodash/isEmpty';
import moment from 'moment';
import flatMap from 'lodash/flatMap';
import sortBy from 'lodash/sortBy';
import { getDayRange } from 'utils/dates';

import { initialState } from './reducers';
import basemaps from './basemaps';

// map state
const selectMapUrlState = state =>
  state.location && state.location.query && state.location.query.map;
const selectMapLoading = state => state.map && state.map.loading;
const selectGeostoreLoading = state => state.geostore && state.geostore.loading;
const selectLatestLoading = state => state.latest && state.latest.loading;
const selectDatasetsLoading = state => state.datasets && state.datasets.loading;
const selectRecentImageryLoading = state =>
  state.recentImagery && state.recentImagery.loading;
const selectMapData = state => state.map && state.map.data;
const selectDatasets = state => state.datasets && state.datasets.data;
const selectLatest = state => state.latest && state.latest.data;
export const selectGeostore = state => state.geostore && state.geostore.data;
const selectActiveLang = state =>
  (state.location &&
    state.location &&
    state.location.query &&
    state.location.query.lang) ||
  JSON.parse(localStorage.getItem('txlive:selectedlang')) ||
  'en';

// CONSTS
export const getBasemaps = () => basemaps;

// SELECTORS
export const getMapSettings = createSelector([selectMapUrlState], urlState => ({
  ...initialState.settings,
  ...urlState
}));

export const getMapViewport = createSelector([getMapSettings], settings => {
  const { zoom, bearing, pitch, center } = settings;
  return {
    zoom,
    bearing,
    pitch,
    latitude: center.lat,
    longitude: center.lng,
    transitionDuration: 500
  };
});

export const getMapZoom = createSelector(
  [getMapSettings],
  settings => settings.zoom
);

export const getMapMinZoom = createSelector(
  [getMapSettings],
  settings => settings.minZoom
);

export const getMapMaxZoom = createSelector(
  [getMapSettings],
  settings => settings.maxZoom
);

export const getBasemapFromState = createSelector(
  getMapSettings,
  settings => settings.basemap
);

export const getBasemap = createSelector(
  [getBasemapFromState],
  basemapState => {
    const basemap = {
      ...basemaps[basemapState.value],
      ...basemapState
    };
    let url = basemap && basemap.url;
    if (url) {
      Object.keys(basemap).forEach(key => {
        if (url.includes(`{${key}}`)) {
          url = url.replace(`{${key}}`, basemap[key]);
        }
      });
    }

    return { ...basemap, url };
  }
);

export const getMapStyle = createSelector(
  getBasemap,
  basemap => basemap.mapStyle
);

export const getMapLabels = createSelector(
  getMapSettings,
  settings => settings.labels
);

export const getMapRoads = createSelector(
  getMapSettings,
  settings => settings.roads
);

export const getDrawing = createSelector(
  [getMapSettings],
  settings => settings.drawing
);

export const getCanBound = createSelector(
  getMapSettings,
  settings => settings.canBound
);

export const getGeostoreBbox = createSelector(
  [selectGeostore],
  geostore => geostore && geostore.bbox
);

export const getStateBbox = createSelector(
  [getMapSettings],
  settings => settings && settings.bbox
);

export const getMapLoading = createSelector(
  [
    selectMapLoading,
    selectGeostoreLoading,
    selectLatestLoading,
    selectDatasetsLoading,
    selectRecentImageryLoading
  ],
  (
    mapLoading,
    geostoreLoading,
    latestLoading,
    datasetsLoading,
    recentLoading
  ) =>
    mapLoading ||
    geostoreLoading ||
    latestLoading ||
    datasetsLoading ||
    recentLoading
);

export const getLoadingMessage = createSelector(
  [selectRecentImageryLoading, selectLatestLoading],
  (recentLoading, latestLoading) => {
    if (recentLoading) return 'Fetching the most recent satellite image...';
    if (latestLoading) return 'Fetching latest data...';
    return '';
  }
);

export const getActiveDatasetsFromState = createSelector(
  getMapSettings,
  settings => settings.datasets
);

export const getActiveDatasetIds = createSelector(
  [getActiveDatasetsFromState],
  activeDatasetsState => {
    if (!activeDatasetsState || !activeDatasetsState.length) return null;
    return activeDatasetsState.map(l => l.dataset);
  }
);

export const getActiveDatasets = createSelector(
  [selectDatasets, getActiveDatasetIds],
  (datasets, datasetIds) => {
    if (isEmpty(datasets) || isEmpty(datasetIds)) return null;
    return datasets.filter(d => datasetIds.includes(d.id));
  }
);

// parse active datasets to add config from url
export const getDatasetsWithConfig = createSelector(
  [getActiveDatasets, getActiveDatasetsFromState, selectLatest],
  (datasets, activeDatasetsState, latestDates) => {
    if (isEmpty(datasets) || isEmpty(activeDatasetsState)) return null;

    return datasets.map(d => {
      const layerConfig =
        activeDatasetsState.find(l => l.dataset === d.id) || {};
      const {
        params,
        sqlParams,
        decodeParams,
        timelineParams,
        layers,
        visibility,
        opacity,
        bbox
      } =
        layerConfig || {};

      return {
        ...d,
        ...layerConfig,
        ...(d.selectorLayerConfig && {
          selectorLayerConfig: {
            ...d.selectorLayerConfig,
            selected: d.selectorLayerConfig.options.find(
              l => l.value === layers[0]
            )
          }
        }),
        layers: d.layers.map(l => {
          const {
            hasParamsTimeline,
            hasDecodeTimeline,
            timelineConfig,
            id
          } = l;
          const maxDate = latestDates[id];
          const { latestFormat } = l.params || {};
          const maxDateFormatted = latestFormat
            ? moment(maxDate).format(latestFormat)
            : maxDate;

          return {
            ...l,
            visibility,
            opacity,
            bbox,
            color: d.color,
            active: layers && layers.includes(l.id),
            ...(!isEmpty(l.params) && {
              params: {
                ...l.params,
                ...(maxDate && {
                  endDate: maxDate
                }),
                ...params,
                ...(maxDateFormatted && {
                  date: maxDateFormatted
                }),
                ...(hasParamsTimeline && {
                  ...timelineParams
                }),
                ...(maxDate && {
                  maxDate
                })
              }
            }),
            ...(!isEmpty(l.sqlParams) && {
              sqlParams: {
                ...l.sqlParams,
                ...sqlParams
              }
            }),
            ...(l.decodeFunction && {
              decodeParams: {
                ...l.decodeParams,
                ...(layers && {
                  confirmedOnly: layers.includes('confirmedOnly') ? 1 : 0
                }),
                ...(maxDate && {
                  endDate: maxDate
                }),
                ...decodeParams,
                ...(hasDecodeTimeline && {
                  ...timelineParams
                }),
                ...(maxDate && {
                  maxDate
                })
              }
            }),
            ...((l.hasParamsTimeline || l.hasDecodeTimeline) && {
              timelineParams: {
                ...timelineConfig,
                ...(l.hasParamsTimeline && {
                  ...l.params
                }),
                ...(l.hasDecodeTimeline && {
                  ...l.decodeParams
                }),
                ...(maxDate && {
                  endDate: maxDate,
                  maxDate,
                  trimEndDate: maxDate
                }),
                ...timelineParams
              }
            })
          };
        })
      };
    });
  }
);

// map active datasets into correct order based on url state (drag and drop)
export const getLayerGroups = createSelector(
  [getDatasetsWithConfig, getActiveDatasetsFromState],
  (datasets, activeDatasetsState) => {
    if (isEmpty(datasets) || isEmpty(activeDatasetsState)) return null;

    return activeDatasetsState.map(layer => {
      const dataset = datasets.find(d => d.id === layer.dataset);
      const { metadata } =
        (dataset && dataset.layers.find(l => l.active)) || {};
      return {
        ...dataset,
        metadata: metadata || (dataset && dataset.metadata)
      };
    });
  }
);

// flatten datasets into layers for the layer manager
export const getAllLayers = createSelector(getLayerGroups, layerGroups => {
  if (isEmpty(layerGroups)) return null;

  return sortBy(
    flatten(layerGroups.map(d => d.layers))
      .filter(l => l && l.active && (!l.isRecentImagery || l.params.url))
      .map((l, i) => {
        let zIndex = 1000 - i;
        if (l.isRecentImagery) zIndex = 500;
        if (l.isBoundary) zIndex = 1050 - i;
        return {
          ...l,
          zIndex
        };
      }),
    'zIndex'
  );
});

// all layers for importing by other components
export const getActiveLayers = createSelector(getAllLayers, layers => {
  if (isEmpty(layers)) return [];
  return layers.filter(l => !l.confirmedOnly);
});

export const getActiveLayersWithDates = createSelector(
  getActiveLayers,
  layers => {
    if (isEmpty(layers)) return [];
    return layers.map(l => {
      const { decodeFunction, decodeParams } = l;
      const { startDate, endDate } = decodeParams || {};

      return {
        ...l,
        ...(decodeFunction &&
          decodeParams && {
          decodeParams: {
            ...decodeParams,
            ...(startDate && {
              startYear: moment(startDate).year(),
              startMonth: moment(startDate).month(),
              startDay: moment(startDate).dayOfYear()
            }),
            ...(endDate && {
              endYear: moment(endDate).year(),
              endMonth: moment(endDate).month(),
              endDay: moment(endDate).dayOfYear()
            }),
            ...getDayRange(decodeParams)
          }
        })
      };
    });
  }
);

export const getInteractiveLayerIds = createSelector(
  getActiveLayers,
  layers => {
    if (isEmpty(layers)) return [];
    const interactiveLayers = layers.filter(
      l => !isEmpty(l.interactionConfig) && l.layerConfig.body.vectorLayers
    );

    return flatMap(
      interactiveLayers.reduce((arr, layer) => {
        const clickableLayers = layer.layerConfig.body.vectorLayers;

        return [
          ...arr,
          clickableLayers.map((l, i) => `${layer.id}-${l.type}-${i}`)
        ];
      }, [])
    );
  }
);

export const getInteractionsState = createSelector(
  [selectMapData],
  mapData => mapData && mapData.interactions
);

export const getInteractionsLatLng = createSelector(
  [getInteractionsState],
  interactionData => interactionData && interactionData.latlng
);

export const getInteractionsData = createSelector(
  [getInteractionsState],
  interactionData => interactionData && interactionData.interactions
);

export const getInteractionSelectedId = createSelector(
  [getInteractionsState],
  interactionData => interactionData && interactionData.selected
);

export const getInteractions = createSelector(
  [getInteractionsData, getActiveLayers],
  (interactions, activeLayers) => {
    if (isEmpty(interactions)) return null;
    return Object.keys(interactions).map(i => {
      const layer = activeLayers.find(l => l.id === i);
      return {
        data: interactions[i].data,
        geometry: interactions[i].geometry,
        layer,
        label: layer && layer.name,
        value: layer && layer.id,
        article:
          layer && layer.interactionConfig && layer.interactionConfig.article
      };
    });
  }
);

export const getInteractionSelected = createSelector(
  [getInteractions, getInteractionSelectedId, getActiveLayers],
  (interactions, selected, layers) => {
    if (isEmpty(interactions)) return null;
    const layersWithoutBoundaries = layers.filter(
      l => !l.isBoundary && !isEmpty(l.interactionConfig)
    );
    const layersWithoutBoundariesIds =
      layersWithoutBoundaries &&
      layersWithoutBoundaries.length &&
      layersWithoutBoundaries.map(l => l.id);
    // if there is an article (icon layer) then choose that
    let selectedData = interactions.find(o => o.data.cluster);
    selectedData = interactions.find(o => o.article);
    // if there is nothing selected get the top layer
    if (!selected && !!layersWithoutBoundaries.length) {
      selectedData = interactions
        .reverse()
        .find(o => o.layer && layersWithoutBoundariesIds.includes(o.layer.id));
    }
    // if only one layer then get that
    if (!selectedData && interactions.length === 1) {
      selectedData = interactions[0];
    }
    // otherwise get based on selected
    if (!selectedData) {
      selectedData = interactions.find(o => o.layer && o.layer.id === selected);
    }

    return selectedData;
  }
);

export const getActiveMapLang = createSelector(selectActiveLang, lang => {
  if (lang === 'pt_BR') return 'pt';
  if (lang === 'es_MX') return 'es';
  if (lang === 'id') return 'en';
  return lang;
});

export const getMapProps = createStructuredSelector({
  viewport: getMapViewport,
  loading: getMapLoading,
  loadingMessage: getLoadingMessage,
  minZoom: getMapMinZoom,
  maxZoom: getMapMaxZoom,
  mapStyle: getMapStyle,
  mapLabels: getMapLabels,
  mapRoads: getMapRoads,
  drawing: getDrawing,
  canBound: getCanBound,
  geostoreBbox: getGeostoreBbox,
  stateBbox: getStateBbox,
  interaction: getInteractionSelected,
  interactiveLayerIds: getInteractiveLayerIds,
  basemap: getBasemap,
  lang: getActiveMapLang
});
<|endoftext|>


<commit_before>//Reusable functions
var Alphagov = {
  cookie_domain: function() {
    var host_parts = document.location.host.split(':')[0].split('.').slice(-3);
    return '.' + host_parts.join('.');
  },
  read_cookie: function(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        if (cookie.substring(0, name.length + 1) == (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  },
  delete_cookie: function(name) {
    if (document.cookie && document.cookie != '') {
      var date = new Date();
      date.setTime(date.getTime()-(24*60*60*1000)); // 1 day ago
      document.cookie = name + "=; expires=" + date.toGMTString() + "; domain=" + Alphagov.cookie_domain() + "; path=/";
    }
  },
  write_cookie: function(name, value) {
    var date = new Date();
    date.setTime(date.getTime()+(30*24*60*60*1000)); // 30 days in the future
    document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + date.toGMTString() + "; domain=" +  Alphagov.cookie_domain() + "; path=/";
  }
}

function recordOutboundLink(e) {
  _gat._getTrackerByName()._trackEvent(this.href, 'Outbound Links');
  setTimeout('document.location = "' + this.href + '"', 100);
  return false;
}

// //General page setup
// jQuery(document).ready(function() {

//   $('a').click(recordOutboundLink);

//   //Setup annotator links
//   $('a.annotation').each(function(index) {
//     $(this).linkAnnotator();
//   });

//   //feedback
//   $('#send_feedback').click(function () {
//     $('#feedback-router').show();
//     return false;
//   });

//   $('a.close').click(function () {
//     $(this).closest('.popover-mask').hide();
//   });

// });

$(document).ready(function() {
  $("body").addClass("js-enabled");

  if(window.location.hash) {
    contentNudge(window.location.hash);
  }

  $("nav").delegate('a', 'click', function(){
    var hash;
    var href = $(this).attr('href');
    if(href.charAt(0) === '#'){
      hash = href;
    }
    else if(href.indexOf("#") > 0){
      hash = "#" + href.split("#")[1];
    }
    if($(hash).length == 1){
      $("html, body").animate({scrollTop: $(hash).offset().top - $("#global-header").height()},10);
    }
  });

  function contentNudge(hash){
    if($(hash).length == 1){
      if($(hash).css("top") == "auto" || "0"){
        $(window).scrollTop( $(hash).offset().top - $("#global-header").height()  );
      }
    }
  }

  // related box fixer
  if($(".related-positioning").length != 0){
    $(".related-positioning").css("position", "absolute");
    var viewPort = $(window).height();
    var relatedBox = $(".related").height();
    var boxOffset = $(".related-positioning").position();
    var topBoxOffset = boxOffset.top;
    if(relatedBox > (viewPort - topBoxOffset)){
      $(".related-positioning").css("position", "absolute");
    }
    else{
      $(".related-positioning").css("position", "fixed");
    }
  }

  /*var relatedBoxTop = $(".related-positioning").css("top");

  $(window).bind("scroll", function(){
    if(isScrolledIntoView($(".beta-notice"))){
      var docHeight = $(document).height();
      var portHeight = $(window).height();
      var distanceDownPage = $(window).scrollTop();
      var footerHeight = $("footer").height();
      var relatedHeight = $(".related").height();
      var relatedBottomStopper = footerHeight + relatedHeight;
      console.log("distance down page: "+distanceDownPage)
      console.log("relatedBottomStopper: "+relatedBottomStopper)
      if ( distanceDownPage  <= (relatedBottomStopper + footerHeight) ){

        $(".related-positioning").css("top", "auto");
        $(".related-positioning").css("bottom", relatedBottomStopper);
      }
    }
    else{
      $(".related-positioning").css("top", relatedBoxTop);
       $(".related-positioning").css("bottom", "auto");
    }
  })

  function isScrolledIntoView(elem)
  {
      var docViewTop = $(window).scrollTop();
      var docViewBottom = docViewTop + $(window).height();

      var elemTop = $(elem).offset().top;
      var elemBottom = elemTop + $(elem).height();

      return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
  }
  */

});

<commit_msg>Set geo cookie for 4 months.<commit_after>//Reusable functions
var Alphagov = {
  daysInMsec: function(d) {
    return d * 24 * 60 * 60 * 1000;
  },
  cookie_domain: function() {
    var host_parts = document.location.host.split(':')[0].split('.').slice(-3);
    return '.' + host_parts.join('.');
  },
  read_cookie: function(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        if (cookie.substring(0, name.length + 1) == (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  },
  delete_cookie: function(name) {
    if (document.cookie && document.cookie != '') {
      var date = new Date();
      date.setTime(date.getTime() - Alphagov.daysInMsec(1)); // 1 day ago
      document.cookie = name + "=; expires=" + date.toGMTString() + "; domain=" + Alphagov.cookie_domain() + "; path=/";
    }
  },
  write_cookie: function(name, value) {
    var date = new Date();
    date.setTime(date.getTime() + Alphagov.daysInMsec(4 * 30)); // 4 nominal 30-day months in the future
    document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + date.toGMTString() + "; domain=" + Alphagov.cookie_domain() + "; path=/";
  }
}

function recordOutboundLink(e) {
  _gat._getTrackerByName()._trackEvent(this.href, 'Outbound Links');
  setTimeout('document.location = "' + this.href + '"', 100);
  return false;
}

// //General page setup
// jQuery(document).ready(function() {

//   $('a').click(recordOutboundLink);

//   //Setup annotator links
//   $('a.annotation').each(function(index) {
//     $(this).linkAnnotator();
//   });

//   //feedback
//   $('#send_feedback').click(function () {
//     $('#feedback-router').show();
//     return false;
//   });

//   $('a.close').click(function () {
//     $(this).closest('.popover-mask').hide();
//   });

// });

$(document).ready(function() {
  $("body").addClass("js-enabled");

  if(window.location.hash) {
    contentNudge(window.location.hash);
  }

  $("nav").delegate('a', 'click', function(){
    var hash;
    var href = $(this).attr('href');
    if(href.charAt(0) === '#'){
      hash = href;
    }
    else if(href.indexOf("#") > 0){
      hash = "#" + href.split("#")[1];
    }
    if($(hash).length == 1){
      $("html, body").animate({scrollTop: $(hash).offset().top - $("#global-header").height()},10);
    }
  });

  function contentNudge(hash){
    if($(hash).length == 1){
      if($(hash).css("top") == "auto" || "0"){
        $(window).scrollTop( $(hash).offset().top - $("#global-header").height()  );
      }
    }
  }

  // related box fixer
  if($(".related-positioning").length != 0){
    $(".related-positioning").css("position", "absolute");
    var viewPort = $(window).height();
    var relatedBox = $(".related").height();
    var boxOffset = $(".related-positioning").position();
    var topBoxOffset = boxOffset.top;
    if(relatedBox > (viewPort - topBoxOffset)){
      $(".related-positioning").css("position", "absolute");
    }
    else{
      $(".related-positioning").css("position", "fixed");
    }
  }

  /*var relatedBoxTop = $(".related-positioning").css("top");

  $(window).bind("scroll", function(){
    if(isScrolledIntoView($(".beta-notice"))){
      var docHeight = $(document).height();
      var portHeight = $(window).height();
      var distanceDownPage = $(window).scrollTop();
      var footerHeight = $("footer").height();
      var relatedHeight = $(".related").height();
      var relatedBottomStopper = footerHeight + relatedHeight;
      console.log("distance down page: "+distanceDownPage)
      console.log("relatedBottomStopper: "+relatedBottomStopper)
      if ( distanceDownPage  <= (relatedBottomStopper + footerHeight) ){

        $(".related-positioning").css("top", "auto");
        $(".related-positioning").css("bottom", relatedBottomStopper);
      }
    }
    else{
      $(".related-positioning").css("top", relatedBoxTop);
       $(".related-positioning").css("bottom", "auto");
    }
  })

  function isScrolledIntoView(elem)
  {
      var docViewTop = $(window).scrollTop();
      var docViewBottom = docViewTop + $(window).height();

      var elemTop = $(elem).offset().top;
      var elemBottom = elemTop + $(elem).height();

      return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
  }
  */

});

<|endoftext|>


<commit_before>//Drop Model
SoapStone.Drop = function (args) {
  if (args) {
    this.setAttributes(args);
  }
};

SoapStone.Drop.prototype.setAttributes = function (args) {
  this.id = args.id;
  this.withinRange;
  if (args.coords) {
    this.coords = {};
    this.coords.longitude = args.coords.longitude;
    this.coords.latitude = args.coords.latitude;
  }
  if (args.lon && args.lat) {
    this.coords = {};
    this.coords.latitude = args.lat;
    this.coords.longitude = args.lon;
  }
  if (this.coords) {
    this.lat = this.coords.latitude;
    this.lon = this.coords.longitude;
  }
  this.googleLatLng = new google.maps.LatLng(this.lat, this.lon);
  this.text = args.text;
  this.photo = args.photo;
  this.distance = args.distance;//depricated
  this.has_photo = args["has_photo?"];
  this.created_at = args.created_at;
  this.snaps_count = args.snaps_count;
  this.comments_count = args.comments_count;
  this.snapped_by_you = args["snapped_by?"];
  if (args.user) {
    this.user = new SoapStone.User(args.user);
  }
  if (args.comments) {
    this.comments = args.comments.map(function (data) {
      return new SoapStone.Comment(data);
    });
  }
};

SoapStone.Drop.prototype.distanceFromTarget = function (target) {//we will use target as me for now but this can be used generally
  var meterDistance = google.maps.geometry.spherical.computeDistanceBetween(target, this.googleLatLng);
  this.distance = meterDistance/1609.34;
  return meterDistance*3.28084;//convert the meters which we get from the google function to feet to use in our if statements
};

SoapStone.Drop.prototype.save = function (formData) {
  formData.append('drop[lat]', this.lat);
  formData.append('drop[lon]', this.lon);
  return $.ajax({
    type: "POST",
    url:  "/drops",
    cache: false,
    contentType: false,
    processData: false,
    data: formData
  });
};

SoapStone.Drop.prototype.find = function (id) {
  var self = this;
  return new Promise(function (resolve, reject) {
    $.ajax({
      type: "GET",
      url: "/drops/" + id,
      dataType: 'json'
     })
    .then(function (response) {
      self.setAttributes(response);
      resolve(self);
    })
    .fail(function () {
      reject();
    });
  });
};

SoapStone.Drop.prototype.addSnap = function () {
  var self = this;
  return $.ajax({
    type:"POST",
    url: "/drops/" + self.id + "/snaps"
  }).then(function () {
    self.snaps_count +=1;
    self.snapped_by_you = true;
  });
};

SoapStone.Drop.prototype.createComment = function (comment) {
  var self = this;
  return $.ajax({
    type:"POST",
    url: "/drops/" + self.id + "/comments",
    data:{comment: $("[data-form='comment-form']").val()}
  }).then(function (response) {
    self.comments.push(new SoapStone.Comment(response));
    self.comments_count += 1;
  });
};

SoapStone.Comment = function (args) {
  this.text = args.text;
  if (args.user) {
    this.user = {};
    this.user.id = args.user.id;
    this.user.username = args.user.username;
    this.user.avatar = args.user.avatar;
  }
};

// View
SoapStone.DropView = function () {
  this.showTemplate = Handlebars.compile($("[data-template='show-drop']").html());
  this.dropListTemplate = Handlebars.compile($("[data-template='drop-list']").html());
  Handlebars.registerPartial("snap-button", $("[data-partial='snap-button-partial']").html());
  this.snapButtonTemplate = Handlebars.compile($("[data-partial='snap-button-partial']").html());
  Handlebars.registerPartial("comment", $("[data-partial='comment-partial']").html());
  this.commentsTemplate = Handlebars.compile($("[data-partial='comment-partial']").html());
  this.setUpEventHandlers();
};

SoapStone.DropView.prototype.setUpEventHandlers = function () {
  var self = this;

  // Filter tabs
  $("[data-button='friend-filter']").on('click', function (e) {
    $('.tabs .tab').removeClass('selected');
    $('.tabs .friend').addClass('selected');
    self.controller.loadDrops("/followees");
  });

  $("[data-button='public-filter']").on('click', function (e) {
    $('.tabs .tab').removeClass('selected');
    $('.tabs .public').addClass('selected');
    self.controller.loadDrops();
  });

  // Floating buttons
  $("[data-button='new']").on('click', function (event) {
    event.preventDefault();
    self.showNewDropForm();
  });

  $("[data-button='center']").on('click', function (event) {
    self.controller.mapView.centerMap();
  });

  $("[data-button='list']").on('click', function (event) {
    event.preventDefault();
    self.popupDropList();
  });

  $("[data-button='profile']").on('click', function (e) {
    location.replace('/users/me');
  });

  // New drop form handlers
  $("[data-role='photo-upload']").on('change', function (event) {
    if (this.files.length > 0) {
      $("[data-role='photo-label']")
      .removeClass('orange').addClass('white').addClass('has-file')
      .html($('PHOTO READY TO DROP'));
    } else {
      $("[data-role='photo-label']")
      .addClass('orange').removeClass('white').removeClass('has-file')
      .html('ADD A PHOTO');
    }
  });

  $("[data-role='drop-form']").on('submit', function (event) {
    event.preventDefault();
    self.controller.createDrop($("[data-role='drop-form']"));
    $("#drop_text").val('');
  });

  $("[data-button='close-form']").add('.new-form-lightbox').on('click', function (event) {
    event.preventDefault();
    self.hideNewDropForm();
  });
};

SoapStone.DropView.prototype.showNewDropForm = function () {
  $("[data-view='map']").addClass("drop-form-open");
};

SoapStone.DropView.prototype.hideNewDropForm = function () {
  $("[data-view='new-form']").removeClass('uploading');
  $("[data-view='map']").removeClass("drop-form-open");
};

SoapStone.DropView.prototype.showUploadIndicator = function () {
  $("[data-view='new-form']").addClass('uploading');
};

SoapStone.DropView.prototype.showUploadSuccess = function (response) {
  console.log("Drop posted successfuly!");
  toastr.success("Drop Posted", "Success");
  this.hideNewDropForm();
};

SoapStone.DropView.prototype.showUploadFailure = function (response) {
  console.log("Drop failed to post.");
  toastr.error("Drop failed to post.", "Error");
  this.hideNewDropForm();
};

SoapStone.DropView.prototype.updateSnapButton = function (drop) {
  $("[data-role='snaps']").replaceWith(this.snapButtonTemplate(drop));
};

SoapStone.DropView.prototype.updateComments = function (drop) {
  var self = this;

  $(".comment-list").replaceWith(this.commentsTemplate(drop));

  $("[data-button='comment-button']").on('click', function (event){
    event.preventDefault();
    self.controller.createComment(drop);
    $("[data-form='comment-form']").val('');
  });

  $("[data-button='snap-button']").on('click', function (event) {
    event.preventDefault();
    self.controller.addSnap(drop);
  });
};

SoapStone.DropView.prototype.showDrop = function (drop) {
  var self = this;
  $("[data-view='map']").append(this.showTemplate(drop));
  window.setTimeout(function() {
    $("[data-view='map']").addClass('drop-open');
    $("[data-button='close-drop']").on('click', function (event) {
      self.closeDrop();
    });
  }, 50);

  $("[data-button='snap-button']").on('click', function (event) {
    event.preventDefault();
    self.controller.addSnap(drop);
  });

  $("[data-button='comment-button']").on('click', function (event){
    event.preventDefault();
    self.controller.createComment(drop);
    $("[data-form='comment-form']").val('');
  });
};

SoapStone.DropView.prototype.clearDropList = function (drop) {
  $(".drop-list").remove();
};

SoapStone.DropView.prototype.getMarker = function (drops, id) {
  for (var i = 0; i < drops.length; i++) {
    var drop = drops[i];
    if (drop.id === id) {
      return drop.marker;
    }
  }
};

SoapStone.DropView.prototype.clearMarkerAnimations = function (drops) {
  for (var i = 0; i < drops.length; i++) {
    var drop = drops[i];
    drop.marker.setAnimation(null);
  }
};

SoapStone.DropView.prototype.popupDropList = function() {
  $("[data-view='map']").addClass("drop-list-open");
  this.controller.mapView.panVertically($(window).height() * 0.25);
};

SoapStone.DropView.prototype.hideDropList = function() {
  $("[data-view='map']").removeClass("drop-list-open");
  this.controller.mapView.panVertically(-$(window).height() * 0.25);
};

SoapStone.DropView.prototype.sortAndFilter = function (drops) {
  var orderedDrops = drops.sort(function (drop) {return drop.created_at}).reverse();
  return orderedDrops.slice(0,30);
};

SoapStone.DropView.prototype.showDropList = function (drops) {
  var self = this;
  drops = self.sortAndFilter(drops);
  $("[data-view='map']").append(this.dropListTemplate(drops));
  $(".drop-list").on('click', 'a', function(event){
    if (event.target.dataset.drop) {
      event.preventDefault();
      var dropId = event.target.dataset.drop;
      self.controller.showDrop(dropId);
    }
  });
  $(".drop-list").on('mouseenter', '.drop-item', function(event) {
    $(this).addClass("selected");
    var marker = self.getMarker(drops, Number(this.dataset.dropId));
    if (marker) {
      marker.setAnimation(google.maps.Animation.BOUNCE);
    }
  });
  $(".drop-list").on('mouseleave', '.drop-item', function(event) {
    $(this).removeClass("selected");
    var marker = self.getMarker(drops, Number(this.dataset.dropId));
    if (marker) {
      marker.setAnimation(null);
    }
  });
  $(".drop-list").on('click', '.drop-item', function(event) {
    $('.drop-item').removeClass("selected");
    $(this).addClass("selected");
    self.clearMarkerAnimations(drops);
    var marker = self.getMarker(drops, Number(this.dataset.dropId));
    if (marker) {
      marker.setAnimation(google.maps.Animation.BOUNCE);
    }
  });
  $("[data-button='close-list']").add('.new-form-lightbox').on('click', function (event) {
    event.preventDefault();
    self.hideDropList();
  });
};

SoapStone.DropView.prototype.closeDrop  = function () {
  $("[data-view='map']").removeClass('drop-open');
  window.setTimeout(function() {
      $("[data-view='drop']").remove();
  }, 500);
};
<commit_msg>reset form and revert photo upload styling<commit_after>//Drop Model
SoapStone.Drop = function (args) {
  if (args) {
    this.setAttributes(args);
  }
};

SoapStone.Drop.prototype.setAttributes = function (args) {
  this.id = args.id;
  this.withinRange;
  if (args.coords) {
    this.coords = {};
    this.coords.longitude = args.coords.longitude;
    this.coords.latitude = args.coords.latitude;
  }
  if (args.lon && args.lat) {
    this.coords = {};
    this.coords.latitude = args.lat;
    this.coords.longitude = args.lon;
  }
  if (this.coords) {
    this.lat = this.coords.latitude;
    this.lon = this.coords.longitude;
  }
  this.googleLatLng = new google.maps.LatLng(this.lat, this.lon);
  this.text = args.text;
  this.photo = args.photo;
  this.distance = args.distance;//depricated
  this.has_photo = args["has_photo?"];
  this.created_at = args.created_at;
  this.snaps_count = args.snaps_count;
  this.comments_count = args.comments_count;
  this.snapped_by_you = args["snapped_by?"];
  if (args.user) {
    this.user = new SoapStone.User(args.user);
  }
  if (args.comments) {
    this.comments = args.comments.map(function (data) {
      return new SoapStone.Comment(data);
    });
  }
};

SoapStone.Drop.prototype.distanceFromTarget = function (target) {//we will use target as me for now but this can be used generally
  var meterDistance = google.maps.geometry.spherical.computeDistanceBetween(target, this.googleLatLng);
  this.distance = meterDistance/1609.34;
  return meterDistance*3.28084;//convert the meters which we get from the google function to feet to use in our if statements
};

SoapStone.Drop.prototype.save = function (formData) {
  formData.append('drop[lat]', this.lat);
  formData.append('drop[lon]', this.lon);
  return $.ajax({
    type: "POST",
    url:  "/drops",
    cache: false,
    contentType: false,
    processData: false,
    data: formData
  });
};

SoapStone.Drop.prototype.find = function (id) {
  var self = this;
  return new Promise(function (resolve, reject) {
    $.ajax({
      type: "GET",
      url: "/drops/" + id,
      dataType: 'json'
     })
    .then(function (response) {
      self.setAttributes(response);
      resolve(self);
    })
    .fail(function () {
      reject();
    });
  });
};

SoapStone.Drop.prototype.addSnap = function () {
  var self = this;
  return $.ajax({
    type:"POST",
    url: "/drops/" + self.id + "/snaps"
  }).then(function () {
    self.snaps_count +=1;
    self.snapped_by_you = true;
  });
};

SoapStone.Drop.prototype.createComment = function (comment) {
  var self = this;
  return $.ajax({
    type:"POST",
    url: "/drops/" + self.id + "/comments",
    data:{comment: $("[data-form='comment-form']").val()}
  }).then(function (response) {
    self.comments.push(new SoapStone.Comment(response));
    self.comments_count += 1;
  });
};

SoapStone.Comment = function (args) {
  this.text = args.text;
  if (args.user) {
    this.user = {};
    this.user.id = args.user.id;
    this.user.username = args.user.username;
    this.user.avatar = args.user.avatar;
  }
};

// View
SoapStone.DropView = function () {
  this.showTemplate = Handlebars.compile($("[data-template='show-drop']").html());
  this.dropListTemplate = Handlebars.compile($("[data-template='drop-list']").html());
  Handlebars.registerPartial("snap-button", $("[data-partial='snap-button-partial']").html());
  this.snapButtonTemplate = Handlebars.compile($("[data-partial='snap-button-partial']").html());
  Handlebars.registerPartial("comment", $("[data-partial='comment-partial']").html());
  this.commentsTemplate = Handlebars.compile($("[data-partial='comment-partial']").html());
  this.setUpEventHandlers();
};

SoapStone.DropView.prototype.setUpEventHandlers = function () {
  var self = this;

  // Filter tabs
  $("[data-button='friend-filter']").on('click', function (e) {
    $('.tabs .tab').removeClass('selected');
    $('.tabs .friend').addClass('selected');
    self.controller.loadDrops("/followees");
  });

  $("[data-button='public-filter']").on('click', function (e) {
    $('.tabs .tab').removeClass('selected');
    $('.tabs .public').addClass('selected');
    self.controller.loadDrops();
  });

  // Floating buttons
  $("[data-button='new']").on('click', function (event) {
    event.preventDefault();
    self.showNewDropForm();
  });

  $("[data-button='center']").on('click', function (event) {
    self.controller.mapView.centerMap();
  });

  $("[data-button='list']").on('click', function (event) {
    event.preventDefault();
    self.popupDropList();
  });

  $("[data-button='profile']").on('click', function (e) {
    location.replace('/users/me');
  });

  // New drop form handlers
  $("[data-role='photo-upload']").on('change', function (event) {
    if (this.files.length > 0) {
      $("[data-role='photo-label']")
      .removeClass('orange').addClass('white').addClass('has-file')
      .html($('PHOTO READY TO DROP'));
    } else {
      $("[data-role='photo-label']")
      .addClass('orange').removeClass('white').removeClass('has-file')
      .html('ADD A PHOTO');

    }
  });

  $("[data-role='drop-form']").on('submit', function (event) {
    event.preventDefault();
    self.controller.createDrop($("[data-role='drop-form']"));
  });

  $("[data-button='close-form']").add('.new-form-lightbox').on('click', function (event) {
    event.preventDefault();
    self.hideNewDropForm();
  });
};

SoapStone.DropView.prototype.showNewDropForm = function () {
  $("[data-view='map']").addClass("drop-form-open");
};

SoapStone.DropView.prototype.hideNewDropForm = function () {
  $("[data-view='new-form']").removeClass('uploading');
  $("[data-view='map']").removeClass("drop-form-open");
};

SoapStone.DropView.prototype.showUploadIndicator = function () {
  $("[data-view='new-form']").addClass('uploading');
};

SoapStone.DropView.prototype.showUploadSuccess = function (response) {
  console.log("Drop posted successfuly!");
  toastr.success("Drop Posted", "Success");
  $("[data-role='drop-form']")[0].reset();
  $("[data-role='photo-label']")
  .addClass('orange').removeClass('white').removeClass('has-file')
  .html('ADD A PHOTO');
  this.hideNewDropForm();
};

SoapStone.DropView.prototype.showUploadFailure = function (response) {
  console.log("Drop failed to post.");
  toastr.error("Drop failed to post.", "Error");
  this.hideNewDropForm();
};

SoapStone.DropView.prototype.updateSnapButton = function (drop) {
  $("[data-role='snaps']").replaceWith(this.snapButtonTemplate(drop));
};

SoapStone.DropView.prototype.updateComments = function (drop) {
  var self = this;

  $(".comment-list").replaceWith(this.commentsTemplate(drop));

  $("[data-button='comment-button']").on('click', function (event){
    event.preventDefault();
    self.controller.createComment(drop);
    $("[data-form='comment-form']").val('');
  });

  $("[data-button='snap-button']").on('click', function (event) {
    event.preventDefault();
    self.controller.addSnap(drop);
  });
};

SoapStone.DropView.prototype.showDrop = function (drop) {
  var self = this;
  $("[data-view='map']").append(this.showTemplate(drop));
  window.setTimeout(function() {
    $("[data-view='map']").addClass('drop-open');
    $("[data-button='close-drop']").on('click', function (event) {
      self.closeDrop();
    });
  }, 50);

  $("[data-button='snap-button']").on('click', function (event) {
    event.preventDefault();
    self.controller.addSnap(drop);
  });

  $("[data-button='comment-button']").on('click', function (event){
    event.preventDefault();
    self.controller.createComment(drop);
    $("[data-form='comment-form']").val('');
  });
};

SoapStone.DropView.prototype.clearDropList = function (drop) {
  $(".drop-list").remove();
};

SoapStone.DropView.prototype.getMarker = function (drops, id) {
  for (var i = 0; i < drops.length; i++) {
    var drop = drops[i];
    if (drop.id === id) {
      return drop.marker;
    }
  }
};

SoapStone.DropView.prototype.clearMarkerAnimations = function (drops) {
  for (var i = 0; i < drops.length; i++) {
    var drop = drops[i];
    drop.marker.setAnimation(null);
  }
};

SoapStone.DropView.prototype.popupDropList = function() {
  $("[data-view='map']").addClass("drop-list-open");
  this.controller.mapView.panVertically($(window).height() * 0.25);
};

SoapStone.DropView.prototype.hideDropList = function() {
  $("[data-view='map']").removeClass("drop-list-open");
  this.controller.mapView.panVertically(-$(window).height() * 0.25);
};

SoapStone.DropView.prototype.sortAndFilter = function (drops) {
  var orderedDrops = drops.sort(function (drop) {return drop.created_at}).reverse();
  return orderedDrops.slice(0,30);
};

SoapStone.DropView.prototype.showDropList = function (drops) {
  var self = this;
  drops = self.sortAndFilter(drops);
  $("[data-view='map']").append(this.dropListTemplate(drops));
  $(".drop-list").on('click', 'a', function(event){
    if (event.target.dataset.drop) {
      event.preventDefault();
      var dropId = event.target.dataset.drop;
      self.controller.showDrop(dropId);
    }
  });
  $(".drop-list").on('mouseenter', '.drop-item', function(event) {
    $(this).addClass("selected");
    var marker = self.getMarker(drops, Number(this.dataset.dropId));
    if (marker) {
      marker.setAnimation(google.maps.Animation.BOUNCE);
    }
  });
  $(".drop-list").on('mouseleave', '.drop-item', function(event) {
    $(this).removeClass("selected");
    var marker = self.getMarker(drops, Number(this.dataset.dropId));
    if (marker) {
      marker.setAnimation(null);
    }
  });
  $(".drop-list").on('click', '.drop-item', function(event) {
    $('.drop-item').removeClass("selected");
    $(this).addClass("selected");
    self.clearMarkerAnimations(drops);
    var marker = self.getMarker(drops, Number(this.dataset.dropId));
    if (marker) {
      marker.setAnimation(google.maps.Animation.BOUNCE);
    }
  });
  $("[data-button='close-list']").add('.new-form-lightbox').on('click', function (event) {
    event.preventDefault();
    self.hideDropList();
  });
};

SoapStone.DropView.prototype.closeDrop  = function () {
  $("[data-view='map']").removeClass('drop-open');
  window.setTimeout(function() {
      $("[data-view='drop']").remove();
  }, 500);
};
<|endoftext|>


<commit_before>/**
* This monstrosity ensures that a user can't over-allocate an employee. It watches every allocation
*    select box on the page. When one changes, it calculates the sum of all the selected allocation
*    values on the page. If that sum exceeds 1 (indicating over-allocation), then a hidden div is
*    made visible on the page which informs the user that they must lower the allocation. In
*    addition to this, all the submit buttons on the page are hidden so that the user MUST fix the
*    over-allocation. Once fixed, the div will again be hidden and the submit buttons re-appear.
*/
$(document).ready(function(){
  var overAllocationMessage = $("#over_allocation");
  var submissionButtons = $('.submission');
  var allocationValues = $('.allocation_value');
  var removeAllocations = $('.remove_allocation');
  var newAllocationValue = $("#employee_allocations_allocation")

  // Triggers the change event for the allocation select boxes whenever a remove allocation checkbox
  // is clicked
  removeAllocations.click(function(e) {
    allocationValues.trigger("change");
  });

  // Watches for a change in any of the allocation select boxes
  allocationValues.change(function(e) {
    var totalAllocation = 0;
    var count = 1;

    // Gets total of all allocations on page that aren't marked for deletion
    while(count < allocationValues.length) {
      if(!$("#employee_employee_allocations_attributes_" + (count - 1) +
            "__destroy").is(":checked")) {
        totalAllocation += parseFloat(allocationValues[count].value);
      }
      count += 1;
    }
    if((newAllocationValue.val() != "") && (newAllocationValue.val() != undefined)) {
      totalAllocation += parseFloat(newAllocationValue.val());
    }

    // Hides submit buttons and shows error message if employee is over-allocated
    if( totalAllocation > 1 ) {
      submissionButtons.hide();
      overAllocationMessage.show();
    }

    // Shows submit buttons and hides error message if employee allocation is acceptable
    else {
      submissionButtons.show();
      overAllocationMessage.hide();
    }
  });
});<commit_msg>Fix defect with javascript telling employees they are over-allocated when they are not<commit_after>/**
* This monstrosity ensures that a user can't over-allocate an employee. It watches every allocation
*    select box on the page. When one changes, it calculates the sum of all the selected allocation
*    values on the page. If that sum exceeds 1 (indicating over-allocation), then a hidden div is
*    made visible on the page which informs the user that they must lower the allocation. In
*    addition to this, all the submit buttons on the page are hidden so that the user MUST fix the
*    over-allocation. Once fixed, the div will again be hidden and the submit buttons re-appear.
*/
$(document).ready(function(){
  var overAllocationMessage = $("#over_allocation");
  var submissionButtons = $('.submission');
  var allocationValues = $('.allocation_value');
  var removeAllocations = $('.remove_allocation');
  var newAllocationValue = $("#employee_allocations_allocation")

  // Triggers the change event for the allocation select boxes whenever a remove allocation checkbox
  // is clicked
  removeAllocations.click(function(e) {
    allocationValues.trigger("change");
  });

  // Watches for a change in any of the allocation select boxes
  allocationValues.change(function(e) {
    var totalAllocation = 0;
    var count = 1;

    // Gets total of all allocations on page that aren't marked for deletion
    while(count < allocationValues.length) {
      if(!$("#employee_employee_allocations_attributes_" + (count - 1) +
            "__destroy").is(":checked")) {
        totalAllocation += parseFloat(allocationValues[count].value);
      }
      count += 1;
    }
    if((newAllocationValue.val() != "") && (newAllocationValue.val() != undefined)) {
      totalAllocation += parseFloat(newAllocationValue.val());
    }

    // Hides submit buttons and shows error message if employee is over-allocated. Note that due to
    // the inprecision of floats, the total allocation is not compared to exactly 1.
    if( totalAllocation > 1.00001 ) {
      submissionButtons.hide();
      overAllocationMessage.show();
    }

    // Shows submit buttons and hides error message if employee allocation is acceptable
    else {
      submissionButtons.show();
      overAllocationMessage.hide();
    }
  });
});<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash'),
    request = require('request'),
    SSH = require('simple-ssh'),
    async = require('async');
var Server = require('./server.model'),
    Script = require('../script/script.model'),
    Interval = require('./interval.model');
var config = require('../../config/environment');

exports.runningScripts = [];

// Start Intervals
exports.start = function (req, res) {
  Server.find({})
    .populate('activeScripts.script')
    .exec(function (err, servers) {
    if(err) { return handleError(res, err); }
    async.each(servers, function (server, serverCallback) {
      async.each(server.activeScripts, function (interval, intervalCallback) {
        new StartRunningScript(interval, server, intervalCallback);
        }, function (error) {
            serverCallback(error);
        });
    }, function (error) {
      if (error) { return handleError(res, error); }
      res.send(200);
    });
  });
};

exports.execute = function (req, res) {
  Server.findById(req.params.serverId, function (err, server) {
    if (err) { return handleError(res, err); }
    if (!server) { return res.send(404); }
    var intervalIndex = _.findIndex(server.activeScripts, function (activeScript) {
      return activeScript._id.toString() === req.params.intervalId.toString();
    });
    var interval = server.activeScripts[intervalIndex];

    Script.findById(interval.script, function (err, script) {
      if (err) { return handleError(res, err); }
      if (!script) { return handleError(res, 'The script for that interval could not be found.'); }
      new RunScript(server.hostname, server.username, script.command, function (err, results) {
        if (err) { return handleError(res, err); }
        res.send(200, results);
      });
    });
  });
};

// Get list of servers
exports.index = function(req, res) {
  Server.find()
    .populate('activeScripts.script')
    .exec(function (err, servers) {
      if(err) { return handleError(res, err); }
      return res.json(200, servers);
  });
};

// Get a single server
exports.show = function(req, res) {
  Server.findById(req.params.id)
    .populate('activeScripts.script')
    .exec(function (err, server) {
      if(err) { return handleError(res, err); }
      if(!server) { return res.send(404); }
      return res.json(server);
    });
};

// Creates a new server in the DB.
exports.create = function(req, res) {
  Server.create(req.body, function(err, server) {
    if(err) { return handleError(res, err); }
    return res.json(201, server);
  });
};

// Updates an existing server in the DB.
exports.update = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  for (var s = 0; s < req.body.activeScripts.length; ++s) {
    if (typeof(req.body.activeScripts[s].script) === typeof({})) {
      req.body.activeScripts[s].script = req.body.activeScripts[s].script._id;
    }
  }
  async.waterfall([
    function (callback) {
      // Get original server
      Server.findById(req.params.id, function (err, server) {
        if (err) { return callback(err); }
        if(!server) { return callback('404'); }
        callback(null, server, req.body);
      });
    }, function (oldServer, server, callback) {
      // turn off the old scripts
      async.each(oldServer.activeScripts, StopRunningScript, function (error) {
        callback(error, oldServer, server);
      });
    }, function (oldServer, server, callback) {
      // update server with new info; remove old intervals
      var oldIds = _.difference(oldServer, server);
      Server.update({ _id: oldServer._id },
        {
          hostname: server.hostname || oldServer.hostname,
          description: server.description || oldServer.description,
          username: server.username || oldServer.username
        },
        { $pullAll: { activeScripts: oldIds } },
        function (err) {
          callback(err, oldServer, server);
      });
    }, function (oldServer, server, callback) {
      // update server with new info; add new intervals
      Server.update({ _id: oldServer._id },
        { $addToSet: { activeScripts: { $each: server.activeScripts } } },
        function (err) {
          callback(err, oldServer);
      });
    }, function (oldServer, callback) {
      Server.findById(oldServer._id, function (err, server) {
        callback(err, server);
      });
    }, function (updated, callback) {
      // start new scripts
      async.each(updated.activeScripts, function (interval, scriptCallback) {
        new StartRunningScript(interval, updated, function (error) {
          if (error) { return scriptCallback(error); }
          return scriptCallback();
        });
      }, function (error, result) {
        return callback(error, result);
      });
    }], function (error, result) {
      if (error === '404') {
        return res.send(404);
      }
      else if (error) {
        return handleError(res, error);
      }
      else {
        return res.json(200, result);
      }
    });
};

// Deletes a server from the DB.
exports.destroy = function(req, res) {
  Server.findById(req.params.id)
    .exec(function (err, server) {
    if(err) { return handleError(res, err); }
    if(!server) { return res.send(404); }
    server.remove(function(err) {
      if(err) { return handleError(res, err); }
      async.each(server.activeScripts, StopRunningScript, function (error) {
        if (error) { return handleError(res, error); }
        return res.send(204);
      });
    });
  });
};

function handleError(res, err) {
  console.error(err);
  return res.send(500, err);
}

function IsNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function RunScript (hostname, username, command, callback) {
  var ssh = new SSH({
    host: hostname,
    user: username,
    key: config.sshkey
  });

  ssh.exec(command, {
    out: function(stdout) {
      callback(null, stdout);
    },
    err: function(stderr) {
      console.error(stderr);
    }
  }).start();
}

function RunScriptOnServer (server, interval) {
  new RunScript(
    server.hostname,
    server.username,
    interval.script.command,
    function (err, results) {
      if (err) { return console.error(err); }
      if (new IsNumber(results)) {
        var intervalIndex = _.findIndex(server.activeScripts, function (activeScript) {
          return activeScript._id.toString() === interval._id.toString();
        });
        var intervalObject = {};
        intervalObject['activeScripts.' + intervalIndex + '.results'] = {
          value: parseFloat(results),
          timestamp: new Date()
        };

        Server.update({ _id: server._id }, {
          $push: intervalObject
        }, function (err) {
          if (err) { console.error(err); }
        });
      }
      else {
        console.error('stdout: ' + results +
          'is not a number! from Script: "' + interval.script.command + '" on Server ' + server);
      }
    });
}

function StartRunningScript (interval, server, callback) {
  async.waterfall([
    function (asyncCallback) {
      if (interval.script._id === undefined) {
        Script.findById(interval.script, function (err, script) {
          if (err) { return asyncCallback(err); }
          interval.script = script.toObject();
          asyncCallback(null, interval);
        });
      }
      else {
        asyncCallback(null, interval)
      }
    }],
    function (error, results) {
      if (error) { return callback(error); }

      var newInterval = setInterval(
        RunScriptOnServer,
        results.duration,
        server,
        results);
      exports.runningScripts.push({
        action: newInterval,
        id: results._id
      });
      callback();
    });
}

function StopRunningScript (interval, callback) {
  var data = interval._id;
  if (data === undefined) {
    data = interval;
  }
  var scriptIndex = _.findIndex(exports.runningScripts, function (script) {
    return script.id.toString() === data.toString();
  });

  if (scriptIndex === -1) {
    callback('That interval ID is not running.');
  }
  else {
    clearInterval(exports.runningScripts[scriptIndex].action);
    exports.runningScripts.splice(scriptIndex, 1);
    callback();
  }
}

exports.start(null, {
  send: function (value, object) {
    if (value === 200) {
      console.log('Intervals Started');
    }
    else {
      console.error(object);
    }
  }
});
<commit_msg>stupid typos<commit_after>'use strict';

var _ = require('lodash'),
    request = require('request'),
    SSH = require('simple-ssh'),
    async = require('async');
var Server = require('./server.model'),
    Script = require('../script/script.model'),
    Interval = require('./interval.model');
var config = require('../../config/environment');

exports.runningScripts = [];

// Start Intervals
exports.start = function (req, res) {
  Server.find({})
    .populate('activeScripts.script')
    .exec(function (err, servers) {
    if(err) { return handleError(res, err); }
    async.each(servers, function (server, serverCallback) {
      async.each(server.activeScripts, function (interval, intervalCallback) {
        new StartRunningScript(interval, server, intervalCallback);
        }, function (error) {
            serverCallback(error);
        });
    }, function (error) {
      if (error) { return handleError(res, error); }
      res.send(200);
    });
  });
};

exports.execute = function (req, res) {
  Server.findById(req.params.serverId, function (err, server) {
    if (err) { return handleError(res, err); }
    if (!server) { return res.send(404); }
    var intervalIndex = _.findIndex(server.activeScripts, function (activeScript) {
      return activeScript._id.toString() === req.params.intervalId.toString();
    });
    var interval = server.activeScripts[intervalIndex];

    Script.findById(interval.script, function (err, script) {
      if (err) { return handleError(res, err); }
      if (!script) { return handleError(res, 'The script for that interval could not be found.'); }
      new RunScript(server.hostname, server.username, script.command, function (err, results) {
        if (err) { return handleError(res, err); }
        res.send(200, results);
      });
    });
  });
};

// Get list of servers
exports.index = function(req, res) {
  Server.find()
    .populate('activeScripts.script')
    .exec(function (err, servers) {
      if(err) { return handleError(res, err); }
      return res.json(200, servers);
  });
};

// Get a single server
exports.show = function(req, res) {
  Server.findById(req.params.id)
    .populate('activeScripts.script')
    .exec(function (err, server) {
      if(err) { return handleError(res, err); }
      if(!server) { return res.send(404); }
      return res.json(server);
    });
};

// Creates a new server in the DB.
exports.create = function(req, res) {
  Server.create(req.body, function(err, server) {
    if(err) { return handleError(res, err); }
    return res.json(201, server);
  });
};

// Updates an existing server in the DB.
exports.update = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  for (var s = 0; s < req.body.activeScripts.length; ++s) {
    if (typeof(req.body.activeScripts[s].script) === typeof({})) {
      req.body.activeScripts[s].script = req.body.activeScripts[s].script._id;
    }
  }
  async.waterfall([
    function (callback) {
      // Get original server
      Server.findById(req.params.id, function (err, server) {
        if (err) { return callback(err); }
        if(!server) { return callback('404'); }
        callback(null, server, req.body);
      });
    }, function (oldServer, server, callback) {
      // turn off the old scripts
      async.each(oldServer.activeScripts, StopRunningScript, function (error) {
        callback(error, oldServer, server);
      });
    }, function (oldServer, server, callback) {
      // update server with new info; remove old intervals
      var oldIds = _.difference(oldServer.activeScripts, server.activeScripts);
      Server.update({ _id: oldServer._id },
        {
          hostname: server.hostname || oldServer.hostname,
          description: server.description || oldServer.description,
          username: server.username || oldServer.username,
          $pullAll: { activeScripts: oldIds }
        },
        function (err) {
          callback(err, oldServer, server);
      });
    }, function (oldServer, server, callback) {
      // update server with new info; add new intervals
      Server.update({ _id: oldServer._id },
        { $addToSet: { activeScripts: { $each: server.activeScripts } } },
        function (err) {
          callback(err, oldServer);
      });
    }, function (oldServer, callback) {
      Server.findById(oldServer._id, function (err, server) {
        callback(err, server);
      });
    }, function (updated, callback) {
      // start new scripts
      async.each(updated.activeScripts, function (interval, scriptCallback) {
        new StartRunningScript(interval, updated, function (error) {
          if (error) { return scriptCallback(error); }
          return scriptCallback();
        });
      }, function (error, result) {
        return callback(error, result);
      });
    }], function (error, result) {
      if (error === '404') {
        return res.send(404);
      }
      else if (error) {
        return handleError(res, error);
      }
      else {
        return res.json(200, result);
      }
    });
};

// Deletes a server from the DB.
exports.destroy = function(req, res) {
  Server.findById(req.params.id)
    .exec(function (err, server) {
    if(err) { return handleError(res, err); }
    if(!server) { return res.send(404); }
    server.remove(function(err) {
      if(err) { return handleError(res, err); }
      async.each(server.activeScripts, StopRunningScript, function (error) {
        if (error) { return handleError(res, error); }
        return res.send(204);
      });
    });
  });
};

function handleError(res, err) {
  console.error(err);
  return res.send(500, err);
}

function IsNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function RunScript (hostname, username, command, callback) {
  var ssh = new SSH({
    host: hostname,
    user: username,
    key: config.sshkey
  });

  ssh.exec(command, {
    out: function(stdout) {
      callback(null, stdout);
    },
    err: function(stderr) {
      console.error(stderr);
    }
  }).start();
}

function RunScriptOnServer (server, interval) {
  new RunScript(
    server.hostname,
    server.username,
    interval.script.command,
    function (err, results) {
      if (err) { return console.error(err); }
      if (new IsNumber(results)) {
        var intervalIndex = _.findIndex(server.activeScripts, function (activeScript) {
          return activeScript._id.toString() === interval._id.toString();
        });
        var intervalObject = {};
        intervalObject['activeScripts.' + intervalIndex + '.results'] = {
          value: parseFloat(results),
          timestamp: new Date()
        };

        Server.update({ _id: server._id }, {
          $push: intervalObject
        }, function (err) {
          if (err) { console.error(err); }
        });
      }
      else {
        console.error('stdout: ' + results +
          'is not a number! from Script: "' + interval.script.command + '" on Server ' + server);
      }
    });
}

function StartRunningScript (interval, server, callback) {
  async.waterfall([
    function (asyncCallback) {
      if (interval.script._id === undefined) {
        Script.findById(interval.script, function (err, script) {
          if (err) { return asyncCallback(err); }
          interval.script = script.toObject();
          asyncCallback(null, interval);
        });
      }
      else {
        asyncCallback(null, interval)
      }
    }],
    function (error, results) {
      if (error) { return callback(error); }

      var newInterval = setInterval(
        RunScriptOnServer,
        results.duration,
        server,
        results);
      exports.runningScripts.push({
        action: newInterval,
        id: results._id
      });
      callback();
    });
}

function StopRunningScript (interval, callback) {
  var data = interval._id;
  if (data === undefined) {
    data = interval;
  }
  var scriptIndex = _.findIndex(exports.runningScripts, function (script) {
    return script.id.toString() === data.toString();
  });

  if (scriptIndex === -1) {
    callback('That interval ID is not running.');
  }
  else {
    clearInterval(exports.runningScripts[scriptIndex].action);
    exports.runningScripts.splice(scriptIndex, 1);
    callback();
  }
}

exports.start(null, {
  send: function (value, object) {
    if (value === 200) {
      console.log('Intervals Started');
    }
    else {
      console.error(object);
    }
  }
});
<|endoftext|>


<commit_before>function validateCode()
{

   var code = document.forms["mc-embedded-subscribe-form"]["code"].value;
   if (code === "" || code !== "oxny")
   {
        swal({
          title: "招待コードが違います。",
          text: "OXNYは完全招待制です。\n 正しい招待コードを入力してください。",
          imageUrl:"https://s3-ap-northeast-1.amazonaws.com/oxny/LOGO/Flowerflasklogo_black.png"
        });
    return false;
   }
    return( true );
}

$('#mc-embedded-subscribe').on('click', validateCode);
<commit_msg>招待コードついか<commit_after>function validateCode()
{

   var code = document.forms["mc-embedded-subscribe-form"]["code"].value;
   if (code === "" || code !== "oxny")
   {
        swal({
          title: "招待コードが違います。",
          text: "OXNYは完全招待制です。\n 正しい招待コードを入力してください。",
          imageUrl:"https://s3-ap-northeast-1.amazonaws.com/oxny/LOGO/Flowerflasklogo_black.png"
        });
    return false;
   }
    return( true );
}

$('[id=mc-embedded-subscribe]').on('click', validateCode);
<|endoftext|>


<commit_before>/* Application functionality */

var main = (function () {
"use strict";
	var main = {};

	// initalize the application
	main.init = function()
	{
		busyManager.init();
		busyManager.hide(); // temp - immediately hide
		infoScreenManager.init(); // initialize help/info screen (in utility bar)
		alertManager.init(); // intialize alert box manager
	}

	//=================================================================================
	// manages show and hiding of splash screen
		var busyManager = (function(){
		var busyManager = {};

		var splashScreen; // loading screen

		// PUBLIC METHODS
		busyManager.init = function()
		{
			splashScreen = document.getElementById("splash-screen");
			//.success(function() { dataLoadedSuccess(); })
			//.error(function() { dataLoadedError(); })
			//.complete(function() { dataLoadedComplete(); });
		}

		// PUBLIC METHODS
		busyManager.show = function()
		{
			console.log("show splash screen");
			splashScreen.classList.remove("hide");
		}

		busyManager.hide = function()
		{
			console.log("hide splash screen");
			splashScreen.classList.add("hide");
		}

		return busyManager;
	})();

	//=================================================================================
	// manages show and hiding of info screen
	var infoScreenManager = (function(){
		var infoScreenManager = {};

		// PRIVATE PROPERTIES
		var infoScreenBtn; // help screen that covers content
		var infoScreen; // help screen that covers content

		// PUBLIC PROPERTIES
		infoScreenManager.storageName = "hrl-infoscreen";

		// PUBLIC METHODS
		infoScreenManager.init = function()
		{
			//console.log("initialized infoscreen");
			infoScreenBtn = document.getElementById("info-screen-btn");
			infoScreen = document.getElementById("info-screen");

			infoScreenBtn.addEventListener("mouseover",btnOverHandler,false);
			infoScreenBtn.addEventListener("mouseout",btnOutHandler,false);
			infoScreenBtn.addEventListener("mousedown",maximizeHandler,false);

			infoScreen.addEventListener("mousedown",minimizeHandler,false);

			if (webStorageProxy.getItem(infoScreenManager.storageName))
				infoScreenManager.minimize();
			else
				infoScreenManager.maximize();
		}

		// PUBLIC METHODS
		infoScreenManager.maximize = function()
		{
			// prevent mouseout of infoscreenbtn
			infoScreenBtn.removeEventListener("mouseout",btnOutHandler,false);

			// show info screen
			infoScreen.classList.remove("mini");
			infoScreen.classList.add("max");
		}

		infoScreenManager.minimize = function()
		{
			// hide info screen
			infoScreen.classList.add("mini");
			infoScreen.classList.remove("max");

			// enable mouseout of infoscreenbtn
			infoScreenBtn.addEventListener("mouseout",btnOutHandler,false);

			// record that the info screen has been seen
			webStorageProxy.setItem(infoScreen.storageName,true);
		}

		// PRIVATE METHODS
		// minimize the info/help box
		function minimizeHandler(evt)
		{
			if (evt.target.attributes["href"] == undefined)
			{
				infoScreenManager.minimize();
				// mouseout of button is cursor is not over the button
				if (infoScreenBtn != document.elementFromPoint(evt.clientX, evt.clientY) )
				{
					btnOutHandler();
				}
			}
		}

		// expand the info/help box
		function maximizeHandler(evt)
		{
			infoScreenManager.maximize();
		}

		// rollover handlers for the minified info/help box
		function btnOverHandler(evt)
		{
			infoScreenBtn.classList.add("over");
		}

		function btnOutHandler(evt)
		{
			infoScreenBtn.classList.remove("over");
		}

		return infoScreenManager;
	})();

	//=================================================================================
	// manages closing of alert box
	var alertManager = (function(){
		var alertManager = {};

		// PRIVATE PROPERTIES
		var messagesBox; // alert message box

		// PUBLIC METHODS
		alertManager.init = function()
		{
			messagesBox = document.getElementById("messages");

			messagesBox.addEventListener("mousedown", closeHandler, false)
		}

		// PRIVATE METHODS
		function closeHandler(evt)
		{
			// if clicked element has a close class, remove alert box content
			if (evt.target.classList.contains("close")) messagesBox.innerHTML = "";
		}

		return alertManager;
	})();

	//=================================================================================
	// Utility JS functions
	var util = (function(){
		var util = {};

		// get computed style (from http://stackoverflow.com/questions/2664045/how-to-retrieve-a-styles-value-in-javascript)
		util.getStyle = function(el, styleProp) {
		  var value, defaultView = (el.ownerDocument || document).defaultView;
		  // W3C standard way:
		  if (defaultView && defaultView.getComputedStyle) {
		    // sanitize property name to css notation
		    // (hypen separated words eg. font-Size)
		    styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
		    return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
		  } else if (el.currentStyle) { // IE
		    // sanitize property name to camelCase
		    styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) {
		      return letter.toUpperCase();
		    });
		    value = el.currentStyle[styleProp];
		    // convert other units to pixels on IE
		    if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
		      return (function(value) {
		        var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
		        el.runtimeStyle.left = el.currentStyle.left;
		        el.style.left = value || 0;
		        value = el.style.pixelLeft + "px";
		        el.style.left = oldLeft;
		        el.runtimeStyle.left = oldRsLeft;
		        return value;
		      })(value);
		    }
		    return value;
		  }
		}

		return util;
	})();

// return internally scoped var as value of globally scoped object
return main;

})();

/*
// new app object template
var search = (function () {
"use strict";

	var search = {};

	// initalize the application
	search.init = function()
	{

	}

	return search;

})();
*/<commit_msg>Fixes #59 - localstorage not being set<commit_after>/* Application functionality */

var main = (function () {
"use strict";
	var main = {};

	// initalize the application
	main.init = function()
	{
		busyManager.init();
		busyManager.hide(); // temp - immediately hide
		infoScreenManager.init(); // initialize help/info screen (in utility bar)
		alertManager.init(); // intialize alert box manager
	}

	//=================================================================================
	// manages show and hiding of splash screen
		var busyManager = (function(){
		var busyManager = {};

		var splashScreen; // loading screen

		// PUBLIC METHODS
		busyManager.init = function()
		{
			splashScreen = document.getElementById("splash-screen");
			//.success(function() { dataLoadedSuccess(); })
			//.error(function() { dataLoadedError(); })
			//.complete(function() { dataLoadedComplete(); });
		}

		// PUBLIC METHODS
		busyManager.show = function()
		{
			console.log("show splash screen");
			splashScreen.classList.remove("hide");
		}

		busyManager.hide = function()
		{
			console.log("hide splash screen");
			splashScreen.classList.add("hide");
		}

		return busyManager;
	})();

	//=================================================================================
	// manages show and hiding of info screen
	var infoScreenManager = (function(){
		var infoScreenManager = {};

		// PRIVATE PROPERTIES
		var infoScreenBtn; // help screen that covers content
		var infoScreen; // help screen that covers content

		// PUBLIC PROPERTIES
		infoScreenManager.storageName = "hrl-infoscreen";

		// PUBLIC METHODS
		infoScreenManager.init = function()
		{
			//console.log("initialized infoscreen");
			infoScreenBtn = document.getElementById("info-screen-btn");
			infoScreen = document.getElementById("info-screen");

			infoScreenBtn.addEventListener("mouseover",btnOverHandler,false);
			infoScreenBtn.addEventListener("mouseout",btnOutHandler,false);
			infoScreenBtn.addEventListener("mousedown",maximizeHandler,false);

			infoScreen.addEventListener("mousedown",minimizeHandler,false);

			if (webStorageProxy.getItem(infoScreenManager.storageName))
				infoScreenManager.minimize();
			else
				infoScreenManager.maximize();
		}

		// PUBLIC METHODS
		infoScreenManager.maximize = function()
		{
			// prevent mouseout of infoscreenbtn
			infoScreenBtn.removeEventListener("mouseout",btnOutHandler,false);

			// show info screen
			infoScreen.classList.remove("mini");
			infoScreen.classList.add("max");
		}

		infoScreenManager.minimize = function()
		{
			// hide info screen
			infoScreen.classList.add("mini");
			infoScreen.classList.remove("max");

			// enable mouseout of infoscreenbtn
			infoScreenBtn.addEventListener("mouseout",btnOutHandler,false);

			// record that the info screen has been seen
			webStorageProxy.setItem(infoScreenManager.storageName,true);
		}

		// PRIVATE METHODS
		// minimize the info/help box
		function minimizeHandler(evt)
		{
			if (evt.target.attributes["href"] == undefined)
			{
				infoScreenManager.minimize();
				// mouseout of button is cursor is not over the button
				if (infoScreenBtn != document.elementFromPoint(evt.clientX, evt.clientY) )
				{
					btnOutHandler();
				}
			}
		}

		// expand the info/help box
		function maximizeHandler(evt)
		{
			infoScreenManager.maximize();
		}

		// rollover handlers for the minified info/help box
		function btnOverHandler(evt)
		{
			infoScreenBtn.classList.add("over");
		}

		function btnOutHandler(evt)
		{
			infoScreenBtn.classList.remove("over");
		}

		return infoScreenManager;
	})();

	//=================================================================================
	// manages closing of alert box
	var alertManager = (function(){
		var alertManager = {};

		// PRIVATE PROPERTIES
		var messagesBox; // alert message box

		// PUBLIC METHODS
		alertManager.init = function()
		{
			messagesBox = document.getElementById("messages");

			messagesBox.addEventListener("mousedown", closeHandler, false)
		}

		// PRIVATE METHODS
		function closeHandler(evt)
		{
			// if clicked element has a close class, remove alert box content
			if (evt.target.classList.contains("close")) messagesBox.innerHTML = "";
		}

		return alertManager;
	})();

	//=================================================================================
	// Utility JS functions
	var util = (function(){
		var util = {};

		// get computed style (from http://stackoverflow.com/questions/2664045/how-to-retrieve-a-styles-value-in-javascript)
		util.getStyle = function(el, styleProp) {
		  var value, defaultView = (el.ownerDocument || document).defaultView;
		  // W3C standard way:
		  if (defaultView && defaultView.getComputedStyle) {
		    // sanitize property name to css notation
		    // (hypen separated words eg. font-Size)
		    styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
		    return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
		  } else if (el.currentStyle) { // IE
		    // sanitize property name to camelCase
		    styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) {
		      return letter.toUpperCase();
		    });
		    value = el.currentStyle[styleProp];
		    // convert other units to pixels on IE
		    if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
		      return (function(value) {
		        var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
		        el.runtimeStyle.left = el.currentStyle.left;
		        el.style.left = value || 0;
		        value = el.style.pixelLeft + "px";
		        el.style.left = oldLeft;
		        el.runtimeStyle.left = oldRsLeft;
		        return value;
		      })(value);
		    }
		    return value;
		  }
		}

		return util;
	})();

// return internally scoped var as value of globally scoped object
return main;

})();

/*
// new app object template
var search = (function () {
"use strict";

	var search = {};

	// initalize the application
	search.init = function()
	{

	}

	return search;

})();
*/<|endoftext|>


<commit_before>const { getVehiclesInRange, updateVehicleStatus, getVehicle, getVehicles } = require('../store/vehicles');
const { getBidsForRequest } = require('../store/bids');
const { getLatestMissionId, getMission, updateMission } = require('../store/missions');
const { createMissionUpdate } = require('../store/mission_updates');
const { hasStore } = require('../lib/environment');
const missionProgress = require('../simulation/missionProgress');
const _ = require('lodash');

const getStatus = async (req, res) => {
  const { lat, long, requestId, user_id } = req.query;
  const status = 'idle';
  const latestMissionId = await getLatestMissionId(user_id);
  const latestMission = await getMission(latestMissionId);
  const bids = (!hasStore() || !requestId) ? [] : await getBidsForRequest(requestId);
  let vehicles = [];
  if (hasStore()) {
    if (bids.length > 0) {
      vehicles = await getVehicles(bids.map(bid => bid.vehicle_id));
    } else {
      vehicles = await getVehiclesInRange(
        { lat: parseFloat(lat), long: parseFloat(long) },
        7000,
      );
    }
  }

  if (latestMission) {
    switch (latestMission.status) {
    case 'awaiting_signatures': {
      let elapsedTime = Date.now() - latestMission.user_signed_at;
      let elapsedSeconds = ((elapsedTime % 60000) / 1000).toFixed(0);
      if (elapsedSeconds > 6) {
        await updateMission(latestMissionId, {'vehicle_signed_at': Date.now(), 'status': 'in_progress'});
        await updateVehicleStatus(latestMission.vehicle_id, 'travelling_pickup');
        await createMissionUpdate(latestMissionId, 'travelling_pickup');
      }
      res.json({status, vehicles, bids});
      break;
    }
    case 'in_progress': {
      const mission = latestMission;
      const vehicle = await getVehicle(latestMission.vehicle_id);
      const status = 'in_mission';
      const currentStatus = _.find(missionProgress, {'status': vehicle.status});
      if (currentStatus.conditionForNextStatus(latestMission)){
        const timestampString = currentStatus.nextMissionStatus + '_at';
        let timestampObject = {};
        timestampObject[timestampString] = Date.now();
        await updateMission(latestMissionId, timestampObject);
        await createMissionUpdate(latestMissionId, currentStatus.nextMissionStatus);
        await updateVehicleStatus(latestMission.vehicle_id, currentStatus.nextVehicleStatus);
      }
      vehicles = [vehicle];
      res.json({status, vehicles, bids, mission});
      break;
    }
    }
  } else {
    res.json({ status, vehicles, bids });
  }
};

module.exports = { getStatus };
<commit_msg>fix: prevent execution from trying to get conditionForNextStatus for waiting_pickup vehicle status<commit_after>const { getVehiclesInRange, updateVehicleStatus, getVehicle, getVehicles } = require('../store/vehicles');
const { getBidsForRequest } = require('../store/bids');
const { getLatestMissionId, getMission, updateMission } = require('../store/missions');
const { createMissionUpdate } = require('../store/mission_updates');
const { hasStore } = require('../lib/environment');
const missionProgress = require('../simulation/missionProgress');
const _ = require('lodash');

const getStatus = async (req, res) => {
  const { lat, long, requestId, user_id } = req.query;
  const status = 'idle';
  const latestMissionId = await getLatestMissionId(user_id);
  const latestMission = await getMission(latestMissionId);
  const bids = (!hasStore() || !requestId) ? [] : await getBidsForRequest(requestId);
  let vehicles = [];
  if (hasStore()) {
    if (bids.length > 0) {
      vehicles = await getVehicles(bids.map(bid => bid.vehicle_id));
    } else {
      vehicles = await getVehiclesInRange(
        { lat: parseFloat(lat), long: parseFloat(long) },
        7000,
      );
    }
  }

  if (latestMission) {
    switch (latestMission.status) {
    case 'awaiting_signatures': {
      let elapsedTime = Date.now() - latestMission.user_signed_at;
      let elapsedSeconds = ((elapsedTime % 60000) / 1000).toFixed(0);
      if (elapsedSeconds > 6) {
        await updateMission(latestMissionId, {'vehicle_signed_at': Date.now(), 'status': 'in_progress'});
        await updateVehicleStatus(latestMission.vehicle_id, 'travelling_pickup');
        await createMissionUpdate(latestMissionId, 'travelling_pickup');
      }
      res.json({status, vehicles, bids});
      break;
    }
    case 'in_progress': {
      const mission = latestMission;
      const vehicle = await getVehicle(latestMission.vehicle_id);
      const status = 'in_mission';
      if (vehicle.status !== 'waiting_pickup'){
        const currentStatus = _.find(missionProgress, {'status': vehicle.status});
        if (currentStatus.conditionForNextStatus(latestMission)){
          const timestampString = currentStatus.nextMissionStatus + '_at';
          let timestampObject = {};
          timestampObject[timestampString] = Date.now();
          await updateMission(latestMissionId, timestampObject);
          await createMissionUpdate(latestMissionId, currentStatus.nextMissionStatus);
          await updateVehicleStatus(latestMission.vehicle_id, currentStatus.nextVehicleStatus);
        }
      }
      vehicles = [vehicle];
      res.json({status, vehicles, bids, mission});
      break;
    }
    }
  } else {
    res.json({ status, vehicles, bids });
  }
};

module.exports = { getStatus };
<|endoftext|>