<commit_before>/**
 * This module is a helper in order to test modules that requires DOM access
 * such as globally available `window` or `document`.
 *
 * You should use it wrapping it around your `DOM`-dependent module. Example:
 *
 * ```js
 *  it('test feature', function() {
 *    const cleanup = require('../helpers/global-dom')('<html></html>', { url: '/sign_in' });
 *    const myModule = require('my-module');
 *
 *    // Test myModule
 *
 *    cleanup();
 *  })
 * ```
 *
 * It **WILL NOT** work with `import` statement. If you want to use `import`,
 * please, use as the following:
 *
 * ```js
 *  import cleanup from '../helpers/register-global-dom'
 *  import 'my-module'
 *
 *  // ...
 * ```
 *
 * The only drawback of using it like that is that you can't customize the HTML
 * nor the URI that you want to stub. Also, the global variables will remain
 * through all the script and you will have little control of them.
 */
module.exports = function globalJsDOM(html, options) {
  const defaultHtml = `<!doctype html>
    <meta charset="utf-8">
    `;

  const jsDomOptions = Object.assign({
    url: `${process.env.BASE_URL}/index?query=1#hashstr`,
    referrer: process.env.BASE_URL,
    contentType: 'text/html',
    userAgent: 'JSDOM',
    includeNodeLocations: false,
  }, options);

  // Loads JSDOM and injects it globally
  // eslint-disable-next-line global-require
  const cleanup = require('jsdom-global')(html || defaultHtml, jsDomOptions);

  // Set the document.domain, since JSDOM.url doesn't
  document.domain = `${window.location.protocol}://${window.location.host}`;

  return cleanup;
};
<commit_msg>Add a reference to `window` on our fake-browser emulator<commit_after>/**
 * This module is a helper in order to test modules that requires DOM access
 * such as globally available `window` or `document`.
 *
 * You should use it wrapping it around your `DOM`-dependent module. Example:
 *
 * ```js
 *  it('test feature', function() {
 *    const cleanup = require('../helpers/global-dom')('<html></html>', { url: '/sign_in' });
 *    const myModule = require('my-module');
 *
 *    // Test myModule
 *
 *    cleanup();
 *  })
 * ```
 *
 * It **WILL NOT** work with `import` statement. If you want to use `import`,
 * please, use as the following:
 *
 * ```js
 *  import cleanup from '../helpers/register-global-dom'
 *  import 'my-module'
 *
 *  // ...
 * ```
 *
 * The only drawback of using it like that is that you can't customize the HTML
 * nor the URI that you want to stub. Also, the global variables will remain
 * through all the script and you will have little control of them.
 */
module.exports = function globalJsDOM(html, options) {
  const defaultHtml = `<!doctype html>
    <meta charset="utf-8">
    `;

  const jsDomOptions = Object.assign({
    url: `${process.env.BASE_URL}/index?query=1#hashstr`,
    referrer: process.env.BASE_URL,
    contentType: 'text/html',
    userAgent: 'JSDOM',
    includeNodeLocations: false,
  }, options);

  // Loads JSDOM and injects it globally
  // eslint-disable-next-line global-require
  const cleanup = require('jsdom-global')(html || defaultHtml, jsDomOptions);

  // Set the document.domain, since JSDOM.url doesn't
  document.domain = `${window.location.protocol}://${window.location.host}`;

  // Add circular reference to have `window` as an alias to the `global` object
  window = global;

  return cleanup;
};
<|endoftext|>


<commit_before>//DashboardBundle
Mautic.dashboardOnLoad = function (container) {
    Mautic.loadDashboardMap();
    Mautic.renderOpenRateDoughnut();
    Mautic.updateActiveVisitorCount();
    setInterval(function() {
        Mautic.updateActiveVisitorCount();
    }, 5000);

};

Mautic.loadDashboardMap = function () {
    var mapData = {};
    mQuery.ajax({
        url: mauticAjaxUrl,
        type: "POST",
        data: "action=dashboard:mapData",
        dataType: "json",
        success: function (response) {
            if (response.success) {
                mapData = response.stats;
            }
            Mautic.stopIconSpinPostEvent(event);
        },
        error: function (request, textStatus, errorThrown) {
            Mautic.processAjaxError(request, textStatus, errorThrown);
            Mautic.stopIconSpinPostEvent(event);
        },
        complete: function () {
            jQuery('#dashboard-map').vectorMap({
                map: 'world_en',
                backgroundColor: null,
                color: '#ffffff',
                hoverOpacity: 0.7,
                selectedColor: '#666666',
                enableZoom: true,
                showTooltip: true,
                values: mapData,
                scaleColors: ['#C8EEFF', '#006491'],
                normalizeFunction: 'polynomial',
                onLabelShow: function (event, label, code) {
                    if(mapData[code] > 0) {
                        label.find('span').remove();
                        label.append('<span>: '+mapData[code]+' Leads<span>');
                    }
                }
            });
        }
    });
}

Mautic.renderOpenRateDoughnut = function () {
    var element = mQuery('#open-reate');
    var sentCount = +element.attr('data-sent-count');
    var readCount = +element.attr('data-read-count');
    var options = {percentageInnerCutout: 90, responsive: false}
    var data = [
        {
            value: readCount,
            color:"#4E5D9D",
            highlight: "#353F6A",
            label: "Opened"
        },
        {
            value: sentCount - readCount,
            color: "#ffffff",
            highlight: "#EBEBEB",
            label: "Not opened"
        }
    ];
    var ctx = document.getElementById("open-reate").getContext("2d");
    var myNewChart = new Chart(ctx).Doughnut(data, options);
}

Mautic.updateActiveVisitorCount = function () {
    mQuery.ajax({
        url: mauticAjaxUrl,
        type: "POST",
        data: "action=dashboard:viewingVisitors",
        dataType: "json",
        success: function (response) {
            if (response.success) {
                var element = mQuery('#active-visitors');
                element.text(response.viewingVisitors);
                if (response.viewingVisitors != Mautic.ActiveVisitorsCount) {
                    var color = '#34D43B';
                    if (Mautic.ActiveVisitorsCount > response.viewingVisitors) {
                        color = '#BC2525';
                    }
                    element.css('text-shadow', color+' 0px 0px 50px');
                    setTimeout(function() {
                        element.css('text-shadow', '#fff 0px 0px 50px');
                    }, 3000);
                }
                Mautic.ActiveVisitorsCount = response.viewingVisitors;
            }
        },
        error: function (request, textStatus, errorThrown) {
            Mautic.processAjaxError(request, textStatus, errorThrown);
        }
    });
}
<commit_msg>5 sec update of active visitors commented out. It adds new ajax call each time chat:updateList is called<commit_after>//DashboardBundle
Mautic.dashboardOnLoad = function (container) {
    Mautic.loadDashboardMap();
    Mautic.renderOpenRateDoughnut();
    Mautic.updateActiveVisitorCount();
    // setInterval(function() {
    //     Mautic.updateActiveVisitorCount();
    // }, 5000);

};

Mautic.loadDashboardMap = function () {
    var mapData = {};
    mQuery.ajax({
        url: mauticAjaxUrl,
        type: "POST",
        data: "action=dashboard:mapData",
        dataType: "json",
        success: function (response) {
            if (response.success) {
                mapData = response.stats;
            }
            Mautic.stopIconSpinPostEvent(event);
        },
        error: function (request, textStatus, errorThrown) {
            Mautic.processAjaxError(request, textStatus, errorThrown);
            Mautic.stopIconSpinPostEvent(event);
        },
        complete: function () {
            jQuery('#dashboard-map').vectorMap({
                map: 'world_en',
                backgroundColor: null,
                color: '#ffffff',
                hoverOpacity: 0.7,
                selectedColor: '#666666',
                enableZoom: true,
                showTooltip: true,
                values: mapData,
                scaleColors: ['#C8EEFF', '#006491'],
                normalizeFunction: 'polynomial',
                onLabelShow: function (event, label, code) {
                    if(mapData[code] > 0) {
                        label.find('span').remove();
                        label.append('<span>: '+mapData[code]+' Leads<span>');
                    }
                }
            });
        }
    });
}

Mautic.renderOpenRateDoughnut = function () {
    var element = mQuery('#open-reate');
    var sentCount = +element.attr('data-sent-count');
    var readCount = +element.attr('data-read-count');
    var options = {percentageInnerCutout: 90, responsive: false}
    var data = [
        {
            value: readCount,
            color:"#4E5D9D",
            highlight: "#353F6A",
            label: "Opened"
        },
        {
            value: sentCount - readCount,
            color: "#ffffff",
            highlight: "#EBEBEB",
            label: "Not opened"
        }
    ];
    var ctx = document.getElementById("open-reate").getContext("2d");
    var myNewChart = new Chart(ctx).Doughnut(data, options);
}

Mautic.updateActiveVisitorCount = function () {
    mQuery.ajax({
        url: mauticAjaxUrl,
        type: "POST",
        data: "action=dashboard:viewingVisitors",
        dataType: "json",
        success: function (response) {
            if (response.success) {
                var element = mQuery('#active-visitors');
                element.text(response.viewingVisitors);
                if (response.viewingVisitors != Mautic.ActiveVisitorsCount) {
                    var color = '#34D43B';
                    if (Mautic.ActiveVisitorsCount > response.viewingVisitors) {
                        color = '#BC2525';
                    }
                    element.css('text-shadow', color+' 0px 0px 50px');
                    setTimeout(function() {
                        element.css('text-shadow', '#fff 0px 0px 50px');
                    }, 3000);
                }
                Mautic.ActiveVisitorsCount = response.viewingVisitors;
            }
        },
        error: function (request, textStatus, errorThrown) {
            Mautic.processAjaxError(request, textStatus, errorThrown);
        }
    });
}
<|endoftext|>


