<commit_before>import {polyfill} from 'es6-promise';
polyfill();

import React from 'react';
import {PropTypes} from 'react';
import { Link } from 'react-router';
import CSSTransitionGroup from 'react/lib/ReactCSSTransitionGroup';

import humanize from 'string-humanize';
import 'isomorphic-fetch';

import Pattern from './index';
import PatternLoader from './pattern-loader';
import PatternDependencies from './pattern-dependencies';
import Headline from '../common/headline';
import Icon from '../common/icon';

import getAugmentedChildren from '../../utils/augment-hierarchy';

class PatternSection extends React.Component {
	displayName = 'PatternSection';
	state = { 'data': null, 'error': false, 'type': null };

	static propTypes = {
		'id': PropTypes.string.isRequired
	};

	async get(props) {
		let { navigation, id, config } = props;

		// check if this is a pattern or folder
		let splits = id.split('/');
		let last = splits.pop();

		let folder = splits.reduce((folder, pathItem) => folder[pathItem].children, navigation);
		let type = (folder && folder[last].type) || 'pattern';

		if (type == 'folder' && config.useFolderTable) {
			this.setState({ 'data': folder[last], 'error': false, 'type': 'folder' });
			return;
		}

		let url = `/api/pattern/${id}`;

		let response;
		let data;

		try {
			response = await fetch(url, { 'headers': {'Accept': 'application/json'}, 'credentials': 'include' });
		} catch (err) {
			this.setState({ 'data': null, 'error': true, 'type': null });
			this.props.eventEmitter.emit('error', `${err.message} ${url}`);
			return;
		}

		if (this.state.data !== null) {
			return;
		}

		try {
			if (response.status >= 400) {
				// Try to get a meaningfull error message
				let message;
				try {
					let data = await response.json();
					message = data.message || response.statusText;
				} catch(error) {
					message = `${response.statusText} ${url}`;
				}
				throw new Error(message);
			}
		} catch (error) {
			this.setState({ 'data': null, 'error': true, 'type': null });
			this.props.eventEmitter.emit('error', `${error.message}`);
			return;
		}

		try {
			data = await response.json();
			this.generateDependencyGraph(data);
		} catch (err) {
			this.setState({ 'data': null, 'error': true, 'type': null });
			this.props.eventEmitter.emit('error', `Could not parse data for ${url}`);
		}

		this.setState({ 'data': data, 'error': false, 'type': 'pattern' });
	}

  generateDependencyGraph(data) {<commit_msg>Fixed #13 where DependencyTab was only visible for single-pattern-view<commit_after>import {polyfill} from 'es6-promise';
polyfill();

import React from 'react';
import {PropTypes} from 'react';
import { Link } from 'react-router';
import CSSTransitionGroup from 'react/lib/ReactCSSTransitionGroup';

import humanize from 'string-humanize';
import 'isomorphic-fetch';

import Pattern from './index';
import PatternLoader from './pattern-loader';
import PatternDependencies from './pattern-dependencies';
import Headline from '../common/headline';
import Icon from '../common/icon';

import getAugmentedChildren from '../../utils/augment-hierarchy';

class PatternSection extends React.Component {
	displayName = 'PatternSection';
	state = { 'data': null, 'error': false, 'type': null };

	static propTypes = {
		'id': PropTypes.string.isRequired
	};

	async get(props) {
		let { navigation, id, config } = props;

		// check if this is a pattern or folder
		let splits = id.split('/');
		let last = splits.pop();

		let folder = splits.reduce((folder, pathItem) => folder[pathItem].children, navigation);
		let type = (folder && folder[last].type) || 'pattern';

		if (type == 'folder' && config.useFolderTable) {
			this.setState({ 'data': folder[last], 'error': false, 'type': 'folder' });
			return;
		}

		let url = `/api/pattern/${id}`;

		let response;
		let data;

		try {
			response = await fetch(url, { 'headers': {'Accept': 'application/json'}, 'credentials': 'include' });
		} catch (err) {
			this.setState({ 'data': null, 'error': true, 'type': null });
			this.props.eventEmitter.emit('error', `${err.message} ${url}`);
			return;
		}

		if (this.state.data !== null) {
			return;
		}

		try {
			if (response.status >= 400) {
				// Try to get a meaningfull error message
				let message;
				try {
					let data = await response.json();
					message = data.message || response.statusText;
				} catch(error) {
					message = `${response.statusText} ${url}`;
				}
				throw new Error(message);
			}
		} catch (error) {
			this.setState({ 'data': null, 'error': true, 'type': null });
			this.props.eventEmitter.emit('error', `${error.message}`);
			return;
		}

		try {
			data = await response.json();
			if(!Array.isArray(data)){
				data = [data];
			}
			data.forEach((item) => {
				this.generateDependencyGraph(item);
			});
		} catch (err) {
			this.setState({ 'data': null, 'error': true, 'type': null });
			this.props.eventEmitter.emit('error', `Could not parse data for ${url}`);
		}

		this.setState({ 'data': data, 'error': false, 'type': 'pattern' });
	}

  generateDependencyGraph(data) {
{'fraction_non_alphanumeric': 0.1745190420102081, 'fraction_numerical': 0.0019630938358853552, 'mean_word_length': 3.793038570084666, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5933440', 'n_tokens_mistral': 1801, 'n_tokens_neox': 1607, 'n_words': 440}