<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { Box } from '../box';
import { IconButton } from '../button';
import {
  IconArrowLeftMediumOutline,
  IconArrowRightMediumOutline,
  IconArrowLeftSmallOutline,
  IconArrowRightSmallOutline,
} from '@teamleader/ui-icons';

const NavigationBar = ({ nextMonth, previousMonth, onPreviousClick, onNextClick, className, localeUtils, size }) => {
  const months = localeUtils.getMonths();
  const previousMonthButtonLabel = months[previousMonth.getMonth()];
  const nextMonthButtonLabel = months[nextMonth.getMonth()];

  return (
    <Box className={className} display="flex" justifyContent="space-between">
      <IconButton
        icon={size === 'large' ? <IconArrowLeftMediumOutline /> : <IconArrowLeftSmallOutline />}
        onClick={() => onPreviousClick()}
        title={previousMonthButtonLabel}
      />
      <IconButton
        icon={size === 'large' ? <IconArrowRightMediumOutline /> : <IconArrowRightSmallOutline />}
        onClick={() => onNextClick()}
        title={nextMonthButtonLabel}
      />
    </Box>
  );
};

NavigationBar.propTypes = {
  className: PropTypes.string,
  localeUtils: PropTypes.object,
  nextMonth: PropTypes.instanceOf(Date),
  previousMonth: PropTypes.instanceOf(Date),
  onNextClick: PropTypes.func,
  onPreviousClick: PropTypes.func,
  size: PropTypes.oneOf(['small', 'medium', 'large']),
};

export default NavigationBar;
<commit_msg>Convert functional component to class extending PureComponent<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Box } from '../box';
import { IconButton } from '../button';
import {
  IconArrowLeftMediumOutline,
  IconArrowRightMediumOutline,
  IconArrowLeftSmallOutline,
  IconArrowRightSmallOutline,
} from '@teamleader/ui-icons';

class NavigationBar extends PureComponent {
	handlePreviousClick = () => {
		this.props.onPreviousClick();
	};

	handleNextClick = () => {
		this.props.onNextClick();
	};

  render() {
		const {
			className,
			localeUtils,
		  nextMonth,
      previousMonth,
      size
		} = this.props;

    const months = localeUtils.getMonths();
    const previousMonthButtonLabel = months[previousMonth.getMonth()];
    const nextMonthButtonLabel = months[nextMonth.getMonth()];

    return (
      <Box className={className} display="flex" justifyContent="space-between">
        <IconButton
          icon={size === 'large' ? <IconArrowLeftMediumOutline /> : <IconArrowLeftSmallOutline />}
          onClick={this.handlePreviousClick}
          title={previousMonthButtonLabel}
        />
        <IconButton
          icon={size === 'large' ? <IconArrowRightMediumOutline /> : <IconArrowRightSmallOutline />}
          onClick={this.handleNextClick}
          title={nextMonthButtonLabel}
        />
      </Box>
    );
	}
}

NavigationBar.propTypes = {
  className: PropTypes.string,
  localeUtils: PropTypes.object,
  nextMonth: PropTypes.instanceOf(Date),
  previousMonth: PropTypes.instanceOf(Date),
  onNextClick: PropTypes.func,
  onPreviousClick: PropTypes.func,
  size: PropTypes.oneOf(['small', 'medium', 'large']),
};

export default NavigationBar;
<|endoftext|>