<commit_before>
'use strict';

import { expect } from 'chai';

import titleCanvas from '../../../../client/scripts/public/modules/titleCanvas';

describe('ARCADE MODE Canvas animation', () => {
  const canvasObject = titleCanvas();

  before(() => {
    document.body.innerHTML =
'
<canvas class="am__am__canvas" height="50" width="220">ARCADE MODE</canvas><svg class="am__am__svg"><clipPath id="arcadePath"><text class="am__am__canvas__text" x="0" y="35">ARCADE MODE</text></clipPath></svg>
';

    canvasObject.init();
  });

  after(() => {
    document.body.removeChild(document.querySelector('.am__am__link'));
  });

  it('should render', () => {
    const canvasEl = document.querySelector('.am__am__canvas');
    expect(canvasEl.height).to.equal(50);
    expect(canvasEl.width).to.equal(220);
    expect(canvasObject.hue).to.be.within(0, 360);
  });
});
<commit_msg>update link<commit_after>
'use strict';

import { expect } from 'chai';

import titleCanvas from '../../../../client/scripts/public/modules/titleCanvas';

describe('ARCADE MODE Canvas animation', () => {
  const canvasObject = titleCanvas();

  before(() => {
    document.body.innerHTML =
'
<canvas class="am__am__canvas" height="50" width="220">ARCADE MODE</canvas><svg class="am__am__svg"><clipPath id="arcadePath"><text class="am__am__canvas__text" x="0" y="35">ARCADE MODE</text></clipPath></svg>
';

    canvasObject.init();
  });

  after(() => {
    document.body.removeChild(document.querySelector('.am__am__link'));
  });

  it('should render', () => {
    const canvasEl = document.querySelector('.am__am__canvas');
    expect(canvasEl.height).to.equal(50);
    expect(canvasEl.width).to.equal(220);
    expect(canvasObject.hue).to.be.within(0, 360);
  });
});
<|endoftext|>


<commit_before>// @flow

import React from 'react';
import Relay from 'react-relay/classic';
import { CSSTransition } from 'react-transition-group';
import classNames from 'classnames';
import { hour, seconds } from 'metrick/duration';

import PusherStore from '../../../../stores/PusherStore';
import Button from '../../../shared/Button';
import Spinner from '../../../shared/Spinner';
import Dropdown from '../../../shared/Dropdown';
import Icon from '../../../shared/Icon';
import Badge from '../../../shared/Badge';

import Build from './build';
import DropdownButton from './../dropdown-button';

type Props = {
  viewer?: Object,
  relay: Object
};

type State = {
  isDropdownVisible: boolean,
  scheduledBuildsCount: number,
  runningBuildsCount: number
};

class MyBuilds extends React.Component<Props, State> {
  constructor(props) {
    super(props);

    // When the MyBuilds starts, see if we've got either cached or
    // current build numbers so we can show something right away.
    const initialState = {
      isDropdownVisible: false,
      scheduledBuildsCount: (
        (this.props.viewer && this.props.viewer.scheduledBuilds)
          ? this.props.viewer.scheduledBuilds.count
          : 0
      ),
      runningBuildsCount: (
        (this.props.viewer && this.props.viewer.runningBuilds)
          ? this.props.viewer.runningBuilds.count
          : 0
      )
    };

    const cachedState = this.getCachedState();

    if (!this.props.viewer || !this.props.viewer.scheduledBuilds) {
      initialState.scheduledBuildsCount = cachedState.scheduledBuildsCount || 0;
    }

    if (!this.props.viewer || !this.props.viewer.runningBuilds) {
      initialState.runningBuildsCount = cachedState.runningBuildsCount || 0;
    }

    this.state = initialState;
  }

  // NOTE: the localStorage key is 'CachedState:MyBuilds:' for backwards
  // compatibility with data stored by the CachedStateWrapper this used to use.
  getCachedState() {
    const { state, expiresAt } = JSON.parse(localStorage['CachedState:MyBuilds:'] || '{}');

    if (!state || (expiresAt && expiresAt < Date.now())) {
      return {};
    }

    return state;
  }

  setCachedState(state = {}) {
    this.setState(state, () => {
      localStorage['CachedState:MyBuilds:'] = JSON.stringify({
        state,
        expiresAt: Date.now() + hour.bind(1)
      });
    });
  }

  componentDidMount() {
    PusherStore.on("user_stats:change", this.handlePusherWebsocketEvent);

    // Now that "My Builds" has been mounted on the page and Pusher has
    // connected, we should force a refetch of the latest `scheduledBuilds` and
    // `runningBuilds` counts from GraphQL.
    PusherStore.on("connected", this.handlePusherConnected);

    // If pusher doesn't connect in 3 seconds, just force the callback
    // manually.  This can happen if Pusher is being a bit weird, or when
    // Pusher isn't connected at all (like in the case of automated tests)
    setTimeout(this.handlePusherConnected, seconds.bind(3));
  }

  componentWillUnmount() {
    PusherStore.off("user_stats:change", this.handlePusherWebsocketEvent);
    PusherStore.off("connected", this.handlePusherConnected);
  }

  // As we get new values for scheduledBuildsCount and runningBuildsCount from
  // Relay + GraphQL, we'll be sure to update the cached state with the latest
  // values so when the page re-loads, we can show the latest numbers.
  componentDidUpdate() {
    if (!this.props.viewer) {
      return;
    }

    if (this.props.viewer.scheduledBuilds || this.props.viewer.runningBuilds) {
      this.setCachedState({
        scheduledBuildsCount: this.props.viewer.scheduledBuilds.count,
        runningBuildsCount: this.props.viewer.runningBuilds.count
      });
    }
  }

  render() {
    return (
      <Dropdown width={320} className="flex ml-auto" onToggle={this.handleDropdownToggle}>
        <DropdownButton className={classNames("flex-none py0", { "lime": this.state.isDropdownVisible })} onMouseEnter={this.handleButtonMouseEnter}>
          {'My Builds '}

            <CSSTransition
              in={this.getBuildsCount() > 0}
              classNames="transition-appear-pop"
              timeout={{
                enter: 200,
                exit: 200
              }}
            >
              {this.renderBadge()}
            </CSSTransition>

          <Icon
            icon="down-triangle"
            className="flex-none"
            style={{
              width: 7,
              height: 7,
              marginLeft: '.5em'
            }}
          />
        </DropdownButton>

        {this.renderDropdown()}
      </Dropdown>
    );
  }

  getBuildsCount() {
    return this.state.runningBuildsCount + this.state.scheduledBuildsCount;
  }

  renderBadge() {
    const buildsCount = this.getBuildsCount();

    // Render nothing (an empty span) if we've not got a number to show
    if (!buildsCount) {
      return ;
    }

    return (
      <Badge className={classNames("hover-lime-child", { "bg-lime": this.state.isDropdownVisible })}>
        {buildsCount}
      </Badge>
    );
  }

  renderDropdown() {
    // If `builds` here is null, that means that Relay hasn't fetched the data
    // for it yet. It will become an Array once it's loaded.
    if (!this.props.viewer || !this.props.viewer.user.builds) {
      return this.renderSpinner();
    }

    // Once we've got an array of builds, we either show what we have, or the
    // setup instructions.
    if (this.props.viewer.user.builds.edges.length > 0) {
      return this.renderBuilds();
    }

    return this.renderSetupInstructions();
  }

  renderBuilds() {
    if (!this.props.viewer) {
      return;
    }

    return (

          {this.props.viewer.user.builds.edges.map((edge) => <Build key={edge.node.id} build={edge.node} />)}

          <Button href="/builds" theme="default" outline={true} className="center" style={{ width: "100%" }}>More Builds</Button>

    );
  }

  renderSetupInstructions() {
    return (

To have your builds appear here, make sure that your commit email address (e.g. git config user.email) is added and verified in your list of personal email addresses.

        <Button href="/user/emails" theme="default" outline={true} className="center" style={{ width: "100%" }}>Update Email Addresses</Button>

    );
  }

  renderSpinner() {
    return (

        <Spinner />

    );
  }

  handleDropdownToggle = (visible) => {
    // If `includeBuilds` hasn't been set to `true` yet (perhaps the mouseEnter
    // event never got triggered because we're on a mobile device) trigger a
    // load of the builds as the dropdown opens.
    if (!this.props.relay.variables.includeBuilds) {
      this.props.relay.forceFetch({ includeBuilds: true });
    }

    this.setState({ isDropdownVisible: visible });
  };

  handlePusherConnected = () => {
    if (!this.props.relay.variables.includeBuildCounts) {
      this.props.relay.forceFetch({ includeBuildCounts: true });
    }
  };

  // If the user is hovering over the "My Builds" button, be sneaky and start
  // loading the build data in the background.
  handleButtonMouseEnter = () => {
    if (!this.props.relay.variables.includeBuilds) {
      this.props.relay.forceFetch({ includeBuilds: true });
    }
  };

  // When we recieve a Pusher event, check to see if the build counts have
  // changed (meaning a new build has probably started or finished). In that
  // case, we'll perform a full refersh of the My Builds data (including new
  // numbers for the nav and the builds themselves).
  //
  // We don't use the data from the payload otherwise the UI would update, and
  // then the builds would update a few moments later when the GraphQL query
  // finishes, which would be a bit weird.
  handlePusherWebsocketEvent = (payload) => {
    const scheduledBuildsCountChanged = this.state.scheduledBuildsCount !== payload.scheduledBuildsCount;
    const runningBuildsCountChanged = this.state.runningBuildsCount !== payload.runningBuildsCount;

    if (scheduledBuildsCountChanged || runningBuildsCountChanged) {
      this.props.relay.forceFetch();
    }
  };
}

