<commit_before>'use strict';

import React from 'react';
import PropTypes from 'prop-types';
import _ from 'underscore';
import { Button, Collapse, MenuItem, ButtonToolbar, DropdownButton } from 'react-bootstrap';
import Alerts from './../alerts';
import { JWT, console, object, ajax, layout, DateUtility, navigate } from './../util';
import { FormattedInfoBlock, HiGlassPlainContainer, ItemDetailList, CollapsibleItemViewButtonToolbar } from './components';
import { LinkToSelector } from './../forms/components';
import DefaultItemView, { OverViewBodyItem } from './DefaultItemView';

export default class HiGlassViewConfigView extends DefaultItemView {

    getTabViewContents(){

        var initTabs    = [],
            width       = this.getTabViewWidth();

        initTabs.push(HiGlassViewConfigTabView.getTabObject(this.props, width));

        return initTabs.concat(this.getCommonTabs());
    }

}



export class HiGlassViewConfigTabView extends React.PureComponent {

    static getTabObject(props, width){
        return {
            'tab' : <span><i className="icon icon-fw icon-television"/> HiGlass Browser</span>,
            'key' : 'higlass',
            'disabled' : false,
            'content' : <HiGlassViewConfigTabView {...props} width={width} />
        };
    }

    static defaultProps = {
        'isValidating' : false,
        'disabled' : false,
        'height' : 600
    };

    constructor(props){
        super(props);
        this.fullscreenButton = this.fullscreenButton.bind(this);
        this.saveButton = this.saveButton.bind(this);
        this.cloneButton = this.cloneButton.bind(this);
        this.getHiGlassComponent = this.getHiGlassComponent.bind(this);
        this.havePermissionToEdit = this.havePermissionToEdit.bind(this);
        this.handleSave = _.throttle(this.handleSave.bind(this), 3000);
        this.handleClone = _.throttle(this.handleClone.bind(this), 3000, { 'trailing' : false });
        this.handleStatusChangeToRelease = this.handleStatusChange.bind(this, 'released');
        this.handleStatusChange = this.handleStatusChange.bind(this);
        this.handleFullscreenToggle = this.handleFullscreenToggle.bind(this);
        this.addFileToHiglass = this.addFileToHiglass.bind(this);

        /**
         * @property {Object} viewConfig            The viewconf that is fed to HiGlassPlainContainer. (N.B.) HiGlassComponent may edit it in place during UI interactions.
         * @property {string} genome_assembly       Common genome assembly for all files/tracks of this viewconf.
         * @property {Object} originalViewConfig    Not currently used, but might eventually be used to compare against state.viewConfig to inform whether to enable save btn or not.
         * @property {boolean} saveLoading          True if AJAX request is en route to save Item.
         * @property {boolean} cloneLoading         True if AJAX request is en route to clone Item.
         * @property {boolean} releaseLoading       True if AJAX request is en route to change Item status.
         * @property {boolean} addFileLoading          True if AJAX request is en route to add file to `state.viewConfig`.
         */
        this.state = {
            'viewConfig'            : props.context && props.context.viewconfig,
            'genome_assembly'       : (props.context && props.context.genome_assembly) || null,
            'originalViewConfig'    : null, //object.deepClone(props.viewConfig)
            'saveLoading'           : false,
            'cloneLoading'          : false,
            'releaseLoading'        : false,
            'addFileLoading'        : false
        };

        this.higlassRef = React.createRef();
    }

