<commit_before>angular.module('player')
	.controller('ScorecardController', ScorecardController);

function ScorecardController($scope, $stateParams, localStorage, FooseyService)
{
	// set up the player
	$scope.player = getPlayer($stateParams.player);

	// set up charts
	setUpCharts();

	// get the player information
	function getPlayer(name)
	{
		return {
			name: name,
			elo: getElo(name),
			avg: getAvg(name),
			percent: getPercent(name)
		}
	}

	// get the elo for this playe from local storage
	function getElo(name)
	{
		// load from local storage
    var elos = localStorage.getObject('elos');
    var index = _.indexOf(_.pluck(elos, 'name'), name);

		return elos[index].elo;
	}

	// get the average score for this player from local storage
	function getAvg(name)
	{
		var avgs = localStorage.getObject('avgs');
		var index = _.indexOf(_.pluck(avgs, 'name'), name);

		return avgs[index].avg;
	}

	// get the win % for this player from local storage
	function getPercent(name)
	{
    var percent = localStorage.getObject('percent');
    var index = _.indexOf(_.pluck(percent, 'name'), name);

		return percent[index].percent;
	}

	// set up the charts for the scorecard page
	function setUpCharts()
	{
		$scope.charts = [];
		$scope.subtitle = 'Data from All Time';

		FooseyService.charts($scope.player.name).then(function successCallback(response)
		{
			// Get chart data
			var chartData = response.data;

			// mock out filtering the charts by something
			chartData.charts = _.filter(chartData.charts, function(chart)
			{
				return true;
			})

			$scope.dates = _.pluck(chartData.charts, 'date');

			// Set up ELO Rating chart
			$scope.charts.push(getEloChartOptions(_.pluck(chartData.charts, 'elo')));

			// Set up Avg Score chart
			$scope.charts.push(getAvgChartOptions(_.pluck(chartData.charts, 'avg')));

			// Set up Win Percent chart
			$scope.charts.push(getPercentChartOptions(_.pluck(chartData.charts, 'percent')));
		});
	}

	// define options for the ELO Rating chart
	function getEloChartOptions(data)
	{
		return {
			title: 'ELO Rating',
			subtitle: $scope.subtitle,
			yAxis: 'ELO',
			class: 'elo',
			data: data,
			dates: $scope.dates
		};
	}

	// define options for the Average Score chart
	function getAvgChartOptions(data)
	{
		return {
			title: 'Average Score Per Game',
			subtitle: $scope.subtitle,
			yAxis: 'Score',
			class: 'avg',
			data: data,
			dates: $scope.dates
		};
	}

	// define options for the Win Percentage chart
	function getPercentChartOptions(data)
	{
		return {
			title: 'Percent Games Won',
			subtitle: $scope.subtitle,
			yAxis: 'Percent',
			class: 'percent',
			data: data,
			dates: $scope.dates
		};
	}
}<commit_msg>Comment out filtering for now because it broke the charts loading on the first go<commit_after>angular.module('player')
	.controller('ScorecardController', ScorecardController);

function ScorecardController($scope, $stateParams, localStorage, FooseyService)
{
	// set up the player
	$scope.player = getPlayer($stateParams.player);

	// set up charts
	setUpCharts();

	// get the player information
	function getPlayer(name)
	{
		return {
			name: name,
			elo: getElo(name),
			avg: getAvg(name),
			percent: getPercent(name)
		}
	}

	// get the elo for this playe from local storage
	function getElo(name)
	{
		// load from local storage
    var elos = localStorage.getObject('elos');
    var index = _.indexOf(_.pluck(elos, 'name'), name);

		return elos[index].elo;
	}

	// get the average score for this player from local storage
	function getAvg(name)
	{
		var avgs = localStorage.getObject('avgs');
		var index = _.indexOf(_.pluck(avgs, 'name'), name);

		return avgs[index].avg;
	}

	// get the win % for this player from local storage
	function getPercent(name)
	{
    var percent = localStorage.getObject('percent');
    var index = _.indexOf(_.pluck(percent, 'name'), name);

		return percent[index].percent;
	}

	// set up the charts for the scorecard page
	function setUpCharts()
	{
		$scope.charts = [];
		$scope.subtitle = 'Data from All Time';

		FooseyService.charts($scope.player.name).then(function successCallback(response)
		{
			// Get chart data
			var chartData = response.data;

			// mock out filtering the charts by something
			// chartData.charts = _.filter(chartData.charts, function(chart)
			// {
			// 	return true;
			// })

			$scope.dates = _.pluck(chartData.charts, 'date');

			// Set up ELO Rating chart
			$scope.charts.push(getEloChartOptions(_.pluck(chartData.charts, 'elo')));

			// Set up Avg Score chart
			$scope.charts.push(getAvgChartOptions(_.pluck(chartData.charts, 'avg')));

			// Set up Win Percent chart
			$scope.charts.push(getPercentChartOptions(_.pluck(chartData.charts, 'percent')));
		});
	}

	// define options for the ELO Rating chart
	function getEloChartOptions(data)
	{
		return {
			title: 'ELO Rating',
			subtitle: $scope.subtitle,
			yAxis: 'ELO',
			class: 'elo',
			data: data,
			dates: $scope.dates
		};
	}

	// define options for the Average Score chart
	function getAvgChartOptions(data)
	{
		return {
			title: 'Average Score Per Game',
			subtitle: $scope.subtitle,
			yAxis: 'Score',
			class: 'avg',
			data: data,
			dates: $scope.dates
		};
	}

	// define options for the Win Percentage chart
	function getPercentChartOptions(data)
	{
		return {
			title: 'Percent Games Won',
			subtitle: $scope.subtitle,
			yAxis: 'Percent',
			class: 'percent',
			data: data,
			dates: $scope.dates
		};
	}
}<|endoftext|>


<commit_before>import { connect } from "react-redux";
import React from "react";
import remark from "remark";
import emoji from "remark-gemoji-to-emoji";

import { Flag, Headline, Link, Markdown, styled, Tag, Text, ThemeProvider, themes } from "@patternplate/components";

import * as item from "../../selectors/item";
import Fullscreen from "../../containers/trigger-fullscreen";
import ToggleOpacity from "../../containers/toggle-opacity";
import ConnectedComponentList from "../../containers/component-list-widget";
import ConnectedComponentDemo from "../../containers/component-demo-widget";

const processor = remark().use(emoji);

export default connect(mapProps)(PatternSheet);

function PatternSheet(props) {
  return (
    <StyledPatternSheet>
      <StyledPatternSheetContainer>
          <StyledControlsBox>
            <StyledName>
              {props.name}
              <StyledVersion>@{props.version}</StyledVersion>
            </StyledName>
            <ThemeProvider theme={themes().dark}>
              <StyledControlsArea orient="right">
                <StyledControlsItem>
                  <ToggleOpacity />
                </StyledControlsItem>
                <StyledControlsItem>
                  <Fullscreen />
                </StyledControlsItem>
              </StyledControlsArea>
            </ThemeProvider>
          </StyledControlsBox>
          {props.description &&
            <StyledDescription>
              {processor.processSync(props.description).contents}
            </StyledDescription>
          }
          <StyledBoxLine>
            <SearchTrigger field="flag" search={props.flag}>
              <Flag>{props.flag}</Flag>
            </SearchTrigger>
            <StyledTagList>
              {
                props.tags.map((tag, index) => (
                  <SearchTrigger key={`${tag}-${index}`} field="tags" search={tag}>
                    <Tag>{tag}</Tag>
                  </SearchTrigger>
                ))
              }
            </StyledTagList>
          </StyledBoxLine>
          {typeof props.doc === "string" &&
            <StyledMarkdownBox>
              <Markdown
                linkable={true}
                source={props.doc}
                widgets={{
                  PatternList: ConnectedComponentList,
                  PatternDemo: ConnectedComponentDemo,
                  ComponentList: ConnectedComponentList,
                  ComponentDemo: ConnectedComponentDemo
                }}
              />
            </StyledMarkdownBox>
          }
      </StyledPatternSheetContainer>
    </StyledPatternSheet>
  );
}

const StyledSearchTrigger = styled.span`
  &:not(:first-child) {
    margin-left: 10px;
  }
`;

const StyledLink = styled(Link)`
  text-decoration: none;
`;

function SearchTrigger(props) {
  return (
    <StyledSearchTrigger>
      <StyledLink
        className={props.className}
        query={{
          "search-enabled": true,
          search: `${props.field}=${props.search}`
        }}
        title={`Search other patterns with ${props.field} "${props.search}"`}
      >
        {props.children}
      </StyledLink>
    </StyledSearchTrigger>
  );
}

function mapProps(state) {
  return {
    doc: item.selectContents(state),
    description: item.selectDescription(state),
    id: state.id,
    icon: item.selectIcon(state),
    type: item.selectType(state),
    name: item.selectName(state),
    flag: item.selectFlag(state),
    tags: item.selectTags(state),
    version: item.selectVersion(state)
  };
}

const TOOLBAR_HEIGHT = 60;