<commit_before>(function ( window , undefined ) {
    'use strict';
    var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.oIndexedDB || window.msIndexedDB,
        IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange,
        transactionModes = {
            readonly: 'readonly',
            readwrite: 'readwrite'
        };

    var hasOwn = Object.prototype.hasOwnProperty;

    if ( !indexedDB ) {
        throw 'IndexedDB required';
    }

    var CallbackList = function () {
        var state,
            list = [];

        var exec = function ( context , args ) {
            if ( list ) {
                args = args || [];
                state = state || [ context , args ];

                for ( var i = 0 , il = list.length ; i < il ; i++ ) {
                    list[ i ].apply( state[ 0 ] , state[ 1 ] );
                }

                list = [];
            }
        };

        this.add = function () {
            for ( var i = 0 , il = arguments.length ; i < il ; i ++ ) {
                list.push( arguments[ i ] );
            }

            if ( state ) {
                exec();
            }

            return this;
        };

        this.execute = function () {
            exec( this , arguments );
            return this;
        };
    };

    var Deferred = function ( func ) {
        var state = 'progress',
            actions = [
                [ 'resolve' , 'done' , new CallbackList() , 'resolved' ],
                [ 'reject' , 'fail' , new CallbackList() , 'rejected' ],
                [ 'notify' , 'progress' , new CallbackList() ],
            ],
            deferred = {},
            promise = {
                state: function () {
                    return state;
                },
                then: function ( /* doneHandler , failedHandler , progressHandler */ ) {
                    var handlers = arguments;

                    return Deferred(function ( newDefer ) {
                        actions.forEach(function ( action , i ) {
                            var handler = handlers[ i ];

                            deferred[ action[ 1 ] ]( typeof handler === 'function' ?
                                function () {
                                    var returned = handler.apply( this , arguments );

                                    if ( returned && typeof returned.promise === 'function' ) {
                                        returned.promise()
                                            .done( newDefer.resolve )
                                            .fail( newDefer.reject )
                                            .progress( newDefer.notify );
                                    }
                                } : newDefer[ action[ 0 ] ]
                            );
                        });
                    }).promise();
                },
                promise: function ( obj ) {
                    if ( obj ) {
                        Object.keys( promise )
                            .forEach(function ( key ) {
                                obj[ key ] = promise[ key ];
                            });

                        return obj;
                    }
                    return promise;
                }
            };

        actions.forEach(function ( action , i ) {
            var list = action[ 2 ],
                actionState = action[ 3 ];

            promise[ action[ 1 ] ] = list.add;

            if ( actionState ) {
                list.add(function () {
                    state = actionState;
                });
            }

            deferred[ action[ 0 ] ] = list.execute;
        });

        promise.promise( deferred );

        if ( func ) {
            func.call( deferred , deferred );
        }

        return deferred;
    };

    var Server = function ( db , name ) {
        var that = this,
            closed = false;

        this.add = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            for (var i = 0; i < arguments.length - 1; i++) {
                records[i] = arguments[i + 1];
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                deferred = Deferred();

            records.forEach( function ( record ) {
                var req;
                if ( record.item && record.key ) {
                    var key = record.key;
                    record = record.item;
                    req = store.add( record , key );
                } else {
                    req = store.add( record );
                }

                req.onsuccess = function ( e ) {
                    var target = e.target;
                    var keyPath = target.source.keyPath;
                    if ( keyPath === null ) {
                        keyPath = '__id__';
                    }
                    Object.defineProperty( record , keyPath , {
                        value: target.result,
                        enumerable: true
                    });
                    deferred.notify();
                };
            } );

            transaction.oncomplete = function () {
                deferred.resolve( records , that );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( records , e );
            };
            transaction.onabort = function ( e ) {
                deferred.reject( records , e );
            };
            return deferred.promise();
        };

        this.update = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            for ( var i = 0 ; i < arguments.length - 1 ; i++ ) {
                records[ i ] = arguments[ i + 1 ];
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                keyPath = store.keyPath,
                deferred = Deferred();

            records.forEach( function ( record ) {
                var req;
                if ( record.item && record.key ) {
                    var key = record.key;
                    record = record.item;
                    req = store.put( record , key );
                } else {
                    req = store.put( record );
                }

                req.onsuccess = function ( e ) {
                    deferred.notify();
                };
            } );

            transaction.oncomplete = function () {
                deferred.resolve( records , that );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( records , e );
            };
            transaction.onabort = function ( e ) {
                deferred.reject( records , e );
            };
            return deferred.promise();
        };

        this.remove = function ( table , key ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                deferred = Deferred();

            var req = store.delete( key );
            transaction.oncomplete = function ( ) {
                deferred.resolve( key );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( e );
            };
            return deferred.promise();
        };

        this.close = function ( ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            db.close();
            closed = true;
            delete dbCache[ name ];
        };

        this.get = function ( table , id ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table ),
                store = transaction.objectStore( table ),
                deferred = Deferred();

            var req = store.get( id );
            req.onsuccess = function ( e ) {
                deferred.resolve( e.target.result );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( e );
            };
            return deferred.promise();
        };

        this.query = function ( table , index ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            return new IndexQuery( table , db , index );
        };

        for ( var i = 0 , il = db.objectStoreNames.length ; i < il ; i++ ) {
            (function ( storeName ) {
                that[ storeName ] = { };
                for ( var i in that ) {
                    if ( !hasOwn.call( that , i ) || i === 'close' ) {
                        continue;
                    }
                    that[ storeName ][ i ] = (function ( i ) {
                        return function () {
                            var args = [ storeName ].concat( [].slice.call( arguments , 0 ) );
                            return that[ i ].apply( that , args );
                        };
                    })( i );
                }
            })( db.objectStoreNames[ i ] );
        }
    };

    var IndexQuery = function ( table , db , indexName ) {
        var that = this;
        var modifyObj = false;

        var runQuery = function ( type, args , cursorType , direction ) {
            var transaction = db.transaction( table, modifyObj ? transactionModes.readwrite : transactionModes.readonly ),
                store = transaction.objectStore( table ),
                index = indexName ? store.index( indexName ) : store,
                keyRange = type ? IDBKeyRange[ type ].apply( null, args ) : null,
                results = [],
                deferred = Deferred(),
                indexArgs = [ keyRange ];

            if ( cursorType !== 'count' ) {
                indexArgs.push( direction || 'next' );
            };

            // create a function that will set in the modifyObj properties into
            // the passed record.
            var modifyKeys = modifyObj ? Object.keys(modifyObj) : false;
            var modifyRecord = function(record) {
                for(var i = 0; i < modifyKeys.length; i++) {
                    var key = modifyKeys[i];
                    var val = modifyObj[key];
                    if(val instanceof Function) val = val(record);
                    console.log('new val: ', val);
                    record[key] = val;
                }
                return record;
            };

            index[cursorType].apply( index , indexArgs ).onsuccess = function ( e ) {
                var cursor = e.target.result;

                if ( typeof cursor === typeof 0 ) {
                    results = cursor;
                } else if ( cursor ) {
                    var val = 'value' in cursor ? cursor.value : cursor.key;
                    results.push(val);

                    // if we're doing a modify, run it now
                    if(modifyObj)
                    {
                        val = modifyRecord(val);
                        cursor.update(val);
                    }
                    cursor.continue();
                }
            };

            transaction.oncomplete = function () {
                deferred.resolve( results );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( e );
            };
            transaction.onabort = function ( e ) {
                deferred.reject( e );
            };
            return deferred.promise();
        };

        var Query = function ( type , args ) {
            var direction = 'next',
                cursorType = 'openCursor',
                filters = [],
                unique = false;

            var execute = function () {
                var deferred = Deferred();

                runQuery( type , args , cursorType , unique ? direction + 'unique' : direction )
                    .then( function ( data ) {
                        if ( data.constructor === Array ) {
                            filters.forEach( function ( filter ) {
                                if ( !filter || !filter.length ) {
                                    return;
                                }

                                if ( filter.length === 2 ) {
                                    data = data.filter( function ( x ) {
                                        return x[ filter[ 0 ] ] === filter[ 1 ];
                                    });
                                } else {
                                    data = data.filter( filter[ 0 ] );
                                }
                            });
                        }
                        deferred.resolve( data );
                    }, deferred.reject , deferred.notify );
                ;

                return deferred.promise();
            };
            var count = function () {
                direction = null;
                cursorType = 'count';

                return {
                    execute: execute
                };
            };
            var keys = function () {
                cursorType = 'openKeyCursor';

                return {
                    desc: desc,
                    execute: execute,
                    filter: filter,
                    distinct: distinct
                };
            };
            var filter = function ( ) {
                filters.push( Array.prototype.slice.call( arguments , 0 , 2 ) );

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    distinct: distinct,
                    modify: modify
                };
            };
            var desc = function () {
                direction = 'prev';

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    distinct: distinct,
                    modify: modify
                };
            };
            var distinct = function () {
                unique = true;
                return {
                    keys: keys,
                    count: count,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    modify: modify
                };
            };
            var modify = function(update) {
                modifyObj = update;
                return {
                    execute: execute
                };
            };

            return {
                execute: execute,
                count: count,
                keys: keys,
                filter: filter,
                desc: desc,
                distinct: distinct,
                modify: modify
            };
        };

        'only bound upperBound lowerBound'.split(' ').forEach(function (name) {
            that[name] = function () {
                return new Query( name , arguments );
            };
        });

        this.filter = function () {
            var query = new Query( null , null );
            return query.filter.apply( query , arguments );
        };

        this.all = function () {
            return this.filter();
        };
    };

    var createSchema = function ( e , schema , db ) {
        if ( typeof schema === 'function' ) {
            schema = schema();
        }

        for ( var tableName in schema ) {
            var table = schema[ tableName ];
            if ( !hasOwn.call( schema , tableName ) || db.objectStoreNames.contains( tableName ) ) {
                continue;
            }

            var store = db.createObjectStore( tableName , table.key );

            for ( var indexKey in table.indexes ) {
                var index = table.indexes[ indexKey ];
                store.createIndex( indexKey , index.key || indexKey , Object.keys(index).length ? index : { unique: false } );
            }
        }
    };

    var open = function ( e , server , version , schema ) {
        var db = e.target.result;
        var s = new Server( db , server );
        var upgrade;

        var deferred = Deferred();
        deferred.resolve( s );
        dbCache[ server ] = db;

        return deferred.promise();
    };

    var dbCache = {};

    var db = {
        version: '0.8.0',
        open: function ( options ) {
            var request;

            var deferred = Deferred();

            if ( dbCache[ options.server ] ) {
                open( {
                    target: {
                        result: dbCache[ options.server ]
                    }
                } , options.server , options.version , options.schema )
                .done(deferred.resolve)
                .fail(deferred.reject)
                .progress(deferred.notify);
            } else {
                request = indexedDB.open( options.server , options.version );

                request.onsuccess = function ( e ) {
                    open( e , options.server , options.version , options.schema )
                        .done(deferred.resolve)
                        .fail(deferred.reject)
                        .progress(deferred.notify);
                };

                request.onupgradeneeded = function ( e ) {
                    createSchema( e , options.schema , e.target.result );
                };
                request.onerror = function ( e ) {
                    deferred.reject( e );
                };
            }

            return deferred.promise();
        }
    };
    if ( typeof define === 'function' && define.amd ) {
        define( function() { return db; } );
    } else {
        window.db = db;
    }
})( window );
<commit_msg>removing console.log (oops)<commit_after>(function ( window , undefined ) {
    'use strict';
    var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.oIndexedDB || window.msIndexedDB,
        IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange,
        transactionModes = {
            readonly: 'readonly',
            readwrite: 'readwrite'
        };

    var hasOwn = Object.prototype.hasOwnProperty;

    if ( !indexedDB ) {
        throw 'IndexedDB required';
    }

    var CallbackList = function () {
        var state,
            list = [];

        var exec = function ( context , args ) {
            if ( list ) {
                args = args || [];
                state = state || [ context , args ];

                for ( var i = 0 , il = list.length ; i < il ; i++ ) {
                    list[ i ].apply( state[ 0 ] , state[ 1 ] );
                }

                list = [];
            }
        };

        this.add = function () {
            for ( var i = 0 , il = arguments.length ; i < il ; i ++ ) {
                list.push( arguments[ i ] );
            }

            if ( state ) {
                exec();
            }

            return this;
        };

        this.execute = function () {
            exec( this , arguments );
            return this;
        };
    };

    var Deferred = function ( func ) {
        var state = 'progress',
            actions = [
                [ 'resolve' , 'done' , new CallbackList() , 'resolved' ],
                [ 'reject' , 'fail' , new CallbackList() , 'rejected' ],
                [ 'notify' , 'progress' , new CallbackList() ],
            ],
            deferred = {},
            promise = {
                state: function () {
                    return state;
                },
                then: function ( /* doneHandler , failedHandler , progressHandler */ ) {
                    var handlers = arguments;

                    return Deferred(function ( newDefer ) {
                        actions.forEach(function ( action , i ) {
                            var handler = handlers[ i ];

                            deferred[ action[ 1 ] ]( typeof handler === 'function' ?
                                function () {
                                    var returned = handler.apply( this , arguments );

                                    if ( returned && typeof returned.promise === 'function' ) {
                                        returned.promise()
                                            .done( newDefer.resolve )
                                            .fail( newDefer.reject )
                                            .progress( newDefer.notify );
                                    }
                                } : newDefer[ action[ 0 ] ]
                            );
                        });
                    }).promise();
                },
                promise: function ( obj ) {
                    if ( obj ) {
                        Object.keys( promise )
                            .forEach(function ( key ) {
                                obj[ key ] = promise[ key ];
                            });

                        return obj;
                    }
                    return promise;
                }
            };

        actions.forEach(function ( action , i ) {
            var list = action[ 2 ],
                actionState = action[ 3 ];

            promise[ action[ 1 ] ] = list.add;

            if ( actionState ) {
                list.add(function () {
                    state = actionState;
                });
            }

            deferred[ action[ 0 ] ] = list.execute;
        });

        promise.promise( deferred );

        if ( func ) {
            func.call( deferred , deferred );
        }

        return deferred;
    };

    var Server = function ( db , name ) {
        var that = this,
            closed = false;

        this.add = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            for (var i = 0; i < arguments.length - 1; i++) {
                records[i] = arguments[i + 1];
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                deferred = Deferred();

            records.forEach( function ( record ) {
                var req;
                if ( record.item && record.key ) {
                    var key = record.key;
                    record = record.item;
                    req = store.add( record , key );
                } else {
                    req = store.add( record );
                }

                req.onsuccess = function ( e ) {
                    var target = e.target;
                    var keyPath = target.source.keyPath;
                    if ( keyPath === null ) {
                        keyPath = '__id__';
                    }
                    Object.defineProperty( record , keyPath , {
                        value: target.result,
                        enumerable: true
                    });
                    deferred.notify();
                };
            } );

            transaction.oncomplete = function () {
                deferred.resolve( records , that );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( records , e );
            };
            transaction.onabort = function ( e ) {
                deferred.reject( records , e );
            };
            return deferred.promise();
        };

        this.update = function( table ) {
            if ( closed ) {
                throw 'Database has been closed';
            }

            var records = [];
            for ( var i = 0 ; i < arguments.length - 1 ; i++ ) {
                records[ i ] = arguments[ i + 1 ];
            }

            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                keyPath = store.keyPath,
                deferred = Deferred();

            records.forEach( function ( record ) {
                var req;
                if ( record.item && record.key ) {
                    var key = record.key;
                    record = record.item;
                    req = store.put( record , key );
                } else {
                    req = store.put( record );
                }

                req.onsuccess = function ( e ) {
                    deferred.notify();
                };
            } );

            transaction.oncomplete = function () {
                deferred.resolve( records , that );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( records , e );
            };
            transaction.onabort = function ( e ) {
                deferred.reject( records , e );
            };
            return deferred.promise();
        };

        this.remove = function ( table , key ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table , transactionModes.readwrite ),
                store = transaction.objectStore( table ),
                deferred = Deferred();

            var req = store.delete( key );
            transaction.oncomplete = function ( ) {
                deferred.resolve( key );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( e );
            };
            return deferred.promise();
        };

        this.close = function ( ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            db.close();
            closed = true;
            delete dbCache[ name ];
        };

        this.get = function ( table , id ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            var transaction = db.transaction( table ),
                store = transaction.objectStore( table ),
                deferred = Deferred();

            var req = store.get( id );
            req.onsuccess = function ( e ) {
                deferred.resolve( e.target.result );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( e );
            };
            return deferred.promise();
        };

        this.query = function ( table , index ) {
            if ( closed ) {
                throw 'Database has been closed';
            }
            return new IndexQuery( table , db , index );
        };

        for ( var i = 0 , il = db.objectStoreNames.length ; i < il ; i++ ) {
            (function ( storeName ) {
                that[ storeName ] = { };
                for ( var i in that ) {
                    if ( !hasOwn.call( that , i ) || i === 'close' ) {
                        continue;
                    }
                    that[ storeName ][ i ] = (function ( i ) {
                        return function () {
                            var args = [ storeName ].concat( [].slice.call( arguments , 0 ) );
                            return that[ i ].apply( that , args );
                        };
                    })( i );
                }
            })( db.objectStoreNames[ i ] );
        }
    };

    var IndexQuery = function ( table , db , indexName ) {
        var that = this;
        var modifyObj = false;

        var runQuery = function ( type, args , cursorType , direction ) {
            var transaction = db.transaction( table, modifyObj ? transactionModes.readwrite : transactionModes.readonly ),
                store = transaction.objectStore( table ),
                index = indexName ? store.index( indexName ) : store,
                keyRange = type ? IDBKeyRange[ type ].apply( null, args ) : null,
                results = [],
                deferred = Deferred(),
                indexArgs = [ keyRange ];

            if ( cursorType !== 'count' ) {
                indexArgs.push( direction || 'next' );
            };

            // create a function that will set in the modifyObj properties into
            // the passed record.
            var modifyKeys = modifyObj ? Object.keys(modifyObj) : false;
            var modifyRecord = function(record) {
                for(var i = 0; i < modifyKeys.length; i++) {
                    var key = modifyKeys[i];
                    var val = modifyObj[key];
                    if(val instanceof Function) val = val(record);
                    record[key] = val;
                }
                return record;
            };

            index[cursorType].apply( index , indexArgs ).onsuccess = function ( e ) {
                var cursor = e.target.result;

                if ( typeof cursor === typeof 0 ) {
                    results = cursor;
                } else if ( cursor ) {
                    var val = 'value' in cursor ? cursor.value : cursor.key;
                    results.push(val);

                    // if we're doing a modify, run it now
                    if(modifyObj)
                    {
                        val = modifyRecord(val);
                        cursor.update(val);
                    }
                    cursor.continue();
                }
            };

            transaction.oncomplete = function () {
                deferred.resolve( results );
            };
            transaction.onerror = function ( e ) {
                deferred.reject( e );
            };
            transaction.onabort = function ( e ) {
                deferred.reject( e );
            };
            return deferred.promise();
        };

        var Query = function ( type , args ) {
            var direction = 'next',
                cursorType = 'openCursor',
                filters = [],
                unique = false;

            var execute = function () {
                var deferred = Deferred();

                runQuery( type , args , cursorType , unique ? direction + 'unique' : direction )
                    .then( function ( data ) {
                        if ( data.constructor === Array ) {
                            filters.forEach( function ( filter ) {
                                if ( !filter || !filter.length ) {
                                    return;
                                }

                                if ( filter.length === 2 ) {
                                    data = data.filter( function ( x ) {
                                        return x[ filter[ 0 ] ] === filter[ 1 ];
                                    });
                                } else {
                                    data = data.filter( filter[ 0 ] );
                                }
                            });
                        }
                        deferred.resolve( data );
                    }, deferred.reject , deferred.notify );
                ;

                return deferred.promise();
            };
            var count = function () {
                direction = null;
                cursorType = 'count';

                return {
                    execute: execute
                };
            };
            var keys = function () {
                cursorType = 'openKeyCursor';

                return {
                    desc: desc,
                    execute: execute,
                    filter: filter,
                    distinct: distinct
                };
            };
            var filter = function ( ) {
                filters.push( Array.prototype.slice.call( arguments , 0 , 2 ) );

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    distinct: distinct,
                    modify: modify
                };
            };
            var desc = function () {
                direction = 'prev';

                return {
                    keys: keys,
                    execute: execute,
                    filter: filter,
                    distinct: distinct,
                    modify: modify
                };
            };
            var distinct = function () {
                unique = true;
                return {
                    keys: keys,
                    count: count,
                    execute: execute,
                    filter: filter,
                    desc: desc,
                    modify: modify
                };
            };
            var modify = function(update) {
                modifyObj = update;
                return {
                    execute: execute
                };
            };

            return {
                execute: execute,
                count: count,
                keys: keys,
                filter: filter,
                desc: desc,
                distinct: distinct,
                modify: modify
            };
        };

        'only bound upperBound lowerBound'.split(' ').forEach(function (name) {
            that[name] = function () {
                return new Query( name , arguments );
            };
        });

        this.filter = function () {
            var query = new Query( null , null );
            return query.filter.apply( query , arguments );
        };

        this.all = function () {
            return this.filter();
        };
    };

    var createSchema = function ( e , schema , db ) {
        if ( typeof schema === 'function' ) {
            schema = schema();
        }

        for ( var tableName in schema ) {
            var table = schema[ tableName ];
            if ( !hasOwn.call( schema , tableName ) || db.objectStoreNames.contains( tableName ) ) {
                continue;
            }

            var store = db.createObjectStore( tableName , table.key );

            for ( var indexKey in table.indexes ) {
                var index = table.indexes[ indexKey ];
                store.createIndex( indexKey , index.key || indexKey , Object.keys(index).length ? index : { unique: false } );
            }
        }
    };

    var open = function ( e , server , version , schema ) {
        var db = e.target.result;
        var s = new Server( db , server );
        var upgrade;

        var deferred = Deferred();
        deferred.resolve( s );
        dbCache[ server ] = db;

        return deferred.promise();
    };

    var dbCache = {};

    var db = {
        version: '0.8.0',
        open: function ( options ) {
            var request;

            var deferred = Deferred();

            if ( dbCache[ options.server ] ) {
                open( {
                    target: {
                        result: dbCache[ options.server ]
                    }
                } , options.server , options.version , options.schema )
                .done(deferred.resolve)
                .fail(deferred.reject)
                .progress(deferred.notify);
            } else {
                request = indexedDB.open( options.server , options.version );

                request.onsuccess = function ( e ) {
                    open( e , options.server , options.version , options.schema )
                        .done(deferred.resolve)
                        .fail(deferred.reject)
                        .progress(deferred.notify);
                };

                request.onupgradeneeded = function ( e ) {
                    createSchema( e , options.schema , e.target.result );
                };
                request.onerror = function ( e ) {
                    deferred.reject( e );
                };
            }

            return deferred.promise();
        }
    };
    if ( typeof define === 'function' && define.amd ) {
        define( function() { return db; } );
    } else {
        window.db = db;
    }
})( window );
<|endoftext|>