    UNSAFE_componentWillReceiveProps(nextProps){
        var nextState = {};

        /*  Below code:
            We no longer change viewConfig if receive new one from back-end because
            backend will always deliver new object reference.

        if (nextProps.viewConfig !== this.props.viewConfig){
            console.warn('NEW VIEWCONF!');
            _.extend(nextState, {
                'originalViewConfig' : null, //object.deepClone(nextProps.viewConfig) // Not currently used.
                'viewConfig' : nextProps.viewConfig,
                'genome_assembly' : (nextProps.context && nextProps.context.genome_assembly) || this.state.genome_assembly || null
            });
        }
        */

        // TODO: think about different (non-componentWillReceiveProps) approaches to this - perhaps simply
        // componentDidUpdate (?) now that we don't swap out state.viewConfig with nextProps.viewConfig.
        if ((nextProps.href !== this.props.href || nextProps.context !== this.props.context) && object.itemUtil.atId(nextProps.context) === object.itemUtil.atId(this.props.context)){
            // If component is still same instance, then is likely that we're changing
            // the URI hash as a consequence of changing tabs --or-- reloading current context due to change in session, etc.
            // Export & save viewConfig from HiGlassComponent internal state to our own to preserve contents.
            var hgc                 = this.getHiGlassComponent(),
                currentViewConfStr  = hgc && hgc.api.exportAsViewConfString(),
                currentViewConf     = currentViewConfStr && JSON.parse(currentViewConfStr);

            currentViewConf && _.extend(nextState, {
                'viewConfig' : currentViewConf
            });
        }

        if (_.keys(nextState).length > 0){
            this.setState(nextState);<commit_msg>Undoing HiGlass edits, adding comments<commit_after>'use strict';

import React from 'react';
import PropTypes from 'prop-types';
import _ from 'underscore';
import { Button, Collapse, MenuItem, ButtonToolbar, DropdownButton } from 'react-bootstrap';
import Alerts from './../alerts';
import { JWT, console, object, ajax, layout, DateUtility, navigate } from './../util';
import { FormattedInfoBlock, HiGlassPlainContainer, ItemDetailList, CollapsibleItemViewButtonToolbar } from './components';
import { LinkToSelector } from './../forms/components';
import DefaultItemView, { OverViewBodyItem } from './DefaultItemView';

export default class HiGlassViewConfigView extends DefaultItemView {

    getTabViewContents(){

        var initTabs    = [],
            width       = this.getTabViewWidth();

        initTabs.push(HiGlassViewConfigTabView.getTabObject(this.props, width));

        return initTabs.concat(this.getCommonTabs());
    }

}



export class HiGlassViewConfigTabView extends React.PureComponent {

    static getTabObject(props, width){
        return {
            'tab' : <span><i className="icon icon-fw icon-television"/> HiGlass Browser</span>,
            'key' : 'higlass',
            'disabled' : false,
            'content' : <HiGlassViewConfigTabView {...props} width={width} />
        };
    }

    static defaultProps = {
        'isValidating' : false,
        'disabled' : false,
        'height' : 600
    };

    constructor(props){
        super(props);
        this.fullscreenButton = this.fullscreenButton.bind(this);
        this.saveButton = this.saveButton.bind(this);
        this.cloneButton = this.cloneButton.bind(this);
        this.getHiGlassComponent = this.getHiGlassComponent.bind(this);
        this.havePermissionToEdit = this.havePermissionToEdit.bind(this);
        this.handleSave = _.throttle(this.handleSave.bind(this), 3000);
        this.handleClone = _.throttle(this.handleClone.bind(this), 3000, { 'trailing' : false });
        this.handleStatusChangeToRelease = this.handleStatusChange.bind(this, 'released');
        this.handleStatusChange = this.handleStatusChange.bind(this);
        this.handleFullscreenToggle = this.handleFullscreenToggle.bind(this);
        this.addFileToHiglass = this.addFileToHiglass.bind(this);

        /**
         * @property {Object} viewConfig            The viewconf that is fed to HiGlassPlainContainer. (N.B.) HiGlassComponent may edit it in place during UI interactions.
         * @property {string} genome_assembly       Common genome assembly for all files/tracks of this viewconf.
         * @property {Object} originalViewConfig    Not currently used, but might eventually be used to compare against state.viewConfig to inform whether to enable save btn or not.
         * @property {boolean} saveLoading          True if AJAX request is en route to save Item.
         * @property {boolean} cloneLoading         True if AJAX request is en route to clone Item.
         * @property {boolean} releaseLoading       True if AJAX request is en route to change Item status.
         * @property {boolean} addFileLoading          True if AJAX request is en route to add file to `state.viewConfig`.
         */
        this.state = {
            'viewConfig'            : props.context && props.context.viewconfig,
            'genome_assembly'       : (props.context && props.context.genome_assembly) || null,
            'originalViewConfig'    : null, //object.deepClone(props.viewConfig)
            'saveLoading'           : false,
            'cloneLoading'          : false,
            'releaseLoading'        : false,
            'addFileLoading'        : false
        };

        this.higlassRef = React.createRef();
    }


    /**
     * @todo
     * Think about different (non-componentWillReceiveProps) approaches to this - perhaps simply
     * componentDidUpdate (?) now that we don't swap out state.viewConfig with nextProps.viewConfig.
     * -- After cleanup.
     */
    UNSAFE_componentWillReceiveProps(nextProps){
        var nextState = {};

        /*  Below code:
            We will likely adjust/remove to no longer change viewConfig if receive new one from back-end because
            backend will always deliver new object reference. Even if same context['@id'] and context.date_modified.
        */

        if (nextProps.viewConfig !== this.props.viewConfig){
            _.extend(nextState, {
                'originalViewConfig' : null, //object.deepClone(nextProps.viewConfig) // Not currently used.
                'viewConfig'         : nextProps.viewConfig,
                'genome_assembly'    : (nextProps.context && nextProps.context.genome_assembly) || this.state.genome_assembly || null
            });
        }

        if (nextProps.href !== this.props.href && object.itemUtil.atId(nextProps.context) === object.itemUtil.atId(this.props.context)){
            // If component is still same instance, then is likely that we're changing
            // the URI hash as a consequence of changing tabs --or-- reloading current context due to change in session, etc.
            // Export & save viewConfig from HiGlassComponent internal state to our own to preserve contents.
            var hgc                 = this.getHiGlassComponent(),
                currentViewConfStr  = hgc && hgc.api.exportAsViewConfString(),
                currentViewConf     = currentViewConfStr && JSON.parse(currentViewConfStr);

            currentViewConf && _.extend(nextState, {
                'viewConfig' : currentViewConf
            });
        }

        if (_.keys(nextState).length > 0){
            this.setState(nextState);
{'fraction_non_alphanumeric': 0.10122535961640916, 'fraction_numerical': 0.002131060202450719, 'mean_word_length': 2.5251956181533646, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1218459', 'n_tokens_mistral': 3012, 'n_tokens_neox': 2910, 'n_words': 791}