const StyledName = styled(props => <Headline {...props} is="h1" order={1}/>)`
  margin: 0 0 10px 0;
`;

const StyledVersion = styled(props => <Headline {...props} is="small" order={3}/>)`
  display: inline-block;
  color: ${props => props.theme.dark};
  margin: 0;
`;

const StyledDescription = styled(Text)`
  color: ${props => props.theme.recess};
  margin-bottom: 20px;
`;

const StyledPatternSheet = styled.div`
/*   position: relative; */
  z-index: 2;
  box-sizing: border-box;
  width: 100%;
  min-height: 30vh;
  margin-top: 70vh;
  padding: 30px 60px;
  border-top: 1px solid ${props => props.theme.border};
  background: ${props => props.theme.background};
`;

const ORIENTATION = props => {
  const direction = props.orient === "right" ? "left" : "right";
  return `margin-${direction}: auto`;
};

const StyledPatternSheetContainer = styled.div`
  margin: 0 auto;
  max-width: 1240px;
`;

const StyledControlsArea = styled.div`
  display: flex;
  ${ORIENTATION};
`;

const StyledControlsBox = styled.div`
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  background: white;
`;

const StyledControlsItem = styled.div`
  & + & {
    padding-left: 10px;
  }
`;

const StyledTagList = styled.div`
  display: inline-block;
  margin-left: 10px;
  padding: 2px 10px;
  border-left: 1px solid ${props => props.theme.border};
`;

const StyledBoxLine = styled.div`
  display: flex;
  align-items: center;
  min-height: 32px;
`;

const StyledMarkdownBox = styled.div`
  margin-top: 30px;
`;
<commit_msg>fix: ensure tags are clickable on pattern sheet<commit_after>import { connect } from "react-redux";
import React from "react";
import remark from "remark";
import emoji from "remark-gemoji-to-emoji";

import { Flag, Headline, Link, Markdown, styled, Tag, Text, ThemeProvider, themes } from "@patternplate/components";

import * as item from "../../selectors/item";
import Fullscreen from "../../containers/trigger-fullscreen";
import ToggleOpacity from "../../containers/toggle-opacity";
import ConnectedComponentList from "../../containers/component-list-widget";
import ConnectedComponentDemo from "../../containers/component-demo-widget";

const processor = remark().use(emoji);

export default connect(mapProps)(PatternSheet);

function PatternSheet(props) {
  return (
    <StyledPatternSheet screenshot={props.screenshot}>
      <StyledPatternSheetContainer>
          <StyledControlsBox>
            <StyledName>
              {props.name}
              <StyledVersion>@{props.version}</StyledVersion>
            </StyledName>
            <ThemeProvider theme={themes().dark}>
              <StyledControlsArea orient="right">
                <StyledControlsItem>
                  <ToggleOpacity />
                </StyledControlsItem>
                <StyledControlsItem>
                  <Fullscreen />
                </StyledControlsItem>
              </StyledControlsArea>
            </ThemeProvider>
          </StyledControlsBox>
          {props.description &&
            <StyledDescription>
              {processor.processSync(props.description).contents}
            </StyledDescription>
          }
          <StyledBoxLine>
            <SearchTrigger field="flag" search={props.flag}>
              <Flag>{props.flag}</Flag>
            </SearchTrigger>
            <StyledTagList>
              {
                props.tags.map((tag, index) => (
                  <SearchTrigger key={`${tag}-${index}`} field="tags" search={tag}>
                    <Tag>{tag}</Tag>
                  </SearchTrigger>
                ))
              }
            </StyledTagList>
          </StyledBoxLine>
          {typeof props.doc === "string" &&
            <StyledMarkdownBox>
              <Markdown
                linkable={true}
                source={props.doc}
                widgets={{
                  PatternList: ConnectedComponentList,
                  PatternDemo: ConnectedComponentDemo,
                  ComponentList: ConnectedComponentList,
                  ComponentDemo: ConnectedComponentDemo
                }}
              />
            </StyledMarkdownBox>
          }
      </StyledPatternSheetContainer>
    </StyledPatternSheet>
  );
}

const StyledSearchTrigger = styled.span`
  &:not(:first-child) {
    margin-left: 10px;
  }
`;

const StyledLink = styled(Link)`
  text-decoration: none;
`;

function SearchTrigger(props) {
  return (
    <StyledSearchTrigger>
      <StyledLink
        className={props.className}
        query={{
          "search-enabled": true,
          search: `${props.field}=${props.search}`
        }}
        title={`Search other patterns with ${props.field} "${props.search}"`}
      >
        {props.children}
      </StyledLink>
    </StyledSearchTrigger>
  );
}

function mapProps(state) {
  return {
    doc: item.selectContents(state),
    description: item.selectDescription(state),
    id: state.id,
    icon: item.selectIcon(state),
    type: item.selectType(state),
    name: item.selectName(state),
    flag: item.selectFlag(state),
    tags: item.selectTags(state),
    version: item.selectVersion(state),
    screenshot: state.routing.locationBeforeTransitions.query.screenshot === "true"
  };
}

const TOOLBAR_HEIGHT = 60;

const StyledName = styled(props => <Headline {...props} is="h1" order={1}/>)`
  margin: 0 0 10px 0;
`;

const StyledVersion = styled(props => <Headline {...props} is="small" order={3}/>)`
  display: inline-block;
  color: ${props => props.theme.dark};
  margin: 0;
`;

const StyledDescription = styled(Text)`
  color: ${props => props.theme.recess};
  margin-bottom: 20px;
`;

const StyledPatternSheet = styled.div`
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  width: 100%;
  min-height: 30vh;
  margin-top: 70vh;
  padding: 30px 60px;
  border-top: 1px solid ${props => props.theme.border};
  background: ${props => props.theme.background};
`;

const ORIENTATION = props => {
  const direction = props.orient === "right" ? "left" : "right";
  return `margin-${direction}: auto`;
};

const StyledPatternSheetContainer = styled.div`
  margin: 0 auto;
  max-width: 1240px;
`;

const StyledControlsArea = styled.div`
  display: flex;
  ${ORIENTATION};
`;

const StyledControlsBox = styled.div`
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  background: white;
`;

const StyledControlsItem = styled.div`
  & + & {
    padding-left: 10px;
  }
`;

const StyledTagList = styled.div`
  display: inline-block;
  margin-left: 10px;
  padding: 2px 10px;
  border-left: 1px solid ${props => props.theme.border};
`;

const StyledBoxLine = styled.div`
  display: flex;
  align-items: center;
  min-height: 32px;
`;

const StyledMarkdownBox = styled.div`
  margin-top: 30px;
`;
<|endoftext|>