<commit_before>Promise.resolve(document.getElementsByTagName('video')).then(videos => {
	if (typeof window.targetVideoSrc !== 'undefined') {
		const targetVideos = Array.from(videos).filter(video => {
			if (video.src === targetVideoSrc) return true;
			return Array.from(video.getElementsByTagName('source')).find(source => {
				return source.src === targetVideoSrc;
			});
		});
		return {videos, targetVideos};
	} else {
		return {videos, targetVideos: videos};
	}
}).then(({videos, targetVideos}) => {
	if (targetVideos.length === 1) return {videos, targetVideo: targetVideos[0]};
	if (targetVideos.length === 0) throw '対象<video>が存在しない';
	throw '対象<video>が複数存在';
}).then(({videos, targetVideo}) => {
	const video = targetVideo;

	// プレイヤーをクリックで再生/一時停止
	let nowPlaying = true;
	video.addEventListener('play', () => {
		nowPlaying = true;
	});
	video.addEventListener('pause', () => {
		nowPlaying = false;
	});
	const playPause = () => {
		if (nowPlaying) {
			video.pause();
		} else {
			video.play();
		}
	};
	video.addEventListener('click', playPause);

	// ホイールで音量変更
	// 下から40pxの領域ではシークする
	const seekAreaHeight = 40;
	const changeVolume = diff => {
		// volume: [0, 1]
		let vol = video.volume;
		vol += diff;
		vol = Math.min(vol, 1);
		vol = Math.max(vol, 0);
		video.volume = vol;
	};
	const seek = diff => {
		video.currentTime += diff;
	};
	video.addEventListener('wheel', evt => {
		evt.preventDefault();
		// 下方向へのスクロール: 正
		const toBottom = evt.deltaY > 0;
		const pxFromBottom = video.clientHeight - evt.offsetY;
		if (pxFromBottom < seekAreaHeight) {
			seek(5 * (toBottom ? 1 : -1));
		} else {
			changeVolume(0.1 * (toBottom ? -1 : 1));
		}
	});

	// ダブルクリックで最大化/最大化解除
	const isFullScreen = () => document.webkitIsFullScreen;
	const requestFullScreen = elem => elem.webkitRequestFullScreen();
	const cancelFullScreen = () => document.webkitCancelFullScreen();
	const toggleFullScreen = () => {
		// TODO: ダブルクリック時に一時停止・再生がされないようにする
		// 		（clickイベントの中でsetTimeoutを使ってうまくやる）
		if (isFullScreen()) {
			cancelFullScreen();
		} else {
			requestFullScreen(video);
		}
	};
	video.addEventListener('dblclick', toggleFullScreen);
	const WHEEL_BUTTON = 1;
	video.addEventListener('mouseup', evt => {
		if (evt.button === WHEEL_BUTTON) toggleFullScreen();
	});

	if (videos.length === 1) {
		// キーボードショートカット
		const shortcutFunctions = {};
		shortcutFunctions[' '] = playPause;
		shortcutFunctions['Enter'] = toggleFullScreen;
		shortcutFunctions['ArrowUp'] = () => changeVolume(0.1);
		shortcutFunctions['ArrowDown'] = () => changeVolume(-0.1);
		shortcutFunctions['ArrowRight'] = ({ctrl} = {}) => seek(ctrl ? 90 : 5);
		shortcutFunctions['ArrowLeft'] = ({ctrl} = {}) => seek(ctrl ? -90 : -5);
		document.body.addEventListener('keydown', evt => {
			const tagName = evt.target.tagName;
			if (tagName === 'TEXTAREA' || tagName === 'INPUT') return;
			const fn = shortcutFunctions[evt.key];
			if (fn) {
				evt.preventDefault();
				fn({
					ctrl: evt.ctrlKey,
				});
			}
		});
	}
});
<commit_msg>refactor: 未定義変数使用警告に対処<commit_after>Promise.resolve(document.getElementsByTagName('video')).then(videos => {
	const targetVideoSrc = window.targetVideoSrc;
	if (typeof targetVideoSrc !== 'undefined') {
		const targetVideos = Array.from(videos).filter(video => {
			if (video.src === targetVideoSrc) return true;
			return Array.from(video.getElementsByTagName('source')).find(source => {
				return source.src === targetVideoSrc;
			});
		});
		return {videos, targetVideos};
	} else {
		return {videos, targetVideos: videos};
	}
}).then(({videos, targetVideos}) => {
	if (targetVideos.length === 1) return {videos, targetVideo: targetVideos[0]};
	if (targetVideos.length === 0) throw '対象<video>が存在しない';
	throw '対象<video>が複数存在';
}).then(({videos, targetVideo}) => {
	const video = targetVideo;

	// プレイヤーをクリックで再生/一時停止
	let nowPlaying = true;
	video.addEventListener('play', () => {
		nowPlaying = true;
	});
	video.addEventListener('pause', () => {
		nowPlaying = false;
	});
	const playPause = () => {
		if (nowPlaying) {
			video.pause();
		} else {
			video.play();
		}
	};
	video.addEventListener('click', playPause);

	// ホイールで音量変更
	// 下から40pxの領域ではシークする
	const seekAreaHeight = 40;
	const changeVolume = diff => {
		// volume: [0, 1]
		let vol = video.volume;
		vol += diff;
		vol = Math.min(vol, 1);
		vol = Math.max(vol, 0);
		video.volume = vol;
	};
	const seek = diff => {
		video.currentTime += diff;
	};
	video.addEventListener('wheel', evt => {
		evt.preventDefault();
		// 下方向へのスクロール: 正
		const toBottom = evt.deltaY > 0;
		const pxFromBottom = video.clientHeight - evt.offsetY;
		if (pxFromBottom < seekAreaHeight) {
			seek(5 * (toBottom ? 1 : -1));
		} else {
			changeVolume(0.1 * (toBottom ? -1 : 1));
		}
	});

	// ダブルクリックで最大化/最大化解除
	const isFullScreen = () => document.webkitIsFullScreen;
	const requestFullScreen = elem => elem.webkitRequestFullScreen();
	const cancelFullScreen = () => document.webkitCancelFullScreen();
	const toggleFullScreen = () => {
		// TODO: ダブルクリック時に一時停止・再生がされないようにする
		// 		（clickイベントの中でsetTimeoutを使ってうまくやる）
		if (isFullScreen()) {
			cancelFullScreen();
		} else {
			requestFullScreen(video);
		}
	};
	video.addEventListener('dblclick', toggleFullScreen);
	const WHEEL_BUTTON = 1;
	video.addEventListener('mouseup', evt => {
		if (evt.button === WHEEL_BUTTON) toggleFullScreen();
	});

	if (videos.length === 1) {
		// キーボードショートカット
		const shortcutFunctions = {};
		shortcutFunctions[' '] = playPause;
		shortcutFunctions['Enter'] = toggleFullScreen;
		shortcutFunctions['ArrowUp'] = () => changeVolume(0.1);
		shortcutFunctions['ArrowDown'] = () => changeVolume(-0.1);
		shortcutFunctions['ArrowRight'] = ({ctrl} = {}) => seek(ctrl ? 90 : 5);
		shortcutFunctions['ArrowLeft'] = ({ctrl} = {}) => seek(ctrl ? -90 : -5);
		document.body.addEventListener('keydown', evt => {
			const tagName = evt.target.tagName;
			if (tagName === 'TEXTAREA' || tagName === 'INPUT') return;
			const fn = shortcutFunctions[evt.key];
			if (fn) {
				evt.preventDefault();
				fn({
					ctrl: evt.ctrlKey,
				});
			}
		});
	}
});
<|endoftext|>