export default Relay.createContainer(MyBuilds, {
  initialVariables: {
    includeBuilds: false,
    includeBuildCounts: false
  },

  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        user {
          builds(first: 5) @include(if: $includeBuilds) {
            edges {
              node {
                id
                ${Build.getFragment('build')}
              }
            }
          }
        }
        runningBuilds: builds(state: RUNNING) @include(if: $includeBuildCounts) {
          count
        }
        scheduledBuilds: builds(state: SCHEDULED) @include(if: $includeBuildCounts) {
          count
        }
      }
    `
  }
});
<commit_msg>Actually fix the MyBuilds counts' lifecycle stuff<commit_after>// @flow

import React from 'react';
import Relay from 'react-relay/classic';
import { CSSTransition } from 'react-transition-group';
import classNames from 'classnames';
import { hour, seconds } from 'metrick/duration';

import PusherStore from '../../../../stores/PusherStore';
import Button from '../../../shared/Button';
import Spinner from '../../../shared/Spinner';
import Dropdown from '../../../shared/Dropdown';
import Icon from '../../../shared/Icon';
import Badge from '../../../shared/Badge';

import Build from './build';
import DropdownButton from './../dropdown-button';

type ViewerPartial = {
  scheduledBuilds: {
    count: number
  },
  runningBuilds: {
    count: number
  }
};

type Props = {
  viewer?: ViewerPartial,
  relay: Object
};

type State = {
  isDropdownVisible: boolean,
  scheduledBuildsCount: number,
  runningBuildsCount: number
};

class MyBuilds extends React.Component<Props, State> {
  constructor(props) {
    super(props);

    // When the MyBuilds starts, see if we've got either cached or
    // current build numbers so we can show something right away.
    const initialState = {
      isDropdownVisible: false,
      scheduledBuildsCount: (
        (this.props.viewer && this.props.viewer.scheduledBuilds)
          ? this.props.viewer.scheduledBuilds.count
          : 0
      ),
      runningBuildsCount: (
        (this.props.viewer && this.props.viewer.runningBuilds)
          ? this.props.viewer.runningBuilds.count
          : 0
      )
    };

    const cachedState = this.getCachedState();

    if (!this.props.viewer || !this.props.viewer.scheduledBuilds) {
      initialState.scheduledBuildsCount = cachedState.scheduledBuildsCount || 0;
    }

    if (!this.props.viewer || !this.props.viewer.runningBuilds) {
      initialState.runningBuildsCount = cachedState.runningBuildsCount || 0;
    }

    this.state = initialState;
  }

  // NOTE: the localStorage key is 'CachedState:MyBuilds:' for backwards
  // compatibility with data stored by the CachedStateWrapper this used to use.
  getCachedState() {
    const { state, expiresAt } = JSON.parse(localStorage['CachedState:MyBuilds:'] || '{}');

    if (!state || (expiresAt && expiresAt < Date.now())) {
      return {};
    }

    return state;
  }

  setCachedState(state = {}) {
    this.setState(state, () => {
      localStorage['CachedState:MyBuilds:'] = JSON.stringify({
        state,
        expiresAt: Date.now() + hour.bind(1)
      });
    });
  }

  componentDidMount() {
    PusherStore.on("user_stats:change", this.handlePusherWebsocketEvent);

    // Now that "My Builds" has been mounted on the page and Pusher has
    // connected, we should force a refetch of the latest `scheduledBuilds` and
    // `runningBuilds` counts from GraphQL.
    PusherStore.on("connected", this.handlePusherConnected);

    // If pusher doesn't connect in 3 seconds, just force the callback
    // manually.  This can happen if Pusher is being a bit weird, or when
    // Pusher isn't connected at all (like in the case of automated tests)
    setTimeout(this.handlePusherConnected, seconds.bind(3));
  }

  componentWillUnmount() {
    PusherStore.off("user_stats:change", this.handlePusherWebsocketEvent);
    PusherStore.off("connected", this.handlePusherConnected);
  }

  // As we get new values for scheduledBuildsCount and runningBuildsCount from
  // Relay + GraphQL, we'll be sure to update the cached state with the latest
  // values so when the page re-loads, we can show the latest numbers.
  componentDidUpdate(prevProps: { viewer?: ViewerPartial }) {
    const { viewer } = this.props;
    const { viewer: prevViewer } = prevProps;

    // If we don't have a current Viewer object, we know we don't have fresh data
    if (!viewer) {
      return;
    }

    // If we have a previous viewer object with build data, let's
    // check if any of the counts have changed, and abort if not
    if (prevViewer && prevViewer.scheduledBuilds && prevViewer.runningBuilds) {
      if (
        viewer.scheduledBuilds.count === prevViewer.scheduledBuilds.count &&
        viewer.runningBuilds.count === prevViewer.runningBuilds.count
      ) {
        return;
      }
    }

    // Finally, update the state
    this.setCachedState({
      scheduledBuildsCount: viewer.scheduledBuilds.count,
      runningBuildsCount: viewer.runningBuilds.count
    });
  }

  render() {
    return (
      <Dropdown width={320} className="flex ml-auto" onToggle={this.handleDropdownToggle}>
        <DropdownButton className={classNames("flex-none py0", { "lime": this.state.isDropdownVisible })} onMouseEnter={this.handleButtonMouseEnter}>
          {'My Builds '}

            <CSSTransition
              in={this.getBuildsCount() > 0}
              classNames="transition-appear-pop"
              timeout={{
                enter: 200,
                exit: 200
              }}
            >
              {this.renderBadge()}
            </CSSTransition>

          <Icon
            icon="down-triangle"
            className="flex-none"
            style={{
              width: 7,
              height: 7,
              marginLeft: '.5em'
            }}
          />
        </DropdownButton>

        {this.renderDropdown()}
      </Dropdown>
    );
  }

  getBuildsCount() {
    return this.state.runningBuildsCount + this.state.scheduledBuildsCount;
  }

  renderBadge() {
    const buildsCount = this.getBuildsCount();

    // Render nothing (an empty span) if we've not got a number to show
    if (!buildsCount) {
      return ;
    }

    return (
      <Badge className={classNames("hover-lime-child", { "bg-lime": this.state.isDropdownVisible })}>
        {buildsCount}
      </Badge>
    );
  }

  renderDropdown() {
    // If `builds` here is null, that means that Relay hasn't fetched the data
    // for it yet. It will become an Array once it's loaded.
    if (!this.props.viewer || !this.props.viewer.user.builds) {
      return this.renderSpinner();
    }

    // Once we've got an array of builds, we either show what we have, or the
    // setup instructions.
    if (this.props.viewer.user.builds.edges.length > 0) {
      return this.renderBuilds();
    }

    return this.renderSetupInstructions();
  }

  renderBuilds() {
    if (!this.props.viewer) {
      return;
    }

    return (

          {this.props.viewer.user.builds.edges.map((edge) => <Build key={edge.node.id} build={edge.node} />)}

          <Button href="/builds" theme="default" outline={true} className="center" style={{ width: "100%" }}>More Builds</Button>

    );
  }

  renderSetupInstructions() {
    return (

To have your builds appear here, make sure that your commit email address (e.g. git config user.email) is added and verified in your list of personal email addresses.

        <Button href="/user/emails" theme="default" outline={true} className="center" style={{ width: "100%" }}>Update Email Addresses</Button>

    );
  }

  renderSpinner() {
    return (

        <Spinner />

    );
  }

  handleDropdownToggle = (visible) => {
    // If `includeBuilds` hasn't been set to `true` yet (perhaps the mouseEnter
    // event never got triggered because we're on a mobile device) trigger a
    // load of the builds as the dropdown opens.
    if (!this.props.relay.variables.includeBuilds) {
      this.props.relay.forceFetch({ includeBuilds: true });
    }

    this.setState({ isDropdownVisible: visible });
  };

  handlePusherConnected = () => {
    if (!this.props.relay.variables.includeBuildCounts) {
      this.props.relay.forceFetch({ includeBuildCounts: true });
    }
  };

  // If the user is hovering over the "My Builds" button, be sneaky and start
  // loading the build data in the background.
  handleButtonMouseEnter = () => {
    if (!this.props.relay.variables.includeBuilds) {
      this.props.relay.forceFetch({ includeBuilds: true });
    }
  };

  // When we recieve a Pusher event, check to see if the build counts have
  // changed (meaning a new build has probably started or finished). In that
  // case, we'll perform a full refersh of the My Builds data (including new
  // numbers for the nav and the builds themselves).
  //
  // We don't use the data from the payload otherwise the UI would update, and
  // then the builds would update a few moments later when the GraphQL query
  // finishes, which would be a bit weird.
  handlePusherWebsocketEvent = (payload) => {
    const scheduledBuildsCountChanged = this.state.scheduledBuildsCount !== payload.scheduledBuildsCount;
    const runningBuildsCountChanged = this.state.runningBuildsCount !== payload.runningBuildsCount;

    if (scheduledBuildsCountChanged || runningBuildsCountChanged) {
      this.props.relay.forceFetch();
    }
  };
}

export default Relay.createContainer(MyBuilds, {
  initialVariables: {
    includeBuilds: false,
    includeBuildCounts: false
  },

  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        user {
          builds(first: 5) @include(if: $includeBuilds) {
            edges {
              node {
                id
                ${Build.getFragment('build')}
              }
            }
          }
        }
        runningBuilds: builds(state: RUNNING) @include(if: $includeBuildCounts) {
          count
        }
        scheduledBuilds: builds(state: SCHEDULED) @include(if: $includeBuildCounts) {
          count
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import i18n from '../../utils/i18n';
import Utils from '../../utils/misc';
import persistence from '../../utils/persistence';
import modal from '../../utils/modal';

export default Ember.Controller.extend({
  refresh_units: function() {
    var _this = this;
    this.set('units', {loading: true});
    Utils.all_pages('unit', {organization_id: this.get('model.id')}, function(list) {
      _this.set('units', list);
    }).then(function(data) {
      _this.set('units', data);
    }, function() {
      _this.set('units', {error: true});
    });
  },
  load_users: function() {
    var _this = this;
    Utils.all_pages('/api/v1/organizations/' + this.get('model.id') + '/users', {result_type: 'user', type: 'GET', data: {recent: true}}).then(function(data) {
      _this.set('all_communicators', data.filter(function(u) { return !u.org_pending; }));
    }, function(err) {
      _this.set('user_error', true);
    });
    Utils.all_pages('/api/v1/organizations/' + this.get('model.id') + '/supervisors', {result_type: 'user', type: 'GET', data: {recent: true}}).then(function(data) {
      _this.set('all_supervisors', data);
    }, function(err) {
      _this.set('user_error', true);
    });
  },
  supervisor_options: function() {
    var res = [{
      id: null,
      name: i18n.t('select_user', "[ Select User ]")
    }];
    (this.get('all_supervisors') || []).forEach(function(sup) {
      res.push({
        id: sup.id,
        name: sup.user_name
      });
    });
    return res;
  }.property('all_supervisors'),
  communicator_options: function() {
    var res = [{
      id: null,
      name: i18n.t('select_user', "[ Select User ]")
    }];
    (this.get('all_communicators') || []).forEach(function(sup) {
      res.push({
        id: sup.id,
        name: sup.user_name
      });
    });
    return res;
  }.property('all_communicators'),
  reorder_units: function(unit_ids) {
  },
  actions: {
    add_unit: function() {
      var name = this.get('new_unit_name');
      var _this = this;
      this.set('new_unit_name', null);
      if(name) {
        var unit = this.store.createRecord('unit', {name: name, organization_id: this.get('model.id')});
        unit.save().then(function() {
          _this.refresh_units();
        }, function() {
          modal.error(i18n.t('room_not_created', "There was an unexpected error creating the new room"));
        });
      }
    },
    delete_unit: function(unit) {
      var _this = this;
      modal.open('confirm-delete-unit', {unit: unit}).then(function(res) {
        if(res && res.deleted) {
          _this.refresh_units();
        }
      });
    },
    edit_unit: function(unit) {
      var _this = this;
      modal.open('edit-unit', {unit: unit}).then(function(res) {
        if(res && res.updated) {
          _this.refresh_units();
        }
      });
    },
    add_users: function(unit) {
      unit.set('adding_users', !unit.get('adding_users'));
    },
    add_unit_user: function(unit, user_type) {
      var action = 'add_' + user_type;
      var user_name = null;
      if(user_type.match('communicator')) {
        user_name = unit.get('communicator_user_name');
      } else {
        user_name = unit.get('supervisor_user_name');
      }
      if(!user_name) { return; }
      action = action + "-" + user_name;
      unit.set('management_action', action);
      unit.save().then(function() {
        unit.set('communicator_user_name', null);
        unit.set('supervisor_user_name', null);
      }, function() {
        modal.error(i18n.t('error_adding_user', "There was an unexpected error while trying to add the user"));
      });
    },
    delete_unit_user: function(unit, user_type, user_id) {
      var action = 'remove_' + user_type + '-' + user_id;
      unit.set('management_action', action);
      unit.save().then(function() {
      }, function() {
        modal.error(i18n.t('error_adding_user', "There was an unexpected error while trying to remove the user"));
      });
    },
    move_up: function(unit) {
    },
    move_down: function(unit) {
    }
  }
});
<commit_msg>list users in alphabetical order when adding to rooms<commit_after>import Ember from 'ember';
import i18n from '../../utils/i18n';
import Utils from '../../utils/misc';
import persistence from '../../utils/persistence';
import modal from '../../utils/modal';

export default Ember.Controller.extend({
  refresh_units: function() {
    var _this = this;
    this.set('units', {loading: true});
    Utils.all_pages('unit', {organization_id: this.get('model.id')}, function(list) {
      _this.set('units', list);
    }).then(function(data) {
      _this.set('units', data);
    }, function() {
      _this.set('units', {error: true});
    });
  },
  load_users: function() {
    var _this = this;
    Utils.all_pages('/api/v1/organizations/' + this.get('model.id') + '/users', {result_type: 'user', type: 'GET', data: {}}).then(function(data) {
      _this.set('all_communicators', data.filter(function(u) { return !u.org_pending; }));
    }, function(err) {
      _this.set('user_error', true);
    });
    Utils.all_pages('/api/v1/organizations/' + this.get('model.id') + '/supervisors', {result_type: 'user', type: 'GET', data: {}}).then(function(data) {
      _this.set('all_supervisors', data);
    }, function(err) {
      _this.set('user_error', true);
    });
  },
  supervisor_options: function() {
    var res = [{
      id: null,
      name: i18n.t('select_user', "[ Select User ]")
    }];
    (this.get('all_supervisors') || []).forEach(function(sup) {
      res.push({
        id: sup.id,
        name: sup.user_name
      });
    });
    return res;
  }.property('all_supervisors'),
  communicator_options: function() {
    var res = [{
      id: null,
      name: i18n.t('select_user', "[ Select User ]")
    }];
    (this.get('all_communicators') || []).forEach(function(sup) {
      res.push({
        id: sup.id,
        name: sup.user_name
      });
    });
    return res;
  }.property('all_communicators'),
  reorder_units: function(unit_ids) {
  },
  actions: {
    add_unit: function() {
      var name = this.get('new_unit_name');
      var _this = this;
      this.set('new_unit_name', null);
      if(name) {
        var unit = this.store.createRecord('unit', {name: name, organization_id: this.get('model.id')});
        unit.save().then(function() {
          _this.refresh_units();
        }, function() {
          modal.error(i18n.t('room_not_created', "There was an unexpected error creating the new room"));
        });
      }
    },
    delete_unit: function(unit) {
      var _this = this;
      modal.open('confirm-delete-unit', {unit: unit}).then(function(res) {
        if(res && res.deleted) {
          _this.refresh_units();
        }
      });
    },
    edit_unit: function(unit) {
      var _this = this;
      modal.open('edit-unit', {unit: unit}).then(function(res) {
        if(res && res.updated) {
          _this.refresh_units();
        }
      });
    },
    add_users: function(unit) {
      unit.set('adding_users', !unit.get('adding_users'));
    },
    add_unit_user: function(unit, user_type) {
      var action = 'add_' + user_type;
      var user_name = null;
      if(user_type.match('communicator')) {
        user_name = unit.get('communicator_user_name');
      } else {
        user_name = unit.get('supervisor_user_name');
      }
      if(!user_name) { return; }
      action = action + "-" + user_name;
      unit.set('management_action', action);
      unit.save().then(function() {
        unit.set('communicator_user_name', null);
        unit.set('supervisor_user_name', null);
      }, function() {
        modal.error(i18n.t('error_adding_user', "There was an unexpected error while trying to add the user"));
      });
    },
    delete_unit_user: function(unit, user_type, user_id) {
      var action = 'remove_' + user_type + '-' + user_id;
      unit.set('management_action', action);
      unit.save().then(function() {
      }, function() {
        modal.error(i18n.t('error_adding_user', "There was an unexpected error while trying to remove the user"));
      });
    },
    move_up: function(unit) {
    },
    move_down: function(unit) {
    }
  }
});
<|endoftext|>


<commit_before>export function initialize (appInstance) {
  let emberAmbitiousForms = appInstance.lookup('service:ember-ambitious-forms')
  emberAmbitiousForms.configure((config) => {
    if (appInstance.hasRegistration('service:i18n')) {
      config.fieldPlugins.push('i18n')
    }
    if (appInstance.hasRegistration('service:validations')) {
      config.fieldPlugins.push('validations')
    }
    if ((typeof RESTless != 'undefined') && (RESTless instanceof Ember.Namespace)) {
      config.fieldPlugins.push('restless')
    }
  })
}

export default {
  name: 'ember-ambitious-forms',
  initialize: initialize
}
<commit_msg>Load config from ENV<commit_after>import Ember from 'ember'
import config from '../config/environment'

export function initialize (appInstance) {
  let emberAmbitiousForms = appInstance.lookup('service:ember-ambitious-forms')
  if (config['ember-ambitious-forms']) {
    emberAmbitiousForms.configure(config['ember-ambitious-forms'])
  }

  if (!Ember.get(config, 'ember-ambitious-forms.fieldPlugins')) {
    // Detect plugins if they are not defined
    emberAmbitiousForms.configure((eaf) => {
      if (appInstance.hasRegistration('service:i18n')) {
        eaf.fieldPlugins.push('i18n')
      }
      if (appInstance.hasRegistration('service:validations')) {
        eaf.fieldPlugins.push('validations')
      }
      if ((typeof RESTless != 'undefined') && (RESTless instanceof Ember.Namespace)) {
        eaf.fieldPlugins.push('restless')
      }
    })
  }
}

export default {
  name: 'ember-ambitious-forms',
  initialize: initialize
}
<|endoftext|>


<commit_before>var $ = require('jquery');
var createVis = require('../../../../src/api/create-vis');
var scenarios = require('./scenarios');

describe('create-vis-new:', function () {
  beforeEach(function () {
    this.container = $('
').css('height', '200px');
    this.containerId = this.container[0].id;
    $('body').append(this.container);
  });

  afterEach(function () {
    this.container.remove();
  });

  describe('Default Options', function () {
    it('should get the map center from the visJson', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('center')).toEqual(visJson.center);
    });
    it('should get the title from the visJson', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('title')).toEqual(visJson.title);
    });
    it('should get the description from the visJson', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('description')).toEqual(visJson.description);
    });
    it('should initialize the right protocol (https:false)', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('https')).toEqual(false);
    });
    it('should not have interactive features by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('interactiveFeatures')).toEqual(false);
    });
    it('should display the "loader" overlay by default [loaderControl, tiles_loader]', function () {
      // loaderControl and tiles_loader appear to do the same.
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.overlaysCollection.findWhere({ type: 'loader' })).toBeDefined();
    });
    it('should display the "logo" by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.overlaysCollection.findWhere({ type: 'logo' })).toBeDefined();
    });
    it('should not display empty infowindow fields by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('showEmptyInfowindowFields')).toEqual(false);
    });
    it('should have legends', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.settings.get('showLegends')).toEqual(true);
    });
    it('should show layer selector', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.settings.get('showLayerSelector')).toEqual(true);
      expect(visModel.settings.get('layerSelectorEnabled')).toEqual(true);
    });
    it('should allow scrollwheel by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('scrollwheel')).toEqual(true);
    });
    it('should have "infowindow" enabled by default', function () {
      pending('It seems that this option is no longer being used');
    });
    it('should have "tooltip" by default', function () {
      pending('It seems that this option  is no longer being used');
    });
  });

  describe('VisModel.map', function () {
    it('should have the right title', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('title')).toEqual(visJson.title);
    });
    it('should have the right description', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('description')).toEqual(visJson.description);
    });
    it('should have the right bounds', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('view_bounds_sw')).toEqual(visJson.bounds[0]);
      expect(visModel.map.get('view_bounds_ne')).toEqual(visJson.bounds[1]);
    });
    it('should have the right zoom', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('zoom')).toEqual(visJson.zoom);
    });
    it('should have the right scrollwheel', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('scrollwheel')).toEqual(visJson.options.scrollwheel);
    });
    it('should have the right drag', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('drag')).toEqual(true);
    });
    it('should have the right provider', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('provider')).toEqual('leaflet');
    });
    it('should have the right feature interactivity', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('isFeatureInteractivityEnabled')).toEqual(false);
    });
    it('should have the right render mode', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('renderMode')).toEqual(visJson.vector ? 'vector' : 'raster');
    });
  });

  describe('VisModel._windshaftMap', function () {
    /**
      client: windshaftClient,
      modelUpdater: modelUpdater,
      windshaftSettings: windshaftSettings,
      dataviewsCollection: this._dataviewsCollection,
      layersCollection: this._layersCollection,
      analysisCollection: this._analysisCollection
     */
    it('should not have the api key', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap.get('apiKey')).toEqual(undefined);
    });
    it('should not have auth token', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap.get('authToken')).toEqual(undefined);
    });
    it('should have the right statTag', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap.get('statTag')).toEqual(visJson.datasource.stat_tag);
    });
  });

  xdescribe('VisModel.overlays', function () {
    it('should set the right map center', function () {

    });
  });

  xdescribe('VisModel.dataviews', function () {
    it('should set the right map center', function () {
    });
  });

  xdescribe('VisModel.analysis', function () {
    it('should set the right map center', function () {
    });
  });
});
<commit_msg>Test the created windshaftMap<commit_after>var $ = require('jquery');
var createVis = require('../../../../src/api/create-vis');
var scenarios = require('./scenarios');

describe('create-vis-new:', function () {
  beforeEach(function () {
    this.container = $('
').css('height', '200px');
    this.containerId = this.container[0].id;
    $('body').append(this.container);
  });

  afterEach(function () {
    this.container.remove();
  });

  describe('Default Options', function () {
    it('should get the map center from the visJson', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('center')).toEqual(visJson.center);
    });
    it('should get the title from the visJson', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('title')).toEqual(visJson.title);
    });
    it('should get the description from the visJson', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('description')).toEqual(visJson.description);
    });
    it('should initialize the right protocol (https:false)', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('https')).toEqual(false);
    });
    it('should not have interactive features by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('interactiveFeatures')).toEqual(false);
    });
    it('should display the "loader" overlay by default [loaderControl, tiles_loader]', function () {
      // loaderControl and tiles_loader appear to do the same.
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.overlaysCollection.findWhere({ type: 'loader' })).toBeDefined();
    });
    it('should display the "logo" by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.overlaysCollection.findWhere({ type: 'logo' })).toBeDefined();
    });
    it('should not display empty infowindow fields by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.get('showEmptyInfowindowFields')).toEqual(false);
    });
    it('should have legends', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.settings.get('showLegends')).toEqual(true);
    });
    it('should show layer selector', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.settings.get('showLayerSelector')).toEqual(true);
      expect(visModel.settings.get('layerSelectorEnabled')).toEqual(true);
    });
    it('should allow scrollwheel by default', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('scrollwheel')).toEqual(true);
    });
    it('should have "infowindow" enabled by default', function () {
      pending('It seems that this option is no longer being used');
    });
    it('should have "tooltip" by default', function () {
      pending('It seems that this option  is no longer being used');
    });
  });

  describe('VisModel.map', function () {
    it('should have the right title', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('title')).toEqual(visJson.title);
    });
    it('should have the right description', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('description')).toEqual(visJson.description);
    });
    it('should have the right bounds', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('view_bounds_sw')).toEqual(visJson.bounds[0]);
      expect(visModel.map.get('view_bounds_ne')).toEqual(visJson.bounds[1]);
    });
    it('should have the right zoom', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('zoom')).toEqual(visJson.zoom);
    });
    it('should have the right scrollwheel', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('scrollwheel')).toEqual(visJson.options.scrollwheel);
    });
    it('should have the right drag', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('drag')).toEqual(true);
    });
    it('should have the right provider', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('provider')).toEqual('leaflet');
    });
    it('should have the right feature interactivity', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('isFeatureInteractivityEnabled')).toEqual(false);
    });
    it('should have the right render mode', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel.map.get('renderMode')).toEqual(visJson.vector ? 'vector' : 'raster');
    });
  });

  describe('VisModel._windshaftMap', function () {
    it('should have the right statTag', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap.get('statTag')).toEqual(visJson.datasource.stat_tag);
    });
    it('should have the _analysisCollection linked', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap._analysisCollection).toEqual(visModel._analysisCollection);
    });
    it('should have the analysisCollection linked', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap._analysisCollection).toEqual(visModel._analysisCollection);
    });
    it('should have the dataviewsCollection linked', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap._dataviewsCollection).toEqual(visModel._dataviewsCollection);
    });
    it('should have the layersCollection linked', function () {
      var visJson = scenarios.load(0);
      var visModel = createVis(this.containerId, visJson);
      expect(visModel._windshaftMap._layersCollection).toEqual(visModel._layersCollection);
    });
    describe('.windshaftSettings', function () {
      it('should have the right urlTemplate', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._windshaftSettings.urlTemplate).toEqual(visJson.datasource.maps_api_template);
      });
      it('should have the right userName', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._windshaftSettings.userName).toEqual(visJson.datasource.user_name);
      });
      it('should have the right statTag', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._windshaftSettings.statTag).toEqual(visJson.datasource.stat_tag);
      });
      it('should not have apikey', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._windshaftSettings.apikey).toBeUndefined();
      });
      it('should not have authToken', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._windshaftSettings.authToken).toBeUndefined();
      });
    });
    describe('.client', function () {
      it('should have the right url', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        var expectedClientUrl = visJson.datasource.maps_api_template.replace(/{user}/, visJson.datasource.user_name);
        expect(visModel._windshaftMap.client.url).toEqual(expectedClientUrl);
      });
      it('should have the right get endpoint', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        var expectedGetEndPoint = 'api/v1/map/named/' + visJson.datasource.template_name + '/jsonp';
        expect(visModel._windshaftMap.client.endpoints.get).toEqual(expectedGetEndPoint);
      });
      it('should have the right post endpoint', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        var expectedGetEndPoint = 'api/v1/map/named/' + visJson.datasource.template_name;
        expect(visModel._windshaftMap.client.endpoints.post).toEqual(expectedGetEndPoint);
      });
    });
    describe('.modelUpdater', function () {
      it('should have the visModel linked', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._modelUpdater._visModel).toEqual(visModel);
      });
      it('should have the mapModel linked', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._modelUpdater._mapModel).toEqual(visModel.map);
      });
      it('should have the layerGroupModel linked', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._modelUpdater._layerGroupModel).toEqual(visModel.layerGroupModel);
      });
      it('should have the dataviewsCollection linked', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._modelUpdater._dataviewsCollection).toEqual(visModel._dataviewsCollection);
      });
      it('should have the layersCollection linked', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._modelUpdater._layersCollection).toEqual(visModel._layersCollection);
      });
      it('should have the analysisCollection linked', function () {
        var visJson = scenarios.load(0);
        var visModel = createVis(this.containerId, visJson);
        expect(visModel._windshaftMap._modelUpdater._analysisCollection).toEqual(visModel._analysisCollection);
      });
    });
  });

  xdescribe('VisModel.overlays', function () {
    it('should set the right map center', function () {});
  });

  xdescribe('VisModel.dataviews', function () {
    it('should set the right map center', function () {});
  });

  xdescribe('VisModel.analysis', function () {
    it('should set the right map center', function () {});
  });
});
<|endoftext|>


<commit_before>/*

`<AccountHeader>`
=================

>   For more information on the contents of this file, please contact:
>
>   - kibigo! [@kibi@glitch.social]

Original file by @gargron@mastodon.social et al as part of
tootsuite/mastodon. We've expanded it in order to handle user bio
frontmatter.

The `<AccountHeader>` component provides the header for account
timelines. It is a fairly simple component which mostly just consists
of a `render()` method.

__Props:__

 -  __`account` (`ImmutablePropTypes.map`) :__
    The account to render a header for.

 -  __`me` (`PropTypes.number.isRequired`) :__
    The id of the currently-signed-in account.

 -  __`onFollow` (`PropTypes.func.isRequired`) :__
    The function to call when the user clicks the "follow" button.

 -  __`intl` (`PropTypes.object.isRequired`) :__
    Our internationalization object, inserted by `@injectIntl`.

*/

//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

/*

Imports:
--------

*/

//  Package imports  //
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';

//  Mastodon imports  //
import emojify from '../../../mastodon/emoji';
import IconButton from '../../../mastodon/components/icon_button';
import Avatar from '../../../mastodon/components/avatar';

//  Our imports  //
import { processBio } from '../../util/bio_metadata';

//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

/*

Inital setup:
-------------

The `messages` constant is used to define any messages that we need
from inside props. In our case, these are the `unfollow`, `follow`, and
`requested` messages used in the `title` of our buttons.

*/

const messages = defineMessages({
  unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
  follow: { id: 'account.follow', defaultMessage: 'Follow' },
  requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
});

//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

/*

Implementation:
---------------

*/

@injectIntl
export default class AccountHeader extends ImmutablePureComponent {

  static propTypes = {
    account  : ImmutablePropTypes.map,
    me       : PropTypes.string.isRequired,
    onFollow : PropTypes.func.isRequired,
    intl     : PropTypes.object.isRequired,
  };

/*

###  `render()`

The `render()` function is used to render our component.

*/

  render () {
    const { account, me, intl } = this.props;

/*

If no `account` is provided, then we can't render a header. Otherwise,
we get the `displayName` for the account, if available. If it's blank,
then we set the `displayName` to just be the `username` of the account.

*/

    if (!account) {
      return null;
    }

    let displayName = account.get('display_name_html');
    let info        = '';
    let actionBtn   = '';
    let following   = false;

    if (displayName.length === 0) {
      displayName = account.get('username');
    }

/*

Next, we handle the account relationships. If the account follows the
user, then we add an `info` message. If the user has requested a
follow, then we disable the `actionBtn` and display an hourglass.
Otherwise, if the account isn't blocked, we set the `actionBtn` to the
appropriate icon.

*/

    if (me !== account.get('id')) {
      if (account.getIn(['relationship', 'followed_by'])) {
        info = (

            <FormattedMessage id='account.follows_you' defaultMessage='Follows you' />

        );
      }
      if (account.getIn(['relationship', 'requested'])) {
        actionBtn = (

            <IconButton size={26} disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />

        );
      } else if (!account.getIn(['relationship', 'blocking'])) {
        following = account.getIn(['relationship', 'following']);
        actionBtn = (

            <IconButton
              size={26}
              icon={following ? 'user-times' : 'user-plus'}
              active={following}
              title={intl.formatMessage(following ? messages.unfollow : messages.follow)}
              onClick={this.props.onFollow}
            />

        );
      }
    }

/*
 we extract the `text` and
`metadata` from our account's `note` using `processBio()`.

*/

    const { text, metadata } = processBio(account.get('note'));

/*

Here, we render our component using all the things we've defined above.

*/

    return (

        <div
          className='account__header'
          style={{ backgroundImage: `url(${account.get('header')})` }}
        >

                <Avatar account={account} size={90} />

              @{account.get('acct')}
              {account.get('locked') ?  : null}

            {info}
            {actionBtn}

        {metadata.length && (

              {(() => {
                let data = [];
                for (let i = 0; i < metadata.length; i++) {
                  data.push(

                  );
                }
                return data;
              })()}

        ) || null}

    );
  }

}
<commit_msg>Fixed header emojification<commit_after>/*

`<AccountHeader>`
=================

>   For more information on the contents of this file, please contact:
>
>   - kibigo! [@kibi@glitch.social]

Original file by @gargron@mastodon.social et al as part of
tootsuite/mastodon. We've expanded it in order to handle user bio
frontmatter.

The `<AccountHeader>` component provides the header for account
timelines. It is a fairly simple component which mostly just consists
of a `render()` method.

__Props:__

 -  __`account` (`ImmutablePropTypes.map`) :__
    The account to render a header for.

 -  __`me` (`PropTypes.number.isRequired`) :__
    The id of the currently-signed-in account.

 -  __`onFollow` (`PropTypes.func.isRequired`) :__
    The function to call when the user clicks the "follow" button.

 -  __`intl` (`PropTypes.object.isRequired`) :__
    Our internationalization object, inserted by `@injectIntl`.

*/

//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

/*

Imports:
--------

*/

//  Package imports  //
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';

//  Mastodon imports  //
import emojify from 'mastodon/features/emoji/emoji';
import IconButton from '../../../mastodon/components/icon_button';
import Avatar from '../../../mastodon/components/avatar';

//  Our imports  //
import { processBio } from '../../util/bio_metadata';

//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

/*

Inital setup:
-------------

The `messages` constant is used to define any messages that we need
from inside props. In our case, these are the `unfollow`, `follow`, and
`requested` messages used in the `title` of our buttons.

*/

const messages = defineMessages({
  unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
  follow: { id: 'account.follow', defaultMessage: 'Follow' },
  requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
});

//  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

/*

Implementation:
---------------

*/

@injectIntl
export default class AccountHeader extends ImmutablePureComponent {

  static propTypes = {
    account  : ImmutablePropTypes.map,
    me       : PropTypes.string.isRequired,
    onFollow : PropTypes.func.isRequired,
    intl     : PropTypes.object.isRequired,
  };

/*

###  `render()`

The `render()` function is used to render our component.

*/

  render () {
    const { account, me, intl } = this.props;

/*

If no `account` is provided, then we can't render a header. Otherwise,
we get the `displayName` for the account, if available. If it's blank,
then we set the `displayName` to just be the `username` of the account.

*/

    if (!account) {
      return null;
    }

    let displayName = account.get('display_name_html');
    let info        = '';
    let actionBtn   = '';
    let following   = false;

    if (displayName.length === 0) {
      displayName = account.get('username');
    }

/*

Next, we handle the account relationships. If the account follows the
user, then we add an `info` message. If the user has requested a
follow, then we disable the `actionBtn` and display an hourglass.
Otherwise, if the account isn't blocked, we set the `actionBtn` to the
appropriate icon.

*/

    if (me !== account.get('id')) {
      if (account.getIn(['relationship', 'followed_by'])) {
        info = (

            <FormattedMessage id='account.follows_you' defaultMessage='Follows you' />

        );
      }
      if (account.getIn(['relationship', 'requested'])) {
        actionBtn = (

            <IconButton size={26} disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />

        );
      } else if (!account.getIn(['relationship', 'blocking'])) {
        following = account.getIn(['relationship', 'following']);
        actionBtn = (

            <IconButton
              size={26}
              icon={following ? 'user-times' : 'user-plus'}
              active={following}
              title={intl.formatMessage(following ? messages.unfollow : messages.follow)}
              onClick={this.props.onFollow}
            />

        );
      }
    }

/*
 we extract the `text` and
`metadata` from our account's `note` using `processBio()`.

*/

    const { text, metadata } = processBio(account.get('note'));

/*

Here, we render our component using all the things we've defined above.

*/

    return (

        <div
          className='account__header'
          style={{ backgroundImage: `url(${account.get('header')})` }}
        >

                <Avatar account={account} size={90} />

              @{account.get('acct')}
              {account.get('locked') ?  : null}

            {info}
            {actionBtn}

        {metadata.length && (

              {(() => {
                let data = [];
                for (let i = 0; i < metadata.length; i++) {
                  data.push(

                  );
                }
                return data;
              })()}

        ) || null}

    );
  }

}
<|endoftext|>


<commit_before>define([
	'jquery',
	'underscore',
	'backbone',
	'template!view/page2',
	'style!view/page2',
	"widget-rangeinput"
], function ($, _, Backbone, template) {
	return Backbone.View.extend({

		el: 'section#page2',

		render: function (id) {
			var self = this;

			require(['template!../app/template/' + id], function (example) {
				var title = $.trim(id).replace(/css-|cs-/gi, '').replace('cs-', '').replace(/-/gi, ' ');
				self.$el.html(
					template({
						pageTitle: title,
						exampleHtml: example()
					})
				);

				// 이미지 썸네일 holder.js
				if (id.match(/.*carousel|.*images|.*thumbnails|.*media-object/gi)) {
					require(['../app/lib/holder'], function () {
						Holder.run();
					});
				}

				// 플러그인
				// 모달
				// 드롭다운

				// 스크롤스파이
				$('[data-spy="scroll"]').each(function () {
					var $spy = $(this);
					$spy.scrollspy($spy.data())
				});

				// 탭
				// 툴팁
				// 팝오버
				// 경고창
				// 버튼
				// 콜랩스
				// 캐로셀
				// 범위 입력상자
				if (id.match(/.*range-input/gi)) {
					require(['widget-rangeinput'], function () {
						$(".widget-range").rangeinput({
							showInput: true
						});
					});
				}
				// 싸인
				if (id.match(/.*sign/gi)) {
					require(['widget-sign'], function () {
						$("#signature").length && $("#signature").sign();
					});
				}
				// 스피너
				if (id.match(/.*spinner/gi)) {
					require(['widget-spinner'], function() {
						$("[data-plugin='spinner']").on("click", function (e) {
							e.preventDefault();
							var self = this;
							var target = $(this).data("spinnerTarget");
							window.setTimeout(function () {
								$(target).spinner("hide");
							}, 3000);
						});
					});
				}
				// 모션캡챠
				if (id.match(/.*motion-captcha/gi)) {
					require(['widget-motioncaptcha'], function () {
						$("#motion-captcha button").on("click", function (e) {
							$("#mc-canvas").remove();
							$("<canvas/>", {
								"id": "mc-canvas",
								"class": "mc-canvas"
							}).appendTo($("#motion-captcha-example")).motioncaptcha({
									errorMsg: '다시 시도해주세요.',
									successMsg: '성공',
									onSuccess: function () {
										console.log("성공");
									}
								}).on('start.cs.motionCaptcha',function (e) {
									console.log('start.cs.motionCaptcha', e);
								}).on('move.cs.motionCaptcha',function (e) {
									console.log('move.cs.motionCaptcha', e);
								}).on('end.cs.motionCaptcha',function (e) {
									console.log('end.cs.motionCaptcha', e);
								}).on('success.cs.motionCaptcha',function (e) {
									console.log('success 이벤트 감지', e);
								}).on('fail.cs.motionCaptcha', function (e) {
									console.log('fail 이벤트 감지', e);
								});
						});
						$("#motion-captcha button").trigger("click");
					});
				}
				// 날짜 입력상자
				if (id.match(/.*datepicker/gi)) {
					require(['widget-datepicker'], function () {
						$("#date-picker1, #date-picker2").datetimepicker({
							firstDisable: true,
							changeDisplay: true
						});
					});
				}
				// 자동완성
				if (id.match(/.*typeahead/gi)) {
					require(['widget-typeahead'], function () {
						$('.example-countries .typeahead').typeahead({
							name: 'countries',
							prefetch: 'data/typeahead-countries.json',
							limit: 10
						});
					});
				}

				// 피처드
				// 스크롤뷰
				if (id.match(/.*scrollview/gi)) {
					require(['widget-scrollview'], function (ScrollView) {
						$("#scrollView1,#scrollView2").featuredScrollView();
					});
				}
				// 리스트뷰
				if (id.match(/.*listview/gi)) {
					require(['widget-listview'], function () {
						$(".js-addItem").on("click", function (e) {
							getItem();
						});

						var $el = $('#listView');
						var isLoading = false;
						var html;

						$el.on("scrollEnd.cs.liveView", function () {
							console.log("scrollEndEvent");
						});

						// ID가 listView이 엘리먼트에 ListView 피쳐드 적용
						$el.length && $el.featuredListView({
							$scroller: $el.closest(".list-view-wrapper"),
							optimization: true,
							scrollEndAction: function () {
								console.log("scrollEndAction");
							}
						});

						// AJAX로 데이터를 가져오는 함수
						function getItem() {
							if (isLoading) {
								return false;
							}

							isLoading = true;

							var request = $.ajax({
								url: "data/sample-list.json",
								type: "GET",
								dataType: "json"
							});

							request.done(function (json) {
								html = '
';
								if (typeof json === "object" && json.items.length > 0) {
									$(json.items).each(function (i) {
										html += '
';
										html += this.title;
										html += '
'
										html += '   ' + this.published + '';
										html += '   ';
										html += '
';
										html += '
';
									});
									html += "
";
									$el.featuredListView("addItem", html);
								}
								html = "";
								isLoading = false;
							});

							request.fail(function (jqXHR, textStatus) {
								console.log("Request failed: " + textStatus);
								isLoading = false;
							});

						}
					});
				}
				// 미디어
				// 에디터
				// 차트
				if (id.match(/.*chart/gi)) {
					require(['widget-chart']);
				}
				// 데이터테이블
			});
			return this;
		},

		events: {
			'click button.next': 'nextPage'
		},

		nextPage: function () {
			location.href = '#page2';
		}
	});
});
<commit_msg>UI 테스트 Widget editor, media 적용<commit_after>define([
	'jquery',
	'underscore',
	'backbone',
	'template!view/page2',
	'style!view/page2',
	"widget-rangeinput"
], function ($, _, Backbone, template) {
	return Backbone.View.extend({

		el: 'section#page2',

		render: function (id) {
			var self = this;

			require(['template!../app/template/' + id], function (example) {
				var title = $.trim(id).replace(/css-|cs-/, '').replace('cs-', '').replace(/-/, ' ');
				self.$el.html(
					template({
						pageTitle: title,
						exampleHtml: example()
					})
				);

				// 이미지 썸네일 holder.js
				if (id.match(/.*carousel|.*images|.*thumbnails|.*media-object/)) {
					require(['../app/lib/holder'], function () {
						Holder.run();
					});
				}

				// 플러그인
				// 모달
				// 드롭다운

				// 스크롤스파이
				$('[data-spy="scroll"]').each(function () {
					var $spy = $(this);
					$spy.scrollspy($spy.data())
				});

				// 탭
				// 툴팁
				// 팝오버
				// 경고창
				// 버튼
				// 콜랩스
				// 캐로셀
				// 범위 입력상자
				if (id.match(/.*range-input/)) {
					require(['widget-rangeinput'], function () {
						$(".widget-range").rangeinput({
							showInput: true
						});
					});
				}
				// 싸인
				if (id.match(/.*sign/)) {
					require(['widget-sign'], function () {
						$("#signature").length && $("#signature").sign();
					});
				}
				// 스피너
				if (id.match(/.*spinner/)) {
					require(['widget-spinner'], function() {
						$("[data-plugin='spinner']").on("click", function (e) {
							e.preventDefault();
							var self = this;
							var target = $(this).data("spinnerTarget");
							window.setTimeout(function () {
								$(target).spinner("hide");
							}, 3000);
						});
					});
				}
				// 모션캡챠
				if (id.match(/.*motion-captcha/)) {
					require(['widget-motioncaptcha'], function () {
						$("#motion-captcha button").on("click", function (e) {
							$("#mc-canvas").remove();
							$("<canvas/>", {
								"id": "mc-canvas",
								"class": "mc-canvas"
							}).appendTo($("#motion-captcha-example")).motioncaptcha({
									errorMsg: '다시 시도해주세요.',
									successMsg: '성공',
									onSuccess: function () {
										console.log("성공");
									}
								}).on('start.cs.motionCaptcha',function (e) {
									console.log('start.cs.motionCaptcha', e);
								}).on('move.cs.motionCaptcha',function (e) {
									console.log('move.cs.motionCaptcha', e);
								}).on('end.cs.motionCaptcha',function (e) {
									console.log('end.cs.motionCaptcha', e);
								}).on('success.cs.motionCaptcha',function (e) {
									console.log('success 이벤트 감지', e);
								}).on('fail.cs.motionCaptcha', function (e) {
									console.log('fail 이벤트 감지', e);
								});
						});
						$("#motion-captcha button").trigger("click");
					});
				}
				// 날짜 입력상자
				if (id.match(/.*datepicker/)) {
					require(['widget-datepicker'], function () {
						$("#date-picker1, #date-picker2").datetimepicker({
							firstDisable: true,
							changeDisplay: true
						});
					});
				}
				// 자동완성
				if (id.match(/.*typeahead/)) {
					require(['widget-typeahead'], function () {
						$('.example-countries .typeahead').typeahead({
							name: 'countries',
							prefetch: 'data/typeahead-countries.json',
							limit: 10
						});
					});
				}

				// 피처드
				// 스크롤뷰
				if (id.match(/.*scrollview/)) {
					require(['widget-scrollview'], function (ScrollView) {
						$("#scrollView1,#scrollView2").featuredScrollView();
					});
				}
				// 리스트뷰
				if (id.match(/.*listview/)) {
					require(['widget-listview'], function () {
						$(".js-addItem").on("click", function (e) {
							getItem();
						});

						var $el = $('#listView');
						var isLoading = false;
						var html;

						$el.on("scrollEnd.cs.liveView", function () {
							console.log("scrollEndEvent");
						});

						// ID가 listView이 엘리먼트에 ListView 피쳐드 적용
						$el.length && $el.featuredListView({
							$scroller: $el.closest(".list-view-wrapper"),
							optimization: true,
							scrollEndAction: function () {
								console.log("scrollEndAction");
							}
						});

						// AJAX로 데이터를 가져오는 함수
						function getItem() {
							if (isLoading) {
								return false;
							}

							isLoading = true;

							var request = $.ajax({
								url: "data/sample-list.json",
								type: "GET",
								dataType: "json"
							});

							request.done(function (json) {
								html = '
';
								if (typeof json === "object" && json.items.length > 0) {
									$(json.items).each(function (i) {
										html += '
';
										html += this.title;
										html += '
'
										html += '   ' + this.published + '';
										html += '   ';
										html += '
';
										html += '
';
									});
									html += "
";
									$el.featuredListView("addItem", html);
								}
								html = "";
								isLoading = false;
							});

							request.fail(function (jqXHR, textStatus) {
								console.log("Request failed: " + textStatus);
								isLoading = false;
							});

						}
					});
				}
				// 미디어
				if (id.match(/featured-media/)) {
					require(['widget-media'], function () {
					});
				}
				// 에디터
				if (id.match(/.*editor/)) {
					require(['widget-editor'], function () {
						$("#editorExample").featuredEditor();
					})
				}
				// 차트
				if (id.match(/.*chart/)) {
					require(['widget-chart']);
				}
				// 데이터테이블
			});
			return this;
		},

		events: {
			'click button.next': 'nextPage'
		},

		nextPage: function () {
			location.href = '#page2';
		}
	});
});
<|endoftext|>


<commit_before>'use strict';

angular.module('ddsApp').controller('FoyerCaptureImmobilierModalCtrl', function($scope, $modalInstance, situation, SituationService) {
    $scope.situation = situation;

    var conjointLabels = {
        'mariage': 'conjoint',
        'pacs': 'partenaire PACS',
        'relation_libre': 'concubin',
    };

    $scope.debutPeriode = moment().startOf('month').subtract('years', 1).format('MMMM YYYY');
    $scope.finPeriode = moment().startOf('month').subtract('months', 1).format('MMMM YYYY');
    $scope.months = SituationService.getMonths();

    $scope.revenusLocatifs = {
        months: [
            {montant: 0},
            {montant: 0},
            {montant: 0}
        ],
        year: 0
    };

    $scope.revenusDuCapital = {
        months: [
            {montant: 0},
            {montant: 0},
            {montant: 0}
        ],
        year: 0
    };

    $scope.situation.hasImmobilier = false;
    $scope.situation.valeurLocativeImmoNonLoue = 0;
    $scope.situation.valeurLocativeTerrainNonLoue = 0;
    $scope.hasMobilier = false;
    $scope.situation.mobilierValueLivret = 0;
    $scope.situation.epargneSansRevenus = 0;

    $scope.conjointLabel = function() {
        return conjointLabels[$scope.situation.conjoint.relationType];
    };

    $scope.updateRevenusLocatifsYearAmount = function() {
        var montants = _.map($scope.revenusLocatifs.months, function(month) {
            return month.montant;
        });
        $scope.revenusLocatifs.year = Math.round(4 * _.reduce(montants, function(sum, num) {
            return sum + num;
        }));
    };

    $scope.submit = function(form) {
        $scope.situation.immobilierCaptured = true;
        $modalInstance.close();
    };
});
<commit_msg>fix bug initialisation situation.hasImmoblier<commit_after>'use strict';

angular.module('ddsApp').controller('FoyerCaptureImmobilierModalCtrl', function($scope, $modalInstance, situation, SituationService) {
    $scope.situation = situation;

    var conjointLabels = {
        'mariage': 'conjoint',
        'pacs': 'partenaire PACS',
        'relation_libre': 'concubin',
    };

    $scope.debutPeriode = moment().startOf('month').subtract('years', 1).format('MMMM YYYY');
    $scope.finPeriode = moment().startOf('month').subtract('months', 1).format('MMMM YYYY');
    $scope.months = SituationService.getMonths();

    $scope.revenusLocatifs = {
        months: [
            {montant: 0},
            {montant: 0},
            {montant: 0}
        ],
        year: 0
    };

    $scope.revenusDuCapital = {
        months: [
            {montant: 0},
            {montant: 0},
            {montant: 0}
        ],
        year: 0
    };

    $scope.situation.hasImmobilier = false;
    $scope.situation.valeurLocativeImmoNonLoue = 0;
    $scope.situation.valeurLocativeTerrainNonLoue = 0;
    $scope.situation.hasMobilier = false;
    $scope.situation.mobilierValueLivret = 0;
    $scope.situation.epargneSansRevenus = 0;

    $scope.conjointLabel = function() {
        return conjointLabels[$scope.situation.conjoint.relationType];
    };

    $scope.updateRevenusLocatifsYearAmount = function() {
        var montants = _.map($scope.revenusLocatifs.months, function(month) {
            return month.montant;
        });
        $scope.revenusLocatifs.year = Math.round(4 * _.reduce(montants, function(sum, num) {
            return sum + num;
        }));
    };

    $scope.submit = function(form) {
        $scope.situation.immobilierCaptured = true;
        $modalInstance.close();
    };
});
<|endoftext|>


<commit_before>(function cycleText($){
  $.fn.cycleText = function(selector, quotes, options){
    var self = this;
    if (typeof selector === "object"){
      options = quotes;
      quotes = selector;
    }
    if (typeof selector === "string"){
      selector = document.querySelector(selector);
    }

    // default settings
    var settings = {
      fadeInSpeed: 2000,
      displayDuration: 7000,
      fadeOutSpeed: 2000,
      delay: 0,
      element: "p"
    };
    // adopts user-defined settings
    if (typeof options === "object"){
      for (var option in options){
        settings[option] = options[option];
      }
    }

    // creates elements for the quote to reside in
    quotes.forEach(function(quote){
      var el = document.createElement(settings.element);
      el.innerHTML = quote;
      el.style.display = "none";
      self[0].appendChild(el);
    });

    // non-jQuery fadeIn
    function fadeIn(el, time) {
      el.style.display = "block";
      el.style.opacity = 0;
      var last = +new Date();
      var tick = function() {
        el.style.opacity = +el.style.opacity + (new Date() - last) / time;
        last = +new Date();
        if (+el.style.opacity < 1) {
          (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
        }
      };
      tick();
    }

    // non-jQuery fadeOut
    function fadeOut(el, time) {
      el.style.opacity = 1;
      var last = +new Date();
      var tick = function() {
        el.style.opacity = +el.style.opacity - (new Date() - last) / time;
        last = +new Date();
        if (+el.style.opacity > 0) {
          (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
        }
        if (el.style.opacity < 0){
          el.style.display = "none";
        }
      };
      tick();
    }

    // displays each quote in sequence
    var i = 0;
    function displayQuote(){
      var el = document.getElementsByTagName(settings.element).item(i);
      fadeIn(el, settings.fadeInSpeed);
      // sets duration of fadeout AND duration to display quote
      var fadeOutTimer = setTimeout(function(){
        fadeOut(el, settings.fadeOutSpeed);
        i++;
        // resets counter
        if (i === quotes.length){
          i = 0;
        }
      }, settings.displayDuration);
      // sets duration between initiating the display of a quote and the next initiation of displaying a quote
      setTimeout(function(){
        clearTimeout(fadeOutTimer);
        // recursively calls the displayQuote function
        displayQuote();
      }, settings.fadeOutSpeed + settings.displayDuration + settings.delay);
    }
    displayQuote();
  };
  return this;
}(window.jQuery));<commit_msg>adds eventlistener for inactive/active tab<commit_after>(function cycleText($){
  $.fn.cycleText = function(selector, quotes, options){
    var self = this;
    if (typeof selector === "object"){
      options = quotes;
      quotes = selector;
    }
    if (typeof selector === "string"){
      selector = document.querySelector(selector);
    }

    // browsers change setIntervals and requestAnimationFrames when the tab isn't active; this section will help us deal with that
    var hidden, visibilityChange;
    if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
      hidden = "hidden";
      visibilityChange = "visibilitychange";
    } else if (typeof document.mozHidden !== "undefined") {
      hidden = "mozHidden";
      visibilityChange = "mozvisibilitychange";
    } else if (typeof document.msHidden !== "undefined") {
      hidden = "msHidden";
      visibilityChange = "msvisibilitychange";
    } else if (typeof document.webkitHidden !== "undefined") {
      hidden = "webkitHidden";
      visibilityChange = "webkitvisibilitychange";
    }

    function handleVisibilityChange() {
      if (document[hidden]) {
        return;
      }
      else {
        displayQuote();
      }
    }

    document.addEventListener(visibilityChange, handleVisibilityChange, false);

    // default settings
    var settings = {
      fadeInSpeed: 2000,
      displayDuration: 7000,
      fadeOutSpeed: 2000,
      delay: 0,
      element: "p"
    };
    // adopts user-defined settings
    if (typeof options === "object"){
      for (var option in options){
        settings[option] = options[option];
      }
    }

    // creates elements for the quote to reside in
    quotes.forEach(function(quote, i){
      var el = document.createElement(settings.element);
      el.innerHTML = quote;
      el.style.display = "none";
      el.id = "cycletext" + i;
      self[0].appendChild(el);
    });

    // non-jQuery fadeIn
    function fadeIn(el, time) {
      el.style.display = "block";
      el.style.opacity = 0;
      var last = Date.now();
      var tick = function() {
        el.style.opacity = +el.style.opacity + (Date.now() - last) / time;
        last = Date.now();
        if (+el.style.opacity <= 1) {
          (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
        }
      };
      tick();
    }

    // non-jQuery fadeOut
    function fadeOut(el, time) {
      var last = Date.now();
      var tick = function() {
        el.style.opacity = +el.style.opacity - (Date.now() - last) / time;
        last = Date.now();
        if (+el.style.opacity > 0) {
          (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
        }
        if (el.style.opacity <= 0){
          el.style.display = "none";
        }
      };
      tick();
    }

    // displays each quote in sequence
    var i = 0;
    function displayQuote(){
      var el = document.getElementById("cycletext" + i);
      fadeIn(el, settings.fadeInSpeed);
      // sets duration of fadeout AND duration to display quote
      var fadeOutTimer = setTimeout(function(){
        fadeOut(el, settings.fadeOutSpeed);
        i++;
        // resets counter
        if (i === quotes.length){
          i = 0;
        }
      }, settings.displayDuration);
      // sets duration between initiating the display of a quote and the next initiation of displaying a quote
      var fadeInTimer = setTimeout(function(){
        clearTimeout(fadeOutTimer);
        // recursively calls the displayQuote function
        if (document[hidden]) {
          el.style.display = "none";
          return;
        }
        else {
          displayQuote();
        }
      }, settings.fadeOutSpeed + settings.displayDuration + settings.delay);
    }
    displayQuote();
  };
  return this;
}(window.jQuery));<|endoftext|>