<commit_before>var files = [
    {
        name:"flokkie_Pak ze",
        title:"Pak ze",
        author:"flokkie"
    },
    {	name: "wim_Soldaat Reuterink!",
	title: "Soldaat Reuterink!",
	author: "wim",
    },
    {
        name:"jos_Hey! Klootzak",
        title:"Hey! Klootzak!",
        author:"jos"
    },
    {
        name:"flokkie_Hey Evert",
        title:"Hey Evert",
        author:"flokkie"
    },
    {
        name:"wim_Goed gehydrateerd blijven",
        title:"Goed gehydrateerd blijven",
        author:"wim"
    },
    {
        name:"flokkie_Koekoek",
        title:"Koekoek",
        author:"flokkie"
    },
    {
	name: "wim_Godsamme, krijg toch de vinkentering man!",
	title: "Godsamme, krijg toch de vinkentering man!",
	author: "wim"
    },
    {
        name:"yarno_Best Reload Moment Ever",
        title:"Best Reload Moment Ever",
        author:"yarno"
    },
    {
        name:"flokkie_Twee men",
        title:"Twee men",
        author:"flokkie"
    },
    {
        name:"jelle_Kutkutkut",
        title:"Kutkutkut",
        author:"jelle"
    },
    {
        name:"flokkie_Verkeerde knopje",
        title:"Verkeerde knopje",
        author:"flokkie"
    },
    {
        name:"wim_Ha! Ik heb mijn neus dicht",
        title:"Ha! Ik heb mijn neus dicht",
        author:"wim"
    },
    {
        name:"flokkie_WTF Ricardo",
        title:"WTF Ricardo?!",
        author:"flokkie"
    },
    {
        name:"yarno_Nou nou",
        title:"Nou nou",
        author:"yarno"
    },
    {	name: "wim_ neeneenee, zo werkt dat niet jongeman",
	title:"Nee nee, zo werkt dat niet jongeman",
	author: "wim"
    },
    {
        name:"flokkie_Wat doet ie nou",
        title:"Wat doet ie nou",
        author:"flokkie"
    },
    {
        name:"yarno_Zo jammer",
        title:"Zo jammer",
        author:"yarno"
    },
    {
        name:"flokkie_Wat doe je nou Jos",
        title:"Wat doe je nou Jos?",
        author:"flokkie"
    },
    {
        name:"wim_Hoezo ben ik nou de piemel",
        title:"Hoezo ben ik nou de piemel?",
        author:"wim"
    },
    {
        name:"flokkie_Zo fucking kansloos",
        title:"Zo fucking kansloos",
        author:"flokkie"
    },
    {
        name: "yarno_Flokkie Flokstra!",
        title: "Flokkie Flokstra!",
        author: "yarno"
    },
    {
        name:"flokkie_I'm coming for you Jos",
        title:"I'm coming for you!",
        author:"flokkie"
    },
    {
    	name:"jos_Welkom bij de eerste zelfmoord van vandaag",
    	title: "Welkom bij de eerste zelfmoord van vandaag",
    	author: "jos"
    },
    {
        name:"flokkie_Jaja ja",
        title:"Jaja ja",
        author:"flokkie"
    },
    {
        name:"wim_G-R-A-T-I-S",
        title:"G-R-A-T-I-S",
        author:"wim"
    },
    {
        name:"flokkie_Are you the aardappel",
        title:"Are you the aardappel?",
        author:"flokkie"
    },
    {
        name: "yarno_Wat is dit nou weer",
        title: "Wat is dit nou weer",
        author: "yarno"
    },
    {
        name:"flokkie_I am the aardappel",
        title:"I am the aardappel",
        author:"flokkie"
    },
    {
        name:"wim_Hagrid",
        title:"Hagrid",
        author:"wim"
    }
];
<commit_msg>[WEB] fixed indentation to match standard.<commit_after>var files = [
    {
        name:"flokkie_Pak ze",
        title:"Pak ze",
        author:"flokkie"
    },
    {
        name: "wim_Soldaat Reuterink!",
	    title: "Soldaat Reuterink!",
	    author: "wim",
    },
    {
        name:"jos_Hey! Klootzak",
        title:"Hey! Klootzak!",
        author:"jos"
    },
    {
        name:"flokkie_Hey Evert",
        title:"Hey Evert",
        author:"flokkie"
    },
    {
        name:"wim_Goed gehydrateerd blijven",
        title:"Goed gehydrateerd blijven",
        author:"wim"
    },
    {
        name:"flokkie_Koekoek",
        title:"Koekoek",
        author:"flokkie"
    },
    {
        name: "wim_Godsamme, krijg toch de vinkentering man!",
        title: "Godsamme, krijg toch de vinkentering man!",
        author: "wim"
    },
    {
        name:"yarno_Best Reload Moment Ever",
        title:"Best Reload Moment Ever",
        author:"yarno"
    },
    {
        name:"flokkie_Twee men",
        title:"Twee men",
        author:"flokkie"
    },
    {
        name:"jelle_Kutkutkut",
        title:"Kutkutkut",
        author:"jelle"
    },
    {
        name:"flokkie_Verkeerde knopje",
        title:"Verkeerde knopje",
        author:"flokkie"
    },
    {
        name:"wim_Ha! Ik heb mijn neus dicht",
        title:"Ha! Ik heb mijn neus dicht",
        author:"wim"
    },
    {
        name:"flokkie_WTF Ricardo",
        title:"WTF Ricardo?!",
        author:"flokkie"
    },
    {
        name:"yarno_Nou nou",
        title:"Nou nou",
        author:"yarno"
    },
    {
        name: "wim_ neeneenee, zo werkt dat niet jongeman",
	    title:"Nee nee, zo werkt dat niet jongeman",
	    author: "wim"
    },
    {
        name:"flokkie_Wat doet ie nou",
        title:"Wat doet ie nou",
        author:"flokkie"
    },
    {
        name:"yarno_Zo jammer",
        title:"Zo jammer",
        author:"yarno"
    },
    {
        name:"flokkie_Wat doe je nou Jos",
        title:"Wat doe je nou Jos?",
        author:"flokkie"
    },
    {
        name:"wim_Hoezo ben ik nou de piemel",
        title:"Hoezo ben ik nou de piemel?",
        author:"wim"
    },
    {
        name:"flokkie_Zo fucking kansloos",
        title:"Zo fucking kansloos",
        author:"flokkie"
    },
    {
        name: "yarno_Flokkie Flokstra!",
        title: "Flokkie Flokstra!",
        author: "yarno"
    },
    {
        name:"flokkie_I'm coming for you Jos",
        title:"I'm coming for you!",
        author:"flokkie"
    },
    {
    	name:"jos_Welkom bij de eerste zelfmoord van vandaag",
    	title: "Welkom bij de eerste zelfmoord van vandaag",
    	author: "jos"
    },
    {
        name:"flokkie_Jaja ja",
        title:"Jaja ja",
        author:"flokkie"
    },
    {
        name:"wim_G-R-A-T-I-S",
        title:"G-R-A-T-I-S",
        author:"wim"
    },
    {
        name:"flokkie_Are you the aardappel",
        title:"Are you the aardappel?",
        author:"flokkie"
    },
    {
        name: "yarno_Wat is dit nou weer",
        title: "Wat is dit nou weer",
        author: "yarno"
    },
    {
        name:"flokkie_I am the aardappel",
        title:"I am the aardappel",
        author:"flokkie"
    },
    {
        name:"wim_Hagrid",
        title:"Hagrid",
        author:"wim"
    }
];
<|endoftext|>