<commit_before>const EXPORT = ["RemoteCommand"];

const NOP = new Function();

function RemoteCommand(type, options) {
    this.type = type;
    this.options = {
        timeout:    15,
        retryCount: 3
    };
    extend(this.options, options || {});
    this.xhr = null;
    this._timerId = 0;
    this.resetListeners(); // EventService
}

extend(RemoteCommand, {
    API_ENDPOINT: {
        edit                    : 'add.edit.json',
        tags                    : 'tags.json',
        entry                   : 'entry.json',
        information_html        : 'partial.information',
        delete_bookmark         : 'api.delete_bookmark.json',
        interesting             : 'api.interesting.json',
        not_interesting         : 'api.not_interesting.json',
        ignore                  : 'api.ignore.json',
        unignore                : 'api.unignore.json',
        ignoring                : 'api.ignoring.json',
        unfollow                : 'api.unfollow.json',
        follow                  : 'api.follow.json',
        following               : 'api.following.json',
        follow_suggest_ignore   : 'api.follow_suggest_ignore.json',
        unfollow_suggest_ignore : 'api.unfollow_suggest_ignore.json',

        // Alias
        delete                  : 'api.delete_bookmark.json'
    }
});

EventService.implement(RemoteCommand.prototype);

extend(RemoteCommand.prototype, {
    get url RC_get_url() {
        return "http://b.hatena.ne.jp/" + this.user.name + "/" +
               RemoteCommand.API_ENDPOINT[this.type];
    },

    get query RC_get_query() {
        let query = this.options.query || {};
        query.rks = this.user.rks;
        return query;
    },

    get user RC_get_user() this.options.user || User.user,

    execute: function RC_execute() {
        this.hook();
        this.xhr = net.post(this.url, method(this, 'onComplete'),
                            method(this, 'onError'), true, this.query);
        this.setTimeoutHandler();
    },

    onComplete: function RC_onComplete(xhr) {
        this.clearTimeoutHandler();
        let json = decodeJSON(xhr.responseText);
        (this.options.onComplete || NOP).call(this, json);
        this.dispatch("complete");
    },

    onError: function RC_onError() {
        this.clearTimeoutHandler();
        if (this.options.retryCount) {
            this.retry();
        } else {
            (this.options.onError || NOP).call(this);
            this.dispatch("error");
        }
    },

    retry: function RC_retry() {
        this.execute();
        this.options.retryCount--;
        this.dispatch("retry");
    },

    setTimeoutHandler: function RC_setTimeoutHandler() {
        this._timerId = setTimeout(function (self) {
            self.clearTimeoutHandler();
            self.xhr.abort();
            self.onError();
        }, this.options.timeout * 1000, this);
    },

    clearTimeoutHandler: function RC_clearTimeoutHandler() {
        if (this._timerId)
            clearTimeout(this._timerId);
        this._timerId = 0;
    },

    hook: function RC_hook() {
        let hookName =
            this.type.replace(/_(.)/g, function (m, c) c.toUpperCase()) + "Hook";
        if (hookName in this)
            this[hookName]();
    },

    editHook: function RC_editHook() {
        let bookmark = this.options.bookmark;
        if (this.options.query || !bookmark) return;
        let query = {
            url:     bookmark.url,
            comment: bookmark.comment
        };
        if (this.options.changeTitle && User.user.public)
            query.title = bookmark.title;
        this.options.query = query;
    },

    deleteHook: function RC_deleteHook() {
        let options = this.options;
        if (options.query || (!options.bookmark && !options.bookmarks))
            return;
        this.options.query = options.bookmark
            ? { url: options.bookmark.url }
            : { urllist: options.bookmarks.map(function (b) b.url).join("|") };
        let bookmarks = options.bookmarks || [options.bookmark];
        let onComplete = this.options.onComplete
        this.options.onComplete = function (result) {
            if (!result || !result.success) {
                this.onError();
                return;
            }
            if (onComplete)
                onComplete.apply(this, arguments);
            p('remove bookmarks', bookmarks.map(function (b) b.url).join("\n"));
            Model.Bookmark.deleteBookmarks(bookmarks);
        };
        this.options.onError = this.options.onError || function () {
            UIUtils.alertBookmarkError('delete', bookmarks);
        };
    }
});
<commit_msg>delete success<commit_after>const EXPORT = ["RemoteCommand"];