<commit_before>(function() {
"use strict";

app.template = function(src) {
    return function(vars) {
        return _.template(src, vars, {interpolate: /{{([\s\S]+?)}}/g});
    };
};

app.PersonSearch = Backbone.View.extend({

    item_html: app.template('
{{ name }}
'),

    events: {
        'submit': 'on_submit'
    },

    initialize: function(options) {
        this.url = options['url'];
    },

    on_submit: function(evt) {
        evt.preventDefault();
        this.query = this.$el.find('[name=query]').val();
        this.update(this.query);
    },

    update: function(query) {
        this.request = $.getJSON(this.url, {q: query});
        this.request.done(_.bind(this.got_update_result, this));
    },

    got_update_result: function(data) {
        this.$el.find('.results').remove();

        if(data['results'].length > 0) {
            var result_list = $('
');
            result_list.appendTo(this.el);
            _(data['results']).forEach(function(result) {
                var link = $('').attr('href', result['url']).text(name);
                var html = this.item_html(result);
                result_list.append(html);
            }, this);
        }
        else {
            var message = $('
');
            message.append(
                "Nu am gasit ",
                $('').text(this.query),
                "."
            );
            this.$el.append(message);
        }
    }

});

app.render_timestream = function(box, data) {
    var margin = 50;
    var width = box.width() - 2*margin;
    var height = 100;

    var svg = d3.select(box[0])
        .append('svg')
        .attr('width', width + 2*margin)
        .attr('height', height + 2*margin)
        .append("g")
          .attr("transform", "translate(" + margin + "," + margin + ")");

    var parseDate = d3.time.format("%Y-%m-%d").parse;

    var x = d3.time.scale()
        .range([0, width]);

    var y = d3.scale.linear()
        .range([height, 0]);

    var color = d3.scale.category10();

    var xAxis = d3.svg.axis()
        .ticks(6)
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .tickFormat(d3.format("d"))
        .scale(y)
        .orient("left");

    var line = d3.svg.line()
        .interpolate("linear")
        .x(function(d) { return x(d.date); })
        .y(function(d) { return y(d.value); });

    var labels = d3.keys(data[0]).filter(function(key) { return key !== "date"; });
    color.domain(labels);

    data.forEach(function(d) {
      d.date = parseDate(d.date);
    });

    var activities = color.domain().map(function(name) {
      return {
        name: name,
        values: data.map(function(d) {
          return {date: d.date, value: +d[name]};
        })
      };
    });

    x.domain(d3.extent(data, function(d) { return d.date; }));

    y.domain([
      d3.min(activities, function(c) { return d3.min(c.values, function(v) { return v.value; }); }),
      d3.max(activities, function(c) { return d3.max(c.values, function(v) { return v.value; }); })
    ]);

    var activity = svg.selectAll(".activity")
        .data(activities)
      .enter().append("g")
        .attr("class", "activity");

    activity.append("path")
        .attr("class", "person-timestream-line")
        .attr("d", function(d) { return line(d.values); })
        .style("stroke", function(d) { return color(d.name); });

    svg.append("g")
        .attr("class", "person-timestream-axis x")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    svg.append("g")
        .attr("class", "person-timestream-axis y")
        .call(yAxis);
};

})();
<commit_msg>translate time labels<commit_after>(function() {
"use strict";

app.template = function(src) {
    return function(vars) {
        return _.template(src, vars, {interpolate: /{{([\s\S]+?)}}/g});
    };
};

app.PersonSearch = Backbone.View.extend({

    item_html: app.template('
{{ name }}
'),

    events: {
        'submit': 'on_submit'
    },

    initialize: function(options) {
        this.url = options['url'];
    },

    on_submit: function(evt) {
        evt.preventDefault();
        this.query = this.$el.find('[name=query]').val();
        this.update(this.query);
    },

    update: function(query) {
        this.request = $.getJSON(this.url, {q: query});
        this.request.done(_.bind(this.got_update_result, this));
    },

    got_update_result: function(data) {
        this.$el.find('.results').remove();

        if(data['results'].length > 0) {
            var result_list = $('
');
            result_list.appendTo(this.el);
            _(data['results']).forEach(function(result) {
                var link = $('').attr('href', result['url']).text(name);
                var html = this.item_html(result);
                result_list.append(html);
            }, this);
        }
        else {
            var message = $('
');
            message.append(
                "Nu am gasit ",
                $('').text(this.query),
                "."
            );
            this.$el.append(message);
        }
    }

});

app.months_en = ["January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"];
app.months_ro = ["ianuarie", "februarie", "martie", "aprilie", "mai", "iunie",
    "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie"];

app.translate_time = function(value) {
    for(var c = 0; c < 12; c ++) {
        value = value.replace(app.months_en[c], app.months_ro[c]);
    }
    return value;
};

app.render_timestream = function(box, data) {
    var margin = 50;
    var width = box.width() - 2*margin;
    var height = 100;

    var svg = d3.select(box[0])
        .append('svg')
        .attr('width', width + 2*margin)
        .attr('height', height + 2*margin)
        .append("g")
          .attr("transform", "translate(" + margin + "," + margin + ")");

    var parseDate = d3.time.format("%Y-%m-%d").parse;

    var x = d3.time.scale()
        .range([0, width]);

    var y = d3.scale.linear()
        .range([height, 0]);

    var color = d3.scale.category10();

    var xAxis = d3.svg.axis()
        .ticks(6)
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .tickFormat(d3.format("d"))
        .scale(y)
        .orient("left");

    var line = d3.svg.line()
        .interpolate("linear")
        .x(function(d) { return x(d.date); })
        .y(function(d) { return y(d.value); });

    var labels = d3.keys(data[0]).filter(function(key) { return key !== "date"; });
    color.domain(labels);

    data.forEach(function(d) {
      d.date = parseDate(d.date);
    });

    var activities = color.domain().map(function(name) {
      return {
        name: name,
        values: data.map(function(d) {
          return {date: d.date, value: +d[name]};
        })
      };
    });

    x.domain(d3.extent(data, function(d) { return d.date; }));

    y.domain([
      d3.min(activities, function(c) { return d3.min(c.values, function(v) { return v.value; }); }),
      d3.max(activities, function(c) { return d3.max(c.values, function(v) { return v.value; }); })
    ]);

    var activity = svg.selectAll(".activity")
        .data(activities)
      .enter().append("g")
        .attr("class", "activity");

    activity.append("path")
        .attr("class", "person-timestream-line")
        .attr("d", function(d) { return line(d.values); })
        .style("stroke", function(d) { return color(d.name); });

    svg.append("g")
        .attr("class", "person-timestream-axis x")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    svg.append("g")
        .attr("class", "person-timestream-axis y")
        .call(yAxis);

    $('.person-timestream-axis.x .tick text').map(function() {
        var el = $(this);
        el.text(app.translate_time(el.text()));
    });
};

})();
<|endoftext|>


<commit_before>/*global defineSuite*/
defineSuite([
        'Scene/Cesium3DTileset',
        'Widgets/CesiumInspector/Cesium3DTilesInspector',
        'Specs/createScene',
        'Core/Ellipsoid',
        'Scene/Globe',
        'ThirdParty/when'
    ], function(
        Cesium3DTileset,
        Cesium3DTilesInspector,
        createScene,
        Ellipsoid,
        Globe,
        when) {
    'use strict';

    // Parent tile with content and four child tiles with content
    var tilesetUrl = './Data/Cesium3DTiles/Tilesets/Tileset/';

    var scene;
    beforeAll(function() {
        scene = createScene();
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        var globe = new Globe(ellipsoid);
        scene.globe = globe;
    });

    afterAll(function() {
        scene.destroyForSpecs();
    });

    it('can create and destroy', function() {
        var container = document.createElement('div');
        container.id = 'testContainer';
        document.body.appendChild(container);

        var widget = new Cesium3DTilesInspector('testContainer', scene);
        expect(widget.container).toBe(container);
        expect(widget.viewModel._scene).toBe(scene);
        expect(widget.isDestroyed()).toEqual(false);
        widget.destroy();
        expect(widget.isDestroyed()).toEqual(true);

        document.body.removeChild(container);
    });

    it('constructor throws with no element', function() {
        expect(function() {
            return new Cesium3DTilesInspector();
        }).toThrowDeveloperError();
    });

    it('constructor throws with string element that does not exist', function() {
        expect(function() {
            return new Cesium3DTilesInspector('does not exist', scene);
        }).toThrowDeveloperError();
    });

    it('constructor throws with no scene', function() {
        expect(function() {
            return new Cesium3DTilesInspector(document.body);
        }).toThrowDeveloperError();
    });

    describe('logging', function() {
        var widget;
        beforeAll(function() {
            var container = document.createElement('div');
            container.id = 'testContainer';
            document.body.appendChild(container);
            widget = new Cesium3DTilesInspector('testContainer', scene);

            var viewModel = widget.viewModel;
            viewModel.tileset = new Cesium3DTileset({
                url: tilesetUrl
            });
            var done = when.defer();
            viewModel._tilesetLoaded.then(function() {
                done.resolve();
            });
            return done;
        });

        afterAll(function() {
            widget.destroy();
        });

        it ('shows performance', function() {
            var viewModel = widget.viewModel;
            viewModel.performance = true;
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-show') !== -1).toBe(true);
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-hide') === -1).toBe(true);
            viewModel.performance = false;
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-show') === -1).toBe(true);
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-hide') !== -1).toBe(true);
        });

        it ('shows stats', function() {
            var viewModel = widget.viewModel;
            viewModel.showStats = true;
            expect(viewModel.statsText).not.toBe('');
            viewModel.showStats = false;
            expect(viewModel.statsText).toBe('');
        });

        it ('shows pick stats', function() {
            var viewModel = widget.viewModel;
            viewModel.picking = true;
            viewModel.showPickStats = true;
            expect(viewModel.pickStatsText).not.toBe('');
            viewModel.showPickStats = false;
            expect(viewModel.pickStatsText).toBe('');
        });
    });
}, 'WebGL');
<commit_msg>properly clean up testContainer element<commit_after>/*global defineSuite*/
defineSuite([
        'Scene/Cesium3DTileset',
        'Widgets/CesiumInspector/Cesium3DTilesInspector',
        'Specs/createScene',
        'Core/Ellipsoid',
        'Scene/Globe',
        'ThirdParty/when'
    ], function(
        Cesium3DTileset,
        Cesium3DTilesInspector,
        createScene,
        Ellipsoid,
        Globe,
        when) {
    'use strict';

    // Parent tile with content and four child tiles with content
    var tilesetUrl = './Data/Cesium3DTiles/Tilesets/Tileset/';

    var scene;
    beforeAll(function() {
        scene = createScene();
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        var globe = new Globe(ellipsoid);
        scene.globe = globe;
    });

    afterAll(function() {
        scene.destroyForSpecs();
    });

    it('can create and destroy', function() {
        var container = document.createElement('div');
        container.id = 'testContainer';
        document.body.appendChild(container);

        var widget = new Cesium3DTilesInspector('testContainer', scene);
        expect(widget.container).toBe(container);
        expect(widget.viewModel._scene).toBe(scene);
        expect(widget.isDestroyed()).toEqual(false);
        widget.destroy();
        expect(widget.isDestroyed()).toEqual(true);

        document.body.removeChild(container);
    });

    it('constructor throws with no element', function() {
        expect(function() {
            return new Cesium3DTilesInspector();
        }).toThrowDeveloperError();
    });

    it('constructor throws with string element that does not exist', function() {
        expect(function() {
            return new Cesium3DTilesInspector('does not exist', scene);
        }).toThrowDeveloperError();
    });

    it('constructor throws with no scene', function() {
        expect(function() {
            return new Cesium3DTilesInspector(document.body);
        }).toThrowDeveloperError();
    });

    describe('logging', function() {
        var widget;
        var container;

        beforeAll(function() {
            container = document.createElement('div');
            container.id = 'testContainer';
            document.body.appendChild(container);
            widget = new Cesium3DTilesInspector('testContainer', scene);

            var viewModel = widget.viewModel;
            viewModel.tileset = new Cesium3DTileset({
                url: tilesetUrl
            });
            return viewModel._tilesetLoaded;
        });

        afterAll(function() {
            widget.destroy();
            document.body.removeChild(container);
        });

        it ('shows performance', function() {
            var viewModel = widget.viewModel;
            viewModel.performance = true;
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-show') !== -1).toBe(true);
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-hide') === -1).toBe(true);
            viewModel.performance = false;
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-show') === -1).toBe(true);
            expect(viewModel._performanceDisplay._container.className.indexOf('cesium-cesiumInspector-hide') !== -1).toBe(true);
        });

        it ('shows stats', function() {
            var viewModel = widget.viewModel;
            viewModel.showStats = true;
            expect(viewModel.statsText).not.toBe('');
            viewModel.showStats = false;
            expect(viewModel.statsText).toBe('');
        });

        it ('shows pick stats', function() {
            var viewModel = widget.viewModel;
            viewModel.picking = true;
            viewModel.showPickStats = true;
            expect(viewModel.pickStatsText).not.toBe('');
            viewModel.showPickStats = false;
            expect(viewModel.pickStatsText).toBe('');
        });
    });
}, 'WebGL');
<|endoftext|>


<commit_before>Tabula = window.Tabula || {};

Tabula.FileUpload = Backbone.Model.extend({
  // isOneOfMultiple:
  // uploadTime
  // uploadOrder
  initialize: function(){
    this.set({
      message: 'waiting to be processed...',
      pct_complete: 0,
    });
  },

  checkStatus: function() {
    if(typeof this.get('file_id') == 'undefined' && typeof !this.get('upload_id') == 'undefined'){
      this.pct_complete = 1;
      this.message = "waiting to be processed..."
    }else{
      $.ajax({
          dataType: 'json',
          url: '/queue/'+this.get('upload_id')+'/json?file_id=' + this.get('file_id'),
          success: _.bind(function(data, status, xhr) {
            if( (data.message.length && data.message != "complete") || data.pct_complete == 100 ){
              this.set('message',  data.message);
            } else if(data.pct_complete > 1) {
              this.set('message', 'processing');
            }

            this.set('pct_complete', data.pct_complete);

            if (data.status == "error" && data.error_type == "unknown") {
                // window.location.reload(true);
            } else if (data.status == "error" && data.error_type == "no-text") {
                console.log('no text');
                window.clearTimeout(this.timer);
                alert("Sorry, your PDF file is image-based; it does not have any embedded text. It might have been scanned... Tabula can't be able to extract any data from image-based PDFs. (Though you can try OCRing the PDF with a tool like Tesseract and then trying Tabula again.)") //TODO: something prettier.
            } else if(data.pct_complete < 100) {
                this.timer = setTimeout(_.bind(this.checkStatus, this), 1000);
            } else {
              this.collection.remove(this);
              Tabula.library.files_collection.fetch();
            }
          }, this),
          error: function(xhr, status, err) {
              console.log('err', err); //TODO:
          }
      });
    }
  },

});

// does flash work?
// clear the input

Tabula.FileUploadsCollection = Backbone.Collection.extend({
  model: Tabula.FileUpload,
  comparator: function(i){ return -i.get('uploadTime') - i.get('uploadOrder')},
})

Tabula.UploadedFile = Backbone.Model.extend({
  size: null,
  page_count: null,
  initialize: function(){
    this.set('size', this.get('size') || null);
    this.set('page_count', this.get('page_count') || null)
  }
});

Tabula.UploadedFilesCollection = Backbone.Collection.extend({
    model: Tabula.UploadedFile,
    url: '/pdfs/workspace.json',
    comparator: function(i){ return -i.get('time')},
    parse: function(items){
      _(items).each(function(i){
        if(!i.original_filename){
          i.original_filename = i.file;
        }
      });
      // if it's still being processed, don't enter it into the library.
      items = _(items).reject(_.bind(function(uploaded_file){
        var in_progress = Tabula.library && Tabula.library.uploads_collection.findWhere({file_id: uploaded_file.id});
        return in_progress
      }, this));
      return items;
    }
});

Tabula.UploadedFileView = Backbone.View.extend({
  tagName: 'tr',
  className: 'uploaded-file',
  events: {
    'click .delete-pdf': 'deletePDF'
  },
  template: _.template( $('#uploaded-file-template').html().replace(/nestedscript/g, 'script')),
  initialize: function(){
    _.bindAll(this, 'render', 'deletePDF');
  },
  render: function(){
    this.$el.append(this.template(this.model.attributes));
    this.$el.addClass('file-id-' + this.model.get('id')); // more efficient lookups than data-attr
    this.$el.data('id', this.model.get('id')); //more cleanly accesse than a class
    return this;
  },
  deletePDF: function(e) {
    var btn = $(e.currentTarget);
    var tr = btn.parents('tr');

    if (!confirm('Delete file "'+btn.data('filename')+'"?')) return;
    var pdf_id = btn.data('pdfid');

    $.post('/pdf/' + pdf_id,
          { _method: 'delete' },
          function() {
            tr.fadeOut(200, function() { $(this).remove(); });
          });
    },
})

Tabula.ProgressBars = Backbone.View.extend({
  template: _.template( $('#progress-bars-template').html().replace(/nestedscript/g, 'script')),
  initialize: function(stuff){
    _.extend(this, stuff); //  in-place.
    this.listenTo(this.uploads_collection, 'remove', this.render);
  },
  render: function(){
    if(this.uploads_collection.size() > 0){
      this.in_progress = false;
      if(!$.trim(this.$el.html())) this.$el.html(this.template({}))
    }else if(!this.in_progress){
      //TODO: this belongs in Library, technically, but we don't go around rerendering that, so here it is for now.
      $('form#upload').find('button').removeAttr('disabled');
      $('form#upload')[0].reset();
    }
    return this;
  }
});

Tabula.Library = Backbone.View.extend({
    events: {
        "submit form#upload": 'uploadPDF',
    },
    template: _.template( $('#uploader-template').html().replace(/nestedscript/g, 'script')),
    initialize: function(){
      _.bindAll(this, 'uploadPDF', 'render', 'renderFileLibrary');
      this.files_collection = new Tabula.UploadedFilesCollection([]);
      this.files_collection.fetch({silent: true, success: _.bind(function(){ this.render(); this.renderFileLibrary(); }, this) });
      this.listenTo(this.files_collection, 'add', this.renderFileLibrary);
      this.uploads_collection = new Tabula.FileUploadsCollection([]);
    },
    uploadPDF: function(e){
      $(e.currentTarget).find('button').attr('disabled', 'disabled');
      this.progress_bars = new Tabula.ProgressBars({el: '#progress-container', uploads_collection: this.uploads_collection });
      this.progress_bars.in_progress = true;
      this.progress_bars.render();

      var files_list = $(e.currentTarget).find('#file')[0].files
      _(files_list).each(_.bind(function(file, index){
        //TODO: the model should get the data, then fire an event that the view listens for, to rerender
        var file_upload = new Tabula.FileUpload({
          collection: this.uploads_collection,
          filename: file.name,
          uploadTime: new Date(),
          uploadOrder: index,
          isOneOfMultiple: files_list.length != 1
        });
        this.uploads_collection.add(file_upload);
        var checker = new Tabula.ProgressBar({model: file_upload });
        this.progress_bars.render().$el.find('#progress-bars-container').append(checker.render().el)
      },this));

      var formdata = new FormData($('form#upload')[0]);
      $.ajax({
          url: $('form#upload').attr('action'),
          type: 'POST',
          success: _.bind(function (res) {
              var statuses = JSON.parse(res);
              _(statuses).each(_.bind(function(status){
                var file_upload = this.uploads_collection.findWhere({filename: status.filename });
                if(!file_upload){
                  console.log("couldn't find upload objcect for " + status.filename );
                  return
                }
                if(status.success){
                  file_upload.set('file_id', status.file_id);
                  file_upload.set('id', status.file_id);
                  file_upload.set('upload_id', status.upload_id);
                  file_upload.set('error', !status.success);
                  file_upload.checkStatus(); //
                }else{
                  console.log('TODO: failure')
                  file_upload.set('file_id', status.file_id);
                  file_upload.set('id', status.file_id);
                  file_upload.set('upload_id', status.upload_id);
                  file_upload.set('error', !status.success);
                }
              }, this))
          }, this),
          error: _.bind(function(a,b,c){
            this.uploads_collection.each(function(file_upload){
              file_upload.message = "Sorry, your file upload could not be processed. ("+a.statusText+")";
              file_upload.pct_complete = 100;
              file_upload.error = true;
            })
            //TODO: cope with multiple
            $(e.currentTarget).find('button').removeAttr('disabled');
          },this),
          data: formdata,

          cache: false,
          contentType: false,
          processData: false
      });
      e.preventDefault();
      return false; // don't actually submit the form
    },

    renderFileLibrary: function(added_model){
      if(this.files_collection.length > 0){
        ($('#uploaded-files-container').is(':empty') ? this.files_collection.reverse() : this.files_collection).
        each(_.bind(function(uploaded_file){
          if(this.$el.find('.file-id-' + uploaded_file.get('id') ).length){
            return;
          }
          var file_element = new Tabula.UploadedFileView({model: uploaded_file}).render().$el;
          if(added_model && added_model.get('id') == uploaded_file.get('id')){
            file_element.addClass('flash');
          }
          $('#uploaded-files-container').prepend(file_element);
        }, this));

        //remove anything that was deleted
        this.$el.find('.uploaded-file').each(_.bind(function(i, el){
          if(typeof this.files_collection.findWhere({id: $(el).data('id')}) === "undefined"){
            $(el).remove();
          }
        }, this));

        $("#fileTable").tablesorter( {
          headers: { 3: { sorter: "usLongDate" },  4: { sorter: false}, 5: {sorter: false} },
          sortList: [[3,1]]  // initial sort
          } );
      }else{
        $('#uploaded-files-container').html( $('
No uploaded files yet.
') );
      }
    },

    render: function(){
      $('#tabula-app').html( this.template({
        TABULA_VERSION: TABULA_VERSION,
        pct_complete: 0,
        importing: false
      }) );
      return this;
    }
});

Tabula.ProgressBar = Backbone.View.extend({
    file_id: null,
    upload_id: null,
    pct_complete: 0,
    message: null,
    tagName: 'div',
    template: _.template( $('#file-upload-template').html().replace(/nestedscript/g, 'script')),
    initialize: function(){
      _.bindAll(this, 'render');
      this.listenTo(this.model, 'change:pct_complete', this.render);
    },

    render: function(){
      if(this.model.get('pct_complete') <= 0){
        this.$el.find('h4').text("Upload Progress");
      }else if(this.model.get('pct_complete') >= 100 && !this.model.get('error')){
        this.$el.find('h4').text("Upload Finished.");
        this.$el.find('#message').text('');
        if (!!this.spinobj) {
            this.spinobj.stop()
        };
        if(this.model.get('isOneOfMultiple')){
          this.remove();
        }else{
          window.location = '/pdf/' + this.model.get('file_id');
        };
      }else if(this.model.get('pct_complete') >= 100 && this.model.get('error')){
        this.$el.find('h4').text("Upload Failed.");
      }else{
        this.$el.find('h4').text("Importing…");
        var spinpots = {
            lines: 11,
            length: 5,
            width: 2,
            radius: 4,
            hwaccel: true,
            top: '0',
            left: 0
        };
        this.spinobj = new Spinner(spinpots).spin(this.$el.find('#spinner')[0]);
      }
      this.$el.html(this.template(this.model.attributes));
      return this;
    }
});<commit_msg>cope with missing workspace.json (zero data state, lookit me with mah big words)<commit_after>Tabula = window.Tabula || {};

Tabula.FileUpload = Backbone.Model.extend({
  // isOneOfMultiple:
  // uploadTime
  // uploadOrder
  initialize: function(){
    this.set({
      message: 'waiting to be processed...',
      pct_complete: 0,
    });
  },

  checkStatus: function() {
    if(typeof this.get('file_id') == 'undefined' && typeof !this.get('upload_id') == 'undefined'){
      this.pct_complete = 1;
      this.message = "waiting to be processed..."
    }else{
      $.ajax({
          dataType: 'json',
          url: '/queue/'+this.get('upload_id')+'/json?file_id=' + this.get('file_id'),
          success: _.bind(function(data, status, xhr) {
            if( (data.message.length && data.message != "complete") || data.pct_complete == 100 ){
              this.set('message',  data.message);
            } else if(data.pct_complete > 1) {
              this.set('message', 'processing');
            }

            this.set('pct_complete', data.pct_complete);

            if (data.status == "error" && data.error_type == "unknown") {
                // window.location.reload(true);
            } else if (data.status == "error" && data.error_type == "no-text") {
                console.log('no text');
                window.clearTimeout(this.timer);
                alert("Sorry, your PDF file is image-based; it does not have any embedded text. It might have been scanned... Tabula can't be able to extract any data from image-based PDFs. (Though you can try OCRing the PDF with a tool like Tesseract and then trying Tabula again.)") //TODO: something prettier.
            } else if(data.pct_complete < 100) {
                this.timer = setTimeout(_.bind(this.checkStatus, this), 1000);
            } else {
              this.collection.remove(this);
              Tabula.library.files_collection.fetch();
            }
          }, this),
          error: function(xhr, status, err) {
              console.log('err', err); //TODO:
          }
      });
    }
  },

});

// does flash work?
// clear the input

Tabula.FileUploadsCollection = Backbone.Collection.extend({
  model: Tabula.FileUpload,
  comparator: function(i){ return -i.get('uploadTime') - i.get('uploadOrder')},
})

Tabula.UploadedFile = Backbone.Model.extend({
  size: null,
  page_count: null,
  initialize: function(){
    this.set('size', this.get('size') || null);
    this.set('page_count', this.get('page_count') || null)
  }
});

Tabula.UploadedFilesCollection = Backbone.Collection.extend({
    model: Tabula.UploadedFile,
    url: '/pdfs/workspace.json',
    comparator: function(i){ return -i.get('time')},
    parse: function(items){
      _(items).each(function(i){
        if(!i.original_filename){
          i.original_filename = i.file;
        }
      });
      // if it's still being processed, don't enter it into the library.
      items = _(items).reject(_.bind(function(uploaded_file){
        var in_progress = Tabula.library && Tabula.library.uploads_collection.findWhere({file_id: uploaded_file.id});
        return in_progress
      }, this));
      return items;
    }
});

Tabula.UploadedFileView = Backbone.View.extend({
  tagName: 'tr',
  className: 'uploaded-file',
  events: {
    'click .delete-pdf': 'deletePDF'
  },
  template: _.template( $('#uploaded-file-template').html().replace(/nestedscript/g, 'script')),
  initialize: function(){
    _.bindAll(this, 'render', 'deletePDF');
  },
  render: function(){
    this.$el.append(this.template(this.model.attributes));
    this.$el.addClass('file-id-' + this.model.get('id')); // more efficient lookups than data-attr
    this.$el.data('id', this.model.get('id')); //more cleanly accesse than a class
    return this;
  },
  deletePDF: function(e) {
    var btn = $(e.currentTarget);
    var tr = btn.parents('tr');

    if (!confirm('Delete file "'+btn.data('filename')+'"?')) return;
    var pdf_id = btn.data('pdfid');

    $.post('/pdf/' + pdf_id,
          { _method: 'delete' },
          function() {
            tr.fadeOut(200, function() { $(this).remove(); });
          });
    },
})

Tabula.ProgressBars = Backbone.View.extend({
  template: _.template( $('#progress-bars-template').html().replace(/nestedscript/g, 'script')),
  initialize: function(stuff){
    _.extend(this, stuff); //  in-place.
    this.listenTo(this.uploads_collection, 'remove', this.render);
  },
  render: function(){
    if(this.uploads_collection.size() > 0){
      this.in_progress = false;
      if(!$.trim(this.$el.html())) this.$el.html(this.template({}))
    }else if(!this.in_progress){
      //TODO: this belongs in Library, technically, but we don't go around rerendering that, so here it is for now.
      $('form#upload').find('button').removeAttr('disabled');
      $('form#upload')[0].reset();
    }
    return this;
  }
});

Tabula.Library = Backbone.View.extend({
    events: {
        "submit form#upload": 'uploadPDF',
    },
    template: _.template( $('#uploader-template').html().replace(/nestedscript/g, 'script')),
    initialize: function(){
      _.bindAll(this, 'uploadPDF', 'render', 'renderFileLibrary');
      this.files_collection = new Tabula.UploadedFilesCollection([]);
      this.files_collection.fetch({silent: true, complete: _.bind(function(){ this.render(); this.renderFileLibrary(); }, this) });
      this.listenTo(this.files_collection, 'add', this.renderFileLibrary);
      this.uploads_collection = new Tabula.FileUploadsCollection([]);
    },
    uploadPDF: function(e){
      $(e.currentTarget).find('button').attr('disabled', 'disabled');
      this.progress_bars = new Tabula.ProgressBars({el: '#progress-container', uploads_collection: this.uploads_collection });
      this.progress_bars.in_progress = true;
      this.progress_bars.render();

      var files_list = $(e.currentTarget).find('#file')[0].files
      _(files_list).each(_.bind(function(file, index){
        //TODO: the model should get the data, then fire an event that the view listens for, to rerender
        var file_upload = new Tabula.FileUpload({
          collection: this.uploads_collection,
          filename: file.name,
          uploadTime: new Date(),
          uploadOrder: index,
          isOneOfMultiple: files_list.length != 1
        });
        this.uploads_collection.add(file_upload);
        var checker = new Tabula.ProgressBar({model: file_upload });
        this.progress_bars.render().$el.find('#progress-bars-container').append(checker.render().el)
      },this));

      var formdata = new FormData($('form#upload')[0]);
      $.ajax({
          url: $('form#upload').attr('action'),
          type: 'POST',
          success: _.bind(function (res) {
              var statuses = JSON.parse(res);
              _(statuses).each(_.bind(function(status){
                var file_upload = this.uploads_collection.findWhere({filename: status.filename });
                if(!file_upload){
                  console.log("couldn't find upload objcect for " + status.filename );
                  return
                }
                if(status.success){
                  file_upload.set('file_id', status.file_id);
                  file_upload.set('id', status.file_id);
                  file_upload.set('upload_id', status.upload_id);
                  file_upload.set('error', !status.success);
                  file_upload.checkStatus(); //
                }else{
                  console.log('TODO: failure')
                  file_upload.set('file_id', status.file_id);
                  file_upload.set('id', status.file_id);
                  file_upload.set('upload_id', status.upload_id);
                  file_upload.set('error', !status.success);
                }
              }, this))
          }, this),
          error: _.bind(function(a,b,c){
            this.uploads_collection.each(function(file_upload){
              file_upload.message = "Sorry, your file upload could not be processed. ("+a.statusText+")";
              file_upload.pct_complete = 100;
              file_upload.error = true;
            })
            //TODO: cope with multiple
            $(e.currentTarget).find('button').removeAttr('disabled');
          },this),
          data: formdata,

          cache: false,
          contentType: false,
          processData: false
      });
      e.preventDefault();
      return false; // don't actually submit the form
    },

    renderFileLibrary: function(added_model){
      if(this.files_collection.length > 0){
        ($('#uploaded-files-container').is(':empty') ? this.files_collection.reverse() : this.files_collection).
        each(_.bind(function(uploaded_file){
          if(this.$el.find('.file-id-' + uploaded_file.get('id') ).length){
            return;
          }
          var file_element = new Tabula.UploadedFileView({model: uploaded_file}).render().$el;
          if(added_model && added_model.get('id') == uploaded_file.get('id')){
            file_element.addClass('flash');
          }
          $('#uploaded-files-container').prepend(file_element);
        }, this));

        //remove anything that was deleted
        this.$el.find('.uploaded-file').each(_.bind(function(i, el){
          if(typeof this.files_collection.findWhere({id: $(el).data('id')}) === "undefined"){
            $(el).remove();
          }
        }, this));

        $("#fileTable").tablesorter( {
          headers: { 3: { sorter: "usLongDate" },  4: { sorter: false}, 5: {sorter: false} },
          sortList: [[3,1]]  // initial sort
          } );
      }else{
        $('#uploaded-files-container').html( $('
No uploaded files yet.
') );
      }
    },

    render: function(){
      $('#tabula-app').html( this.template({
        TABULA_VERSION: TABULA_VERSION,
        pct_complete: 0,
        importing: false
      }) );
      return this;
    }
});

Tabula.ProgressBar = Backbone.View.extend({
    file_id: null,
    upload_id: null,
    pct_complete: 0,
    message: null,
    tagName: 'div',
    template: _.template( $('#file-upload-template').html().replace(/nestedscript/g, 'script')),
    initialize: function(){
      _.bindAll(this, 'render');
      this.listenTo(this.model, 'change:pct_complete', this.render);
    },

    render: function(){
      if(this.model.get('pct_complete') <= 0){
        this.$el.find('h4').text("Upload Progress");
      }else if(this.model.get('pct_complete') >= 100 && !this.model.get('error')){
        this.$el.find('h4').text("Upload Finished.");
        this.$el.find('#message').text('');
        if (!!this.spinobj) {
            this.spinobj.stop()
        };
        if(this.model.get('isOneOfMultiple')){
          this.remove();
        }else{
          window.location = '/pdf/' + this.model.get('file_id');
        };
      }else if(this.model.get('pct_complete') >= 100 && this.model.get('error')){
        this.$el.find('h4').text("Upload Failed.");
      }else{
        this.$el.find('h4').text("Importing…");
        var spinpots = {
            lines: 11,
            length: 5,
            width: 2,
            radius: 4,
            hwaccel: true,
            top: '0',
            left: 0
        };
        this.spinobj = new Spinner(spinpots).spin(this.$el.find('#spinner')[0]);
      }
      this.$el.html(this.template(this.model.attributes));
      return this;
    }
});<|endoftext|>


<commit_before>'use strict';

describe('NEWTON -', function () {

	var NewtonService, NewtonMock, logger;

	beforeEach(function(){
		module('barney');

		inject(function (_BarneyNewton_) {
			NewtonService = _BarneyNewton_;
		});

		logger = {
			log: function(){},
			info: function(){},
			warn: function(){},
			error: function(){}
		};

		NewtonMock = {
			sendEvent: function() {},
			timedEventStart: function() {},
			timedEventStop: function() {}
		};

		window.Newton = {
			getSharedInstance: function(){
				return {
					sendEvent: function(eventName, eventProps){
						NewtonMock.sendEvent(eventName, eventProps);
					},
					timedEventStart: function(eventName, eventProps){
						NewtonMock.timedEventStart(eventName, eventProps);
					},
					timedEventStop: function(eventName, eventProps){
						NewtonMock.timedEventStop(eventName, eventProps);
					}
				}
			},
			SimpleObject: {
				fromJSONObject: function(object){
					return object;
				}
			}
		}

		spyOn(logger, 'log');
		spyOn(NewtonMock, 'sendEvent');
		spyOn(NewtonMock, 'timedEventStart');
		spyOn(NewtonMock, 'timedEventStop');

		NewtonService.init({
			enabled: true,
			verbose: true,
			logger: logger
		})
	});

	describe('trackPage -', function(){
		it('method track a Newton pageview', function(){
			NewtonService.trackPage({
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(NewtonMock.sendEvent).toHaveBeenCalledWith('pageview', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		});

		it('method track a GA pageview, logger', function(){
			NewtonService.trackPage({
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(logger.log).toHaveBeenCalledWith('BarneyNewton', 'track', 'pageview', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		})
	});

	describe('trackEvent -', function(){
		it('method track a Newton pageview', function(){
			NewtonService.trackEvent('bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(NewtonMock.sendEvent).toHaveBeenCalledWith('bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		});

		it('method track a GA pageview, logger', function(){
			NewtonService.trackEvent('bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(logger.log).toHaveBeenCalledWith('BarneyNewton', 'track', 'bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		})
	});

	describe('Heartbeats -', function(){
		it('should start heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

			expect(NewtonMock.timedEventStart).toHaveBeenCalledWith('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });
		});

		it('should stop heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

            NewtonService.stopHeartbeat('aTestHeartbeat');

			expect(NewtonMock.timedEventStop).toHaveBeenCalledWith('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });
		});

		xit('should get an heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

			expect(NewtonService.getSingleHeartbeat('aTestHeartbeat')).toEqual({
				keyWord: 'aTestHeartbeat',
				properties:{
					category: 'Heartbeat',
	                label: '<test>',
	                valuable: 'No',
	                action: 'No'
	        }});
        });

        xit('should stop all heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

            NewtonService.startHeartbeat('aSecondTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

            NewtonService.stopAllHeartbeat();

			expect(NewtonService.heartbeatsList()).toEqual({});
        });
	});

});<commit_msg>applied two tests<commit_after>'use strict';

describe('NEWTON -', function () {

	var NewtonService, NewtonMock, logger;

	beforeEach(function(){
		module('barney');

		inject(function (_BarneyNewton_) {
			NewtonService = _BarneyNewton_;
		});

		logger = {
			log: function(){},
			info: function(){},
			warn: function(){},
			error: function(){}
		};

		NewtonMock = {
			sendEvent: function() {},
			timedEventStart: function() {},
			timedEventStop: function() {}
		};

		window.Newton = {
			getSharedInstance: function(){
				return {
					sendEvent: function(eventName, eventProps){
						NewtonMock.sendEvent(eventName, eventProps);
					},
					timedEventStart: function(eventName, eventProps){
						NewtonMock.timedEventStart(eventName, eventProps);
					},
					timedEventStop: function(eventName, eventProps){
						NewtonMock.timedEventStop(eventName, eventProps);
					}
				}
			},
			SimpleObject: {
				fromJSONObject: function(object){
					return object;
				}
			}
		}

		spyOn(logger, 'log');
		spyOn(NewtonMock, 'sendEvent');
		spyOn(NewtonMock, 'timedEventStart');
		spyOn(NewtonMock, 'timedEventStop');

		NewtonService.init({
			enabled: true,
			verbose: true,
			logger: logger
		})
	});

	describe('trackPage -', function(){
		it('method track a Newton pageview', function(){
			NewtonService.trackPage({
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(NewtonMock.sendEvent).toHaveBeenCalledWith('pageview', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		});

		it('method track a GA pageview, logger', function(){
			NewtonService.trackPage({
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(logger.log).toHaveBeenCalledWith('BarneyNewton', 'track', 'pageview', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		})
	});

	describe('trackEvent -', function(){
		it('method track a Newton pageview', function(){
			NewtonService.trackEvent('bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(NewtonMock.sendEvent).toHaveBeenCalledWith('bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		});

		it('method track a GA pageview, logger', function(){
			NewtonService.trackEvent('bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});

			expect(logger.log).toHaveBeenCalledWith('BarneyNewton', 'track', 'bigBang', {
				page: '/category',
				title: 'Category Page',
				dimensionOne: 'logged',
				dimensionFour: 'premium'
			});
		})
	});

	describe('Heartbeats -', function(){
		it('should start heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

			expect(NewtonMock.timedEventStart).toHaveBeenCalledWith('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });
		});

		it('should stop heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

            NewtonService.stopHeartbeat('aTestHeartbeat');

			expect(NewtonMock.timedEventStop).toHaveBeenCalledWith('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });
		});

		it('should get an heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

			expect(NewtonService.getSingleHeartbeat('aTestHeartbeat')).toEqual({
				keyWord: 'aTestHeartbeat',
				properties:{
					category: 'Heartbeat',
	                label: '<test>',
	                valuable: 'No',
	                action: 'No'
	        }});
        });

        it('should stop all heartbeat', function(){
			NewtonService.startHeartbeat('aTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

            NewtonService.startHeartbeat('aSecondTestHeartbeat', {
                category: 'Heartbeat',
                label: '<test>',
                valuable: 'No',
                action: 'No',
            });

            NewtonService.stopAllHeartbeat();

			expect(NewtonService.heartbeatsList()).toEqual({});
        });
	});

});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Relay from 'react-relay';
import _ from 'lodash';
import { withRouter } from 'react-router';

import Layout from './Layout';
import Icon from './Icon';
import AddEntryMutation from './mutations/AddEntryMutation';
import { withRoles, userFragment } from './wrappers.js';

import TopicForm from './TopicForm';
import SentimentForm from './SentimentForm';
import MediaForm from './MediaForm';
import PageOverlay from './PageOverlay';

import styles from './css/AddEntry.module.css';

const { Content, Header } = Layout;

class AddEntry extends Component {
    static ABOUT = 'ENTRY/ABOUT';
    static SENTIMENT = 'ENTRY/SENTIMENT';
    static MEDIA = 'ENTRY/MEDIA';

    static propTypes = {
        entry: React.PropTypes.object
    }

    static defaultProps = {
        entry: {}
    }

    constructor (props) {
        super(props);

        this.state = {
            entry: props.entry,
            form: AddEntry.ABOUT,
            saving: false
        };

        const { ABOUT, SENTIMENT, MEDIA } = AddEntry;

        this.transitions = {
            [ABOUT]: (key, value) => {
                this.setEntryData(key, value);
                this.setState({
                    form: SENTIMENT
                });
            },
            [SENTIMENT]: (key, value) => {
                this.setEntryData(key, value);
                this.setState({
                    form: MEDIA
                });
            },
            [MEDIA]: (key, value) => {
                this.setEntryData(key, value, true);
            }
        };

        this.handleMediaTypeChange = this.handleMediaTypeChange.bind(this);
    }

    saveEntry (entry) {
        var creator = this.props.creator;

        var onSuccess = () => {
            this.setState({
                saving: false
            });

            this.props.router.push('/app/home');
        };

        this.setState({
            saving: true
        });

        this.props.relay.commitUpdate(
            new AddEntryMutation({
                creator,
                entry
            }),
            {
                onSuccess
            }
        );
    }

    setEntryData (key, value, save) {
        var entry = _.merge({}, this.state.entry, { [key]: value });

        this.setState({
            entry
        });

        if (save) {
            this.saveEntry(entry);
        }
    }

    handleMediaTypeChange (type) {
        this.setState({
            mediaType: type
        });
    }

    renderForm () {
        const { ABOUT, SENTIMENT, MEDIA } = AddEntry;

        switch (this.state.form) {
                default:
                case ABOUT:
                    return <TopicForm save={this.transitions[ABOUT]} topics={this.props.creator.topics} />;

                case SENTIMENT:
                    return <SentimentForm save={this.transitions[SENTIMENT]} />;

                case MEDIA:
                    return <MediaForm save={this.transitions[MEDIA]} onMediaTypeChange={this.handleMediaTypeChange} />;
        }
    }

    render () {
        return (
            <Layout className={styles.wrapper}>

                    {this.state.entry && (

                                {(this.state.entry.topics) ? (

                                        {this.state.entry.topics.map((topic, i) => (

                                                <Icon
                                                    icon={topic}
                                                    small={true}
                                                />

                                        ))}

                                ) : '1. Topic'}

                                {(this.state.entry.sentiment) ? (
                                    <Icon
                                        icon={this.state.entry.sentiment}
                                        small={true}
                                    />
                                ) : '2. Sentiment'}

                                {(this.state.mediaType) ? (
                                    <Icon
                                        icon={this.state.mediaType}
                                        small={true}
                                    />
                                ) : '3. Media type'}

                    )}

                <Content>
                    {this.state.saving && <PageOverlay title='Saving.' />}
                    {this.renderForm()}
                </Content>
            </Layout>
        );
    }
};

// AddEntry = withRouter(AddEntry);

export default withRouter(AddEntry);

export const AddEntryContainer = Relay.createContainer(withRoles(withRouter(AddEntry), ['creator']), {
    fragments: {
        user: () => Relay.QL`
        fragment on User {
                ${userFragment}
        }`,
        creator: () => Relay.QL`
            fragment on Creator {
                id
                topics {
                    type,
                    name
                }
                ${AddEntryMutation.getFragment('creator')}
            }
        `
    }
});
<commit_msg>Fix loading modal not appearing instantly on save<commit_after>import React, { Component } from 'react';
import Relay from 'react-relay';
import _ from 'lodash';
import { withRouter } from 'react-router';

import Layout from './Layout';
import Icon from './Icon';
import AddEntryMutation from './mutations/AddEntryMutation';
import { withRoles, userFragment } from './wrappers.js';

import TopicForm from './TopicForm';
import SentimentForm from './SentimentForm';
import MediaForm from './MediaForm';
import PageOverlay from './PageOverlay';

import styles from './css/AddEntry.module.css';

const { Content, Header } = Layout;

class AddEntry extends Component {
    static ABOUT = 'ENTRY/ABOUT';
    static SENTIMENT = 'ENTRY/SENTIMENT';
    static MEDIA = 'ENTRY/MEDIA';

    static propTypes = {
        entry: React.PropTypes.object
    }

    static defaultProps = {
        entry: {}
    }

    constructor (props) {
        super(props);

        this.state = {
            entry: props.entry,
            form: AddEntry.ABOUT,
            saving: false
        };

        const { ABOUT, SENTIMENT, MEDIA } = AddEntry;

        this.transitions = {
            [ABOUT]: (key, value) => {
                this.setEntryData(key, value);
                this.setState({
                    form: SENTIMENT
                });
            },
            [SENTIMENT]: (key, value) => {
                this.setEntryData(key, value);
                this.setState({
                    form: MEDIA
                });
            },
            [MEDIA]: (key, value) => {
                this.setEntryData(key, value, true);
            }
        };

        this.handleMediaTypeChange = this.handleMediaTypeChange.bind(this);
    }

    saveEntry (entry) {
        var creator = this.props.creator;

        var onSuccess = () => {
            this.setState({
                saving: false
            });

            this.props.router.push('/app/home');
        };

        this.setState({
            saving: true
        }, () => {
            this.props.relay.commitUpdate(
                new AddEntryMutation({
                    creator,
                    entry
                }),
                {
                    onSuccess
                }
            );
        });
    }

    setEntryData (key, value, save) {
        var entry = _.merge({}, this.state.entry, { [key]: value });

        this.setState({
            entry
        });

        if (save) {
            this.saveEntry(entry);
        }
    }

    handleMediaTypeChange (type) {
        this.setState({
            mediaType: type
        });
    }

    renderForm () {
        const { ABOUT, SENTIMENT, MEDIA } = AddEntry;

        switch (this.state.form) {
                default:
                case ABOUT:
                    return <TopicForm save={this.transitions[ABOUT]} topics={this.props.creator.topics} />;

                case SENTIMENT:
                    return <SentimentForm save={this.transitions[SENTIMENT]} />;

                case MEDIA:
                    return <MediaForm save={this.transitions[MEDIA]} onMediaTypeChange={this.handleMediaTypeChange} />;
        }
    }

    render () {
        return (
            <Layout className={styles.wrapper}>

                    {this.state.entry && (

                                {(this.state.entry.topics) ? (

                                        {this.state.entry.topics.map((topic, i) => (

                                                <Icon
                                                    icon={topic}
                                                    small={true}
                                                />

                                        ))}

                                ) : '1. Topic'}

                                {(this.state.entry.sentiment) ? (
                                    <Icon
                                        icon={this.state.entry.sentiment}
                                        small={true}
                                    />
                                ) : '2. Sentiment'}

                                {(this.state.mediaType) ? (
                                    <Icon
                                        icon={this.state.mediaType}
                                        small={true}
                                    />
                                ) : '3. Media type'}

                    )}

                <Content>
                    {this.state.saving && <PageOverlay title='Saving.' />}
                    {this.renderForm()}
                </Content>
            </Layout>
        );
    }
};

// AddEntry = withRouter(AddEntry);

export default withRouter(AddEntry);

export const AddEntryContainer = Relay.createContainer(withRoles(withRouter(AddEntry), ['creator']), {
    fragments: {
        user: () => Relay.QL`
        fragment on User {
                ${userFragment}
        }`,
        creator: () => Relay.QL`
            fragment on Creator {
                id
                topics {
                    type,
                    name
                }
                ${AddEntryMutation.getFragment('creator')}
            }
        `
    }
});
<|endoftext|>