const NOP = new Function();

function RemoteCommand(type, options) {
    this.type = type;
    this.options = {
        timeout:    15,
        retryCount: 3
    };
    extend(this.options, options || {});
    this.xhr = null;
    this._timerId = 0;
    this.resetListeners(); // EventService
}

extend(RemoteCommand, {
    API_ENDPOINT: {
        edit                    : 'add.edit.json',
        tags                    : 'tags.json',
        entry                   : 'entry.json',
        information_html        : 'partial.information',
        delete_bookmark         : 'api.delete_bookmark.json',
        interesting             : 'api.interesting.json',
        not_interesting         : 'api.not_interesting.json',
        ignore                  : 'api.ignore.json',
        unignore                : 'api.unignore.json',
        ignoring                : 'api.ignoring.json',
        unfollow                : 'api.unfollow.json',
        follow                  : 'api.follow.json',
        following               : 'api.following.json',
        follow_suggest_ignore   : 'api.follow_suggest_ignore.json',
        unfollow_suggest_ignore : 'api.unfollow_suggest_ignore.json',

        // Alias
        delete                  : 'api.delete_bookmark.json'
    }
});

EventService.implement(RemoteCommand.prototype);

extend(RemoteCommand.prototype, {
    get url RC_get_url() {
        return "http://b.hatena.ne.jp/" + this.user.name + "/" +
               RemoteCommand.API_ENDPOINT[this.type];
    },

    get query RC_get_query() {
        let query = this.options.query || {};
        query.rks = this.user.rks;
        return query;
    },

    get user RC_get_user() this.options.user || User.user,

    execute: function RC_execute() {
        this.hook();
        this.xhr = net.post(this.url, method(this, 'onComplete'),
                            method(this, 'onError'), true, this.query);
        this.setTimeoutHandler();
    },

    onComplete: function RC_onComplete(xhr) {
        this.clearTimeoutHandler();
        let json = decodeJSON(xhr.responseText);
        (this.options.onComplete || NOP).call(this, json);
        this.dispatch("complete");
    },

    onError: function RC_onError() {
        this.clearTimeoutHandler();
        if (this.options.retryCount) {
            this.retry();
        } else {
            (this.options.onError || NOP).call(this);
            this.dispatch("error");
        }
    },

    retry: function RC_retry() {
        this.execute();
        this.options.retryCount--;
        this.dispatch("retry");
    },

    setTimeoutHandler: function RC_setTimeoutHandler() {
        this._timerId = setTimeout(function (self) {
            self.clearTimeoutHandler();
            self.xhr.abort();
            self.onError();
        }, this.options.timeout * 1000, this);
    },

    clearTimeoutHandler: function RC_clearTimeoutHandler() {
        if (this._timerId)
            clearTimeout(this._timerId);
        this._timerId = 0;
    },

    hook: function RC_hook() {
        let hookName =
            this.type.replace(/_(.)/g, function (m, c) c.toUpperCase()) + "Hook";
        if (hookName in this)
            this[hookName]();
    },

    editHook: function RC_editHook() {
        let bookmark = this.options.bookmark;
        if (this.options.query || !bookmark) return;
        let query = {
            url:     bookmark.url,
            comment: bookmark.comment
        };
        if (this.options.changeTitle && User.user.public)
            query.title = bookmark.title;
        this.options.query = query;
    },

    deleteHook: function RC_deleteHook() {
        let options = this.options;
        if (options.query || (!options.bookmark && !options.bookmarks))
            return;
        this.options.query = options.bookmark
            ? { url: options.bookmark.url }
            : { urllist: options.bookmarks.map(function (b) b.url).join("|") };
        let bookmarks = options.bookmarks || [options.bookmark];
        let onComplete = this.options.onComplete
        this.options.onComplete = function (result) {
            //if (!result || !result.success) {
            // サーバの success = 0 のときはすでにエントリーがないので、ローカル DB はけしとく
            if (!result) {
                this.onError();
                return;
            }
            if (onComplete)
                onComplete.apply(this, arguments);
            p('remove bookmarks', bookmarks.map(function (b) b.url).join("\n"));
            Model.Bookmark.deleteBookmarks(bookmarks);
        };
        this.options.onError = this.options.onError || function () {
            UIUtils.alertBookmarkError('delete', bookmarks);
        };
    }
});
<|endoftext|>


<commit_before>"use strict";

import React        from 'react';
import ReactDOM     from 'react-dom';
import TestUtils    from 'react/lib/ReactTestUtils';
import { Provider } from 'react-redux';
import Helper       from '../../../specs_support/helper';
import { Index }        from './index';
import { __RewireAPI__ as SidebarRewire } from './index';

const FakeSidebar = React.createClass({
  render(){
    return

;
  }
});

describe('index', function() {
  var result, subject;
  var props;

  beforeEach(()=>{
    SidebarRewire.__Rewire__('Sidebar', FakeSidebar);

    props = {
      loadContent: () => {},
      params: {}
    };
    result = TestUtils.renderIntoDocument(<Index {...props}>
Howdy
</Index>);
    subject = ReactDOM.findDOMNode(result);
  });

  afterEach(() => {
    SidebarRewire.__ResetDependency__('Sidebar');
  });

  it('renders the index', function() {
    expect(ReactDOM.findDOMNode(result)).toBeDefined();
  });
  it("renders children", () => {
    expect(subject.innerHTML).toContain('Howdy');
  });
});
<commit_msg>remove unused imports<commit_after>"use strict";

import React        from 'react';
import ReactDOM     from 'react-dom';
import TestUtils    from 'react/lib/ReactTestUtils';
import { Index }        from './index';
import { __RewireAPI__ as SidebarRewire } from './index';

const FakeSidebar = React.createClass({
  render(){
    return

;
  }
});

describe('index', function() {
  var result, subject;
  var props;

  beforeEach(()=>{
    SidebarRewire.__Rewire__('Sidebar', FakeSidebar);

    props = {
      loadContent: () => {},
      params: {}
    };
    result = TestUtils.renderIntoDocument(<Index {...props}>
Howdy
</Index>);
    subject = ReactDOM.findDOMNode(result);
  });

  afterEach(() => {
    SidebarRewire.__ResetDependency__('Sidebar');
  });

  it('renders the index', function() {
    expect(ReactDOM.findDOMNode(result)).toBeDefined();
  });
  it("renders children", () => {
    expect(subject.innerHTML).toContain('Howdy');
  });
});
<|endoftext|>


<commit_before>'use strict';

/* global DOM */
/* global CloudCmd */

const {
    Dialog,
    Images,
} = DOM;

const forEachKey = require('for-each-key/legacy');
const wraptile = require('wraptile/legacy');

const format = require('./format');

module.exports = (options) => (emitter) => {
    const {
        operation,
        callback,
        noContinue,
        from,
        to,
    } = options;

    let done;
    let lastError;

    const onAbort = wraptile(({emitter, operation}) => {
        emitter.abort();

        const msg = `${operation} aborted`;
        lastError = true;

        Dialog.alert(msg, {
            noCancel: true,
        });
    });

    const removeListener = emitter.removeListener.bind(emitter);
    const on = emitter.on.bind(emitter);

    const message = format(operation, from, to);
    const progress = Dialog.progress(message);

    progress.catch(onAbort({
        emitter,
        operation,
    }));

    const listeners = {
        progress: (value) => {
            done = value === 100;
            progress.setProgress(value);
        },

        end: () => {
            Images.hide();
            forEachKey(removeListener, listeners);

            if (lastError || done)
                callback();
        },

        error: (error) => {
            lastError = error;

            if (noContinue) {
                listeners.end(error);
                Dialog.alert(error);
                return;
            }

            Dialog.confirm(error + '\n Continue?')
                .then(() => {
                    emitter.continue();
                }, () => {
                    emitter.abort();
                });
        },
    };

    forEachKey(on, listeners);
};

<commit_msg>fix(operation) set-listeners: alert: noCancel -> cancel<commit_after>'use strict';

/* global DOM */
/* global CloudCmd */

const {
    Dialog,
    Images,
} = DOM;

const forEachKey = require('for-each-key/legacy');
const wraptile = require('wraptile/legacy');

const format = require('./format');

module.exports = (options) => (emitter) => {
    const {
        operation,
        callback,
        noContinue,
        from,
        to,
    } = options;

    let done;
    let lastError;

    const onAbort = wraptile(({emitter, operation}) => {
        emitter.abort();

        const msg = `${operation} aborted`;
        lastError = true;

        Dialog.alert(msg, {
            cancel: false,
        });
    });

    const removeListener = emitter.removeListener.bind(emitter);
    const on = emitter.on.bind(emitter);

    const message = format(operation, from, to);
    const progress = Dialog.progress(message);

    progress.catch(onAbort({
        emitter,
        operation,
    }));

    const listeners = {
        progress: (value) => {
            done = value === 100;
            progress.setProgress(value);
        },

        end: () => {
            Images.hide();
            forEachKey(removeListener, listeners);

            if (lastError || done)
                callback();
        },

        error: (error) => {
            lastError = error;

            if (noContinue) {
                listeners.end(error);
                Dialog.alert(error);
                return;
            }

            Dialog.confirm(error + '\n Continue?')
                .then(() => {
                    emitter.continue();
                }, () => {
                    emitter.abort();
                });
        },
    };

    forEachKey(on, listeners);
};

<|endoftext|>


<commit_before>
'use strict';

export const OUTPUT_CHANGED = 'OUTPUT_CHANGED'; // test
export const TESTS_STARTED = 'TESTS_STARTED'; // playerstatus, test
export const TESTS_FINISHED = 'TESTS_FINISHED'; // test
export const TESTS_FAILED = 'TESTS_FAILED'; // test
export const TESTS_PASSED = 'TESTS_PASSED'; // test

/* Given a list of test results, returns pass/fail status.*/

const getTestStatus = testResults => testResults.every(testResult => testResult.pass);

// TODO:
// possibly reduce the number of workers because spawning and setting up a worker takes time

const createTestWorker = (userCode, currChallenge, dispatch) =>
  new Promise(resolve => {
    const wk = new Worker('public/js/ww.bundle.js');
    wk.postMessage([userCode, currChallenge.toJS()]); // postMessage mangles the Immutable object, so it needs to be transformed into regular JS before sending over to worker.
    wk.onmessage = e => {
      resolve(e.data);
    };
  })
  .then(workerData => {
    dispatch(onOutputChange(workerData[0]));
    if (workerData.length > 1) {
      const testResults = workerData.slice(4); // to take into account the benchmark items
      const allTestsPassed = getTestStatus(testResults);

      if (allTestsPassed) {
        dispatch(actionTestsPassed());
        // call benchmark webworkers here:

        const benchmarkFnCall = workerData[3];
        if (benchmarkFnCall) {
          const benchmarkCode = workerData.slice(1, 3);
          const benchmarkTimes = createBenchmarkWorker(benchmarkCode, benchmarkFnCall)
            .then(data => console.log(data))
            .catch(err => console.error(err));
        }
      }
      else {
        dispatch(actionTestsFailed());
      }

      // Would it make sense to include this with passed/failed actions?
      dispatch(actionTestsFinished(testResults));
    }
  })
  .catch(err => { console.log(`Promise rejected: ${err}.`); });

const createBenchmarkWorker = (code, benchmarkFnCall) =>
  new Promise(resolve => {
    const wk = new Worker('public/js/wwBenchmark.bundle.js');
    wk.postMessage([code, benchmarkFnCall]);
    wk.onmessage = e => {
      resolve(e.data);
    };
  })
  .catch(err => console.error(err));

export function onOutputChange(newOutput) {
  return {
    type: OUTPUT_CHANGED,
    userOutput: newOutput
  };
}

/* Thunk action which runs the test cases against user code. */
export function runTests(userCode, currChallenge) {
  return dispatch => {
    dispatch(actionTestsStarted());

    // Eval user code inside worker
    // http://stackoverflow.com/questions/9020116/is-it-possible-to-restrict-the-scope-of-a-javascript-function/36255766#36255766
    createTestWorker(userCode, currChallenge, dispatch);
  };
}

/* Dispatched when a user starts running the tests.*/
export function actionTestsStarted () {
  return {
    type: TESTS_STARTED
  };
}

/* Dispatched when tests fail.*/
export function actionTestsPassed () {
  return {
    type: TESTS_PASSED
  };
}

/* Dispatched when tests fail.*/
export function actionTestsFailed () {
  return {
    type: TESTS_FAILED
  };
}

/* Dispatched when the tests finish. */
export function actionTestsFinished (testResults) {
  return {
    type: TESTS_FINISHED,
    testResults
  };
}
<commit_msg>add statistical confidence output<commit_after>
'use strict';

export const OUTPUT_CHANGED = 'OUTPUT_CHANGED'; // test
export const TESTS_STARTED = 'TESTS_STARTED'; // playerstatus, test
export const TESTS_FINISHED = 'TESTS_FINISHED'; // test
export const TESTS_FAILED = 'TESTS_FAILED'; // test
export const TESTS_PASSED = 'TESTS_PASSED'; // test

/* Given a list of test results, returns pass/fail status.*/

const getTestStatus = testResults => testResults.every(testResult => testResult.pass);

export function onOutputChange(newOutput) {
  return {
    type: OUTPUT_CHANGED,
    userOutput: newOutput
  };
}

/* Thunk action which runs the test cases against user code. */
export function runTests(userCode, currChallenge) {
  return dispatch => {
    dispatch(actionTestsStarted());

    // Eval user code inside worker
    // http://stackoverflow.com/questions/9020116/is-it-possible-to-restrict-the-scope-of-a-javascript-function/36255766#36255766
    const perfBefore = performance.now();
    createTestWorker(userCode, currChallenge, dispatch)
      .then(() => console.log(`Total time to evaluate test cases: ${performance.now() - perfBefore}`))
      .catch(err => console.error(err));
  };
}

/* Dispatched when a user starts running the tests.*/
export function actionTestsStarted () {
  return {
    type: TESTS_STARTED
  };
}

/* Dispatched when tests fail.*/
export function actionTestsPassed () {
  return {
    type: TESTS_PASSED
  };
}

/* Dispatched when tests fail.*/
export function actionTestsFailed () {
  return {
    type: TESTS_FAILED
  };
}

/* Dispatched when the tests finish. */
export function actionTestsFinished (testResults) {
  return {
    type: TESTS_FINISHED,
    testResults
  };
}

function verifyFastest (data) {
  const re = /^.*x (\d.*) ops\/sec ±(.*)% \(.*$/;
  let statisticalConfidence = true;

  if (data.testData[0].match(re) && data.testData[1].match(re)) {
    const stats = data.testData.map(datum => {
      return {
        mean: parseInt((datum.match(re)[1]).replace(',', ''), 10),
        pMarginOfError: Number(datum.match(re)[2]) / 100
      };
    }).map(stat => {
      return {
        mean: stat.mean,
        pMarginOfError: stat.pMarginOfError,
        aMarginOfError: stat.mean * stat.pMarginOfError
      };
    });

    // console.log(stats);

    const stockRange = [
      stats[0].mean - stats[0].aMarginOfError, stats[0].mean + stats[0].aMarginOfError
    ];

    const userRange = [
      stats[1].mean - stats[1].aMarginOfError, stats[1].mean + stats[1].aMarginOfError
    ];

    // console.log(stockRange, userRange);

    if (stockRange[0] <= userRange[1] && stockRange[1] >= userRange[0]) {
      statisticalConfidence = false;
    }

    if (statisticalConfidence) {
      if (data.fastest === 'user test') {
        // user code faster than stock code:
        console.log('Your code is extremely fast!');
      }
      else {
        // stock code faster than user code:
        console.log('Your code can be made more efficient.');
      }
    }
    else {
      // tied between user and stock code:
      console.log('Optimal code!');
    }
  }
}

// TODO:
// possibly reduce the number of workers because spawning and setting up a worker takes time
const createTestWorker = (userCode, currChallenge, dispatch) =>
  new Promise(resolve => {
    const wk = new Worker('public/js/ww.bundle.js');
    wk.postMessage([userCode, currChallenge.toJS()]); // postMessage mangles the Immutable object, so it needs to be transformed into regular JS before sending over to worker.
    wk.onmessage = e => {
      resolve(e.data);
    };
  })
  .then(workerData => {
    dispatch(onOutputChange(workerData[0]));
    if (workerData.length > 1) {
      const testResults = workerData.slice(4); // to take into account the benchmark items
      const allTestsPassed = getTestStatus(testResults);

      if (allTestsPassed) {
        dispatch(actionTestsPassed());
        // call benchmark webworkers here:
        const perfBefore = performance.now();
        const benchmarkFnCall = workerData[3];
        if (benchmarkFnCall) {
          const benchmarkCode = workerData.slice(1, 3);
          const benchmarkTimes = createBenchmarkWorker(benchmarkCode, benchmarkFnCall)
            .then(data => {
              console.log(data.fastest);
              verifyFastest(data);
              console.log(data.testData[0]);
              console.log(data.testData[1]);
              console.log(`Total time to benchmark: ${performance.now() - perfBefore}`);
            })
            .catch(err => console.error(err));
        }
      }
      else {
        dispatch(actionTestsFailed());
      }

      // Would it make sense to include this with passed/failed actions?
      dispatch(actionTestsFinished(testResults));
    }
  })
  .catch(err => { console.log(`Promise rejected: ${err}.`); });

const createBenchmarkWorker = (code, benchmarkFnCall) =>
  new Promise(resolve => {
    const wk = new Worker('public/js/wwBenchmark.bundle.js');
    wk.postMessage([code, benchmarkFnCall]);
    wk.onmessage = e => {
      resolve(e.data);
    };
  })
  .catch(err => console.error(err));
<|endoftext|>


<commit_before>/**
 * Created by Maya on 10.8.15.
 */

import NewFile from '../../services/NewFile';
import * as Keys from '../../services/Shortcuts';

class IdeController {
    constructor(Api, $stateParams, Editor, $scope, Shortcuts) {
        this.$scope = $scope;
        this.openFiles = [];
        this.workspace = {
            name: $stateParams.workspace,
            files: []
        };

        this.Editor = Editor;
        this.Api = Api;

        this.editorApi = {
            onSave: function (tool){
                this.activeFile.content = JSON.stringify(tool, null, 4);
                this.saveFile(this.activeFile);
            }.bind(this),

            getJson: function (tool){
                console.log('got json', tool);
            }.bind(this)

        };

        Api.workspaces.query({workspace: $stateParams.workspace},
            (res) => {
                _.forEach(res.files, (file) => {
                    if (file.type) {
                        let fileObj = new NewFile(file.name, file.type, file.content);
                        this.workspace.files.push(makeTab(fileObj));
                    }
                });
            }, (err) => {
                new Error(err);
            });

        this.addKeyboardHandlers($scope, Shortcuts);
    }

    /** File methods **/

    fileAdded(file) {
        let fileObj = makeTab(new NewFile(file.name, file.type, file.content));
        this.workspace.files.push(fileObj);
        this.openFiles.push(fileObj);
        this.setActiveFile(fileObj);
    }

    fileOpened(file) {
        this.setActiveFile(file);
        if (this.openFiles.indexOf(file) !== -1) {
            return;
        }

        this.openFiles.push(file);

        if (!file.content) {
            this.loadFile(file);
        }
    }

    switchFiles(file) {
        this.setActiveFile(_.find(this.openFiles, file));
    }

    saveFile(file) {
        this.Api.files.update({file: file.name, workspace: this.workspace.name, content: file.content},
            (suc) => {
                console.log('successfully updated file', suc);
            }, (err) => {
                console.log('something went wrong here', err);
            });
    }

    loadFile(file) {
        this.Api.files.query({file: file.name, workspace: this.workspace.name},
            (res) => {
                try {
                    let fileContents = JSON.parse(res.content);
                    file.class = fileContents ? fileContents.class : '';
                } catch (ex) {
                    console.log('could not parse json');
                }

                file.content = res.content;
            }, (err) => {
                console.log('something went wrong here', err);
            });
    }

    closeFile(file) {
        const index = _.indexOf(this.openFiles, file);
        _.remove(this.openFiles, file);
        let length = this.openFiles.length;

        if (file === this.activeFile && length !== 0) {
            if (index < length && index >= 0) {
                this.setActiveFile(this.openFiles[index]);
            } else {
                this.setActiveFile(this.openFiles[length - 1]);
            }
        } else if (length === 0) {
            this.activeFile = null;
            delete this.activeFile;
        }
    }

    setActiveFile(fileObj) {
        this.activeFile = fileObj;
        this.Editor.setMode(fileObj.type);
    }

    /**
     * Adds event handlers for keyboard shortcuts
     * @param $scope
     * @param Shortcuts
     */
    addKeyboardHandlers($scope, Shortcuts) {
        $scope.$on(Shortcuts.events.save, () => {
            if (this.activeFile) {
                this.saveFile(this.activeFile)
            }
        });

        $scope.$on(Shortcuts.events.close, function() {
            if (this.activeFile) {
                this.closeFile(this.activeFile);
                $scope.$apply();
            }
        }.bind(this));

        $scope.$on(Shortcuts.events.moveRight, function() {
            if (this.openFiles.length > 1) {
                let index = _.indexOf(this.openFiles, this.activeFile);
                if (index === this.openFiles.length - 1) {
                    this.setActiveFile(this.openFiles[0]);
                } else {
                    this.setActiveFile(this.openFiles[index + 1]);
                }
            }
            $scope.$apply();
        }.bind(this));

        /** Move to left **/
        $scope.$on(Shortcuts.events.moveLeft, function() {
            if (this.openFiles.length > 1) {
                let index = _.indexOf(this.openFiles, this.activeFile);
                if (index === 0) {
                    this.setActiveFile(this.openFiles[this.openFiles.length - 1]);
                } else {
                    this.setActiveFile(this.openFiles[index - 1]);
                }
            }
            $scope.$apply();
        }.bind(this));
    }
}

function makeTab(obj) {
    obj.slug = _.kebabCase(obj.name);
    return obj;
}

IdeController.$inject = ['Api', '$stateParams', 'Editor', '$scope', 'Shortcuts'];
angular.module('cottontail').controller('IdeController', IdeController);

export default IdeController;<commit_msg>feat(Global): make communication between cottontail and rabix editors work with promises<commit_after>/**
 * Created by Maya on 10.8.15.
 */

import NewFile from '../../services/NewFile';
import * as Keys from '../../services/Shortcuts';

class IdeController {
    constructor(Api, $stateParams, Editor, $scope, Shortcuts, $q) {
        this.$scope = $scope;
        this.openFiles = [];
        this.workspace = {
            name: $stateParams.workspace,
            files: []
        };
        this.$q = $q;
        this.Editor = Editor;
        this.Api = Api;

        this.editorApi = {
            onSave: function (tool){
                let deferred = $q.defer();
                this.activeFile.content = JSON.stringify(tool, null, 4);
                this.saveFile(this.activeFile).then((suc) => {
                    deferred.resolve(suc);
                });

                return deferred.promise;
            }.bind(this),

            getJson: function (tool){
                console.log('got json', tool);
            }.bind(this)

        };

        Api.workspaces.query({workspace: $stateParams.workspace},
            (res) => {
                _.forEach(res.files, (file) => {
                    if (file.type) {
                        let fileObj = new NewFile(file.name, file.type, file.content);
                        this.workspace.files.push(makeTab(fileObj));
                    }
                });
            }, (err) => {
                new Error(err);
            });

        this.addKeyboardHandlers($scope, Shortcuts);
    }

    /** File methods **/

    fileAdded(file) {
        let fileObj = makeTab(new NewFile(file.name, file.type, file.content));
        this.workspace.files.push(fileObj);
        this.openFiles.push(fileObj);
        this.setActiveFile(fileObj);
    }

    fileOpened(file) {
        this.setActiveFile(file);
        if (this.openFiles.indexOf(file) !== -1) {
            return;
        }

        this.openFiles.push(file);

        if (!file.content) {
            this.loadFile(file);
        }
    }

    switchFiles(file) {
        this.setActiveFile(_.find(this.openFiles, file));
    }

    saveFile(file) {
        let deferred = this.$q.defer();
        this.Api.files.update({file: file.name, workspace: this.workspace.name, content: file.content},
            (suc) => {
                deferred.resolve(suc);
                console.log('successfully updated file', suc);
            }, (err) => {
                deferred.reject(err);
                console.log('something went wrong here', err);
            });
        return deferred.promise;
    }

    loadFile(file) {
        this.Api.files.query({file: file.name, workspace: this.workspace.name},
            (res) => {
                try {
                    let fileContents = JSON.parse(res.content);
                    file.class = fileContents ? fileContents.class : '';
                } catch (ex) {
                    console.log('could not parse json');
                }

                file.content = res.content;
            }, (err) => {
                console.log('something went wrong here', err);
            });
    }

    closeFile(file) {
        const index = _.indexOf(this.openFiles, file);
        _.remove(this.openFiles, file);
        let length = this.openFiles.length;

        if (file === this.activeFile && length !== 0) {
            if (index < length && index >= 0) {
                this.setActiveFile(this.openFiles[index]);
            } else {
                this.setActiveFile(this.openFiles[length - 1]);
            }
        } else if (length === 0) {
            this.activeFile = null;
            delete this.activeFile;
        }
    }

    setActiveFile(fileObj) {
        this.activeFile = fileObj;
        this.Editor.setMode(fileObj.type);
    }

    /**
     * Adds event handlers for keyboard shortcuts
     * @param $scope
     * @param Shortcuts
     */
    addKeyboardHandlers($scope, Shortcuts) {
        $scope.$on(Shortcuts.events.save, () => {
            if (this.activeFile) {
                this.saveFile(this.activeFile)
            }
        });

        $scope.$on(Shortcuts.events.close, function() {
            if (this.activeFile) {
                this.closeFile(this.activeFile);
                $scope.$apply();
            }
        }.bind(this));

        $scope.$on(Shortcuts.events.moveRight, function() {
            if (this.openFiles.length > 1) {
                let index = _.indexOf(this.openFiles, this.activeFile);
                if (index === this.openFiles.length - 1) {
                    this.setActiveFile(this.openFiles[0]);
                } else {
                    this.setActiveFile(this.openFiles[index + 1]);
                }
            }
            $scope.$apply();
        }.bind(this));

        /** Move to left **/
        $scope.$on(Shortcuts.events.moveLeft, function() {
            if (this.openFiles.length > 1) {
                let index = _.indexOf(this.openFiles, this.activeFile);
                if (index === 0) {
                    this.setActiveFile(this.openFiles[this.openFiles.length - 1]);
                } else {
                    this.setActiveFile(this.openFiles[index - 1]);
                }
            }
            $scope.$apply();
        }.bind(this));
    }
}

function makeTab(obj) {
    obj.slug = _.kebabCase(obj.name);
    return obj;
}

IdeController.$inject = ['Api', '$stateParams', 'Editor', '$scope', 'Shortcuts', '$q'];
angular.module('cottontail').controller('IdeController', IdeController);

export default IdeController;<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Button, Panel } from '@freecodecamp/react-bootstrap';

import { FullWidthRow } from '../helpers';
import SectionHeader from './SectionHeader';
import HonestyPolicy from '../../resources/honesty-policy';

import './honesty.css';

const propTypes = {
  isHonest: PropTypes.bool,
  policy: PropTypes.arrayOf(PropTypes.string),
  updateIsHonest: PropTypes.func.isRequired
};

class Honesty extends Component {
  handleAgreeClick = () => this.props.updateIsHonest({ isHonest: true });

  renderAgreeButton = () => (
    <Button block={true} bsStyle='primary' onClick={this.handleAgreeClick}>
      Agree
    </Button>
  );

  renderIsHonestAgreed = () => (
    <Button
      block={true}
      bsStyle='primary'
      className='disabled-agreed'
      disabled={true}
    >

You have accepted our Academic Honesty Policy.

    </Button>
  );

  render() {
    const { isHonest } = this.props;

    return (

        <SectionHeader>Academic Honesty Policy</SectionHeader>
        <FullWidthRow>
          <Panel className='honesty-panel'>
            <HonestyPolicy />
          </Panel>

          {isHonest ? this.renderIsHonestAgreed() : this.renderAgreeButton()}
        </FullWidthRow>

    );
  }
}

Honesty.displayName = 'Honesty';
Honesty.propTypes = propTypes;

export default Honesty;
<commit_msg>Refactor Honesty (#39726)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { Button, Panel } from '@freecodecamp/react-bootstrap';

import { FullWidthRow } from '../helpers';
import SectionHeader from './SectionHeader';
import HonestyPolicy from '../../resources/honesty-policy';

import './honesty.css';

const propTypes = {
  isHonest: PropTypes.bool,
  updateIsHonest: PropTypes.func.isRequired
};

const Honesty = ({ isHonest, updateIsHonest }) => {
  const button = isHonest ? (
    <Button
      block={true}
      bsStyle='primary'
      className='disabled-agreed'
      disabled={true}
    >

You have accepted our Academic Honesty Policy.

    </Button>
  ) : (
    <Button
      block={true}
      bsStyle='primary'
      onClick={() => updateIsHonest({ isHonest: true })}
    >
      Agree
    </Button>
  );
  return (

      <SectionHeader>Academic Honesty Policy</SectionHeader>
      <FullWidthRow>
        <Panel className='honesty-panel'>
          <HonestyPolicy />
        </Panel>

        {button}
      </FullWidthRow>

  );
};

Honesty.displayName = 'Honesty';
Honesty.propTypes = propTypes;

export default Honesty;
<|endoftext|>


<commit_before>import {ShortcutDispatcher} from './shortcut.dispatcher';
import {Command} from '../command/command';
import {CommandManager} from './../command/command.manager';

describe('ShortcutDispatcher', () => {
	let manager = new CommandManager();
	let command1 = new Command();
	command1.shortcut = 'ctrl|escape';
	let command2 = new Command();
	command2.shortcut = () => 'alt|shift';
	let command3 = new Command();
	command3.shortcut = () => 'enter|tab';
	let cmds = [command1, command2, command3];
	let shortcutDispatcher = new ShortcutDispatcher();

	describe('execute', () => {
		it('should return true if shortcut was registered and executed', () => {
			shortcutDispatcher.register(manager, cmds);
			let result = shortcutDispatcher.execute('ctrl');
			expect(result).to.equal(true);
		});

		it('should return false if shortcut was not found', () => {
			let result = shortcutDispatcher.execute('deleeete');
			expect(result).to.equal(false);
		});
	});

	describe('test', () => {
		it('should return true if shortcut contains * symbol', () => {
			expect(shortcutDispatcher.test('*|ctrl', '')).to.equal(true);
		});
		it('should return true if shortcut equals code ', () => {
			expect(shortcutDispatcher.test('ctrl|shift', 'ctrl')).to.equal(true);
		});
		it('should return false otherwise', () => {
			expect(shortcutDispatcher.test('ctrl|shift', 'space')).to.equal(false);
		});
	});
});
<commit_msg>fix tests<commit_after>import {ShortcutDispatcher} from './shortcut.dispatcher';
import {Command} from '../command/command';
import {CommandManager} from './../command/command.manager';

describe('ShortcutDispatcher', () => {
	let manager = new CommandManager();
	let command1 = new Command();
	command1.shortcut = 'ctrl|escape';
	let command2 = new Command();
	command2.shortcut = () => 'alt|shift';
	let command3 = new Command();
	command3.shortcut = () => 'enter|tab';
	let cmds = [command1, command2, command3];
	let shortcutDispatcher = new ShortcutDispatcher();

	describe('execute', () => {
		it('should return true if shortcut was registered and executed', () => {
			shortcutDispatcher.register(manager, cmds);
			let result = shortcutDispatcher.execute('ctrl').length > 0;
			expect(result).to.equal(true);
		});

		it('should return false if shortcut was not found', () => {
			let result = shortcutDispatcher.execute('deleeete').length > 0;
			expect(result).to.equal(false);
		});
	});

	describe('test', () => {
		it('should return true if shortcut contains * symbol', () => {
			expect(shortcutDispatcher.test('*|ctrl', '')).to.equal(true);
		});
		it('should return true if shortcut equals code ', () => {
			expect(shortcutDispatcher.test('ctrl|shift', 'ctrl')).to.equal(true);
		});
		it('should return false otherwise', () => {
			expect(shortcutDispatcher.test('ctrl|shift', 'space')).to.equal(false);
		});
	});
});
<|endoftext|>