<commit_before>'use strict';

// Load environment variables
require('dotenv').config({path: '../app/.env'});

/**
 * Global dependencies
 */
const gulp = require('gulp');
const fs = require('fs-extra');
const del = require('del');
const plugins = require('gulp-load-plugins')();

// Set up logging
let doILog = (process.env.UF_MODE == 'dev');
let logger = (message) => {
    if (doILog) {
        console.log(message);
    }
};

const sprinklesDir = '../app/sprinkles';

// The Sprinkle load order from sprinkles.json
const sprinkles = ['core'].concat(require(`${sprinklesDir}/sprinkles.json`)['base']);

// The directory where the bundle task should place compiled assets.
// The names of assets in bundle.result.json will be located relative to this path.
const publicAssetsDir = '../public/assets/';

// name of the bundle file
const bundleFile = 'bundle.config.json';

// Compiled bundle config file
const bundleConfigFile = `./${bundleFile}`;

/**
 * Vendor asset task
 */
gulp.task('assets-install', () => {
    'use strict';

    // Legacy clean up
    let legacyVendorAssets = '../app/sprinkles/*/assets/vendor/**';
    if (del.sync(legacyVendorAssets, { dryRun: true, force: true }).length > 0) {
        logger('Frontend vendor assets are now located at "app/assets".\nStarting clean up of legacy vendor assets...');
        del.sync(legacyVendorAssets, { force: true });
        logger('Complete.')
    }

    let mergePkg = require('@userfrosting/merge-package-dependencies');

    // See if there are any yarn packages.
    let yarnPaths = [];
    for (let sprinkle of sprinkles) {
        if (fs.existsSync(`../app/sprinkles/${sprinkle}/package.json`)) {
            yarnPaths.push(`../app/sprinkles/${sprinkle}/package.json`);
        }
    }
    if (yarnPaths.length > 0) {
        // Yes there are!

        // Delete old package.json
        del.sync('../app/assets/package.json', { force: true });

        // Generate package.json
        let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields.
            private: true,
            flat: true
        };
        logger('\nMerging packages...\n');
        mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog);
        logger('\nMerge complete.\n');

        // Yarn automatically removes extraneous packages.

        // Perform installation.
        logger('Installing npm/yarn assets...');
        let childProcess = require('child_process');
        childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', {
            cwd: '../app/assets',
            stdio: doILog ? 'inherit' : ''
        });
    }
    else del.sync([
        '../app/assets/package.json',
        '../app/assets/node_modules/'
    ], { force: true });

    // See if there are any bower packages.
    let bowerPaths = [];
    for (let sprinkle of sprinkles) {
        // bower
        if (fs.existsSync(`../app/sprinkles/${sprinkle}/bower.json`)) {
            console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`);
            bowerPaths.push(`../app/sprinkles/${sprinkle}/bower.json`);
        }
    }
    if (bowerPaths.length > 0) {
        // Yes there are!

        // Delete old bower.json
        del.sync('../app/assets/bower.json', { force: true });

        // Generate bower.json
        let bowerTemplate = {
            name: 'uf-vendor-assets'
        };
        logger('\nMerging packages...\n');
        mergePkg.bower(bowerTemplate, bowerPaths, '../app/assets/', doILog);
        logger('\nMerge complete.\n');

        let childProcess = require('child_process');

        // Remove extraneous packages
        childProcess.execSync('bower prune', {
            cwd: '../app/assets',
            stdio: doILog ? 'inherit' : ''
        });

        // Perform installation
        childProcess.execSync('bower install -q --allow-root', { // --allow-root stops bower from complaining about being in 'sudo'.
            cwd: '../app/assets',
            stdio: doILog ? 'inherit' : ''
        });
        // Yarn is able to output its completion. Bower... not so much.
        logger('Done.\n');
    }
    else del.sync([
        '../app/assets/bower.json',
        '../app/assets/bower_components/'
    ], { force: true });
});

/**
 * Bundling tasks
 */

// Executes bundling tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order.
// Respects bundle collision rules.
gulp.task('bundle-build', () => {
    'use strict';
    let copy = require('recursive-copy');
    let merge = require('merge-array-object');
    let cleanup = (e) => {
        'use strict';
        // Delete temporary directory if exists
        fs.rmdirSync('./temp');
        // Delete created bundle.config.json file
        fs.unlinkSync(bundleConfigFile);
        // Propagate error
        throw e;
    };
    let config = {
        bundle: {},
        copy: []
    };
    sprinkles.forEach((sprinkle) => {
        'use strict';
        let location = `${sprinklesDir}/${sprinkle}/`;
        if (fs.existsSync(`${location}${bundleFile}`)) {
            let currentConfig = require(`${location}${bundleFile}`);
            // Add bundles to config, respecting collision rules.
            for (let bundleName in currentConfig.bundle) {
                // If bundle already defined, handle as per collision rules.
                if (bundleName in config.bundle) {
                    let onCollision = 'replace';
                    try {
                        onCollision = (typeof currentConfig.bundle[bundleName].options.sprinkle.onCollision !== 'undefined' ? currentConfig.bundle[bundleName].options.sprinkle.onCollision : 'replace');
                    }
                    catch (e) {

                    }
                    switch (onCollision) {
                        case 'replace':
                            config.bundle[bundleName] = currentConfig.bundle[bundleName];
                            break;
                        case 'merge':
                            // If using this collision rule, keep in mind any bundling options will also be merged.
                            // Inspect the produced 'bundle.config.json' file in the 'build' folder to ensure options are correct.
                            config.bundle[bundleName] = merge(config.bundle[bundleName], currentConfig.bundle[bundleName]);
                            break;
                        case 'ignore':
                            // Do nothing. This simply exists to prevent falling through to error catchment.
                            break;
                        case 'error':
                            cleanup(`The bundle '${bundleName}' in the Sprinkle '${sprinkle}' has been previously defined, and the bundle's 'onCollision' property is set to 'error'.`);
                        default:
                            cleanup(`Unexpected input '${onCollision}' for 'onCollision' for the bundle '${bundleName}' in the Sprinkle '${sprinkle}'.`);
                    }
                }
                // Otherwise, just add.
                else {
                    config.bundle[bundleName] = currentConfig.bundle[bundleName];
                }
            }
            // Add/merge copy files to config
            if ('copy' in currentConfig) {
                config.copy = new Set(config.copy, currentConfig.copy);
            }
        }
    });
    // Save bundle rules to bundle.config.json
    fs.writeFileSync(bundleConfigFile, JSON.stringify(config));

    // Copy vendor assets (bower, then npm)
    /** @todo Should really keep the garbage files out. A filter function can be passed to the copySync settings object. */
    let paths = [
        '../app/assets/bower_components/',
        '../app/assets/node_modules/'
    ];
    for (let path of paths) {
        if (fs.pathExistsSync(path)) fs.copySync(path, `${publicAssetsDir}vendor/`, { overwrite: true });
    }
    // Copy sprinkle assets
    paths = [];
    for (let sprinkle of sprinkles) {
        paths.push(`../app/sprinkles/${sprinkle}/assets/`);
    }
    for (let path of paths) {
        fs.copySync(path, '../public/assets/', { overwrite: true });
    }
    return;
});

// Execute gulp-bundle-assets
gulp.task('bundle', () => {
    'use strict';
    return gulp.src(bundleConfigFile)
        .pipe(plugins.ufBundleAssets({
            base: publicAssetsDir
        }))
        .pipe(plugins.ufBundleAssets.results({
            dest: './'
        }))
        .pipe(gulp.dest(publicAssetsDir));
});

/**
 * Clean up tasks
 */

gulp.task('public-clean', () => {
    'use strict';
    return del(publicAssetsDir, { force: true });
});

// Clean up temporary bundling files
gulp.task('bundle-clean', () => {
    'use strict';
    return del(bundleConfigFile, { force: true });
});

// Deletes assets fetched by assets-install
gulp.task('assets-clean', () => {
    'use strict';
    return del(['../app/assets/bower_components/', '../app/assets/node_modules/', '../app/assets/bower.json', '../app/assets/package.json'], { force: true });
});

// Deletes all generated, or acquired files.
gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean'], () => { });<commit_msg>Build clean up improvements, and note about assets-install behavior.<commit_after>'use strict';

// Load environment variables
require('dotenv').config({path: '../app/.env'});

/**
 * Global dependencies
 */
const gulp = require('gulp');
const fs = require('fs-extra');
const del = require('del');
const plugins = require('gulp-load-plugins')();

// Set up logging
let doILog = (process.env.UF_MODE == 'dev');
let logger = (message) => {
    if (doILog) {
        console.log(message);
    }
};

const sprinklesDir = '../app/sprinkles';

// The Sprinkle load order from sprinkles.json
const sprinkles = ['core'].concat(require(`${sprinklesDir}/sprinkles.json`)['base']);

// The directory where the bundle task should place compiled assets.
// The names of assets in bundle.result.json will be located relative to this path.
const publicAssetsDir = '../public/assets/';

// name of the bundle file
const bundleFile = 'bundle.config.json';

// Compiled bundle config file
const bundleConfigFile = `./${bundleFile}`;

/**
 * Vendor asset task
 * NOTE: This task cannot be run directly from the gulp cli. Use the npm run script instead.
 */
gulp.task('assets-install', () => {
    'use strict';

    // Legacy clean up
    let legacyVendorAssets = '../app/sprinkles/*/assets/vendor/**';
    if (del.sync(legacyVendorAssets, { dryRun: true, force: true }).length > 0) {
        logger('Frontend vendor assets are now located at "app/assets".\nStarting clean up of legacy vendor assets...');
        del.sync(legacyVendorAssets, { force: true });
        logger('Complete.')
    }

    let mergePkg = require('@userfrosting/merge-package-dependencies');

    // See if there are any yarn packages.
    let yarnPaths = [];
    for (let sprinkle of sprinkles) {
        if (fs.existsSync(`../app/sprinkles/${sprinkle}/package.json`)) {
            yarnPaths.push(`../app/sprinkles/${sprinkle}/package.json`);
        }
    }
    if (yarnPaths.length > 0) {
        // Yes there are!

        // Delete old package.json
        del.sync('../app/assets/package.json', { force: true });

        // Generate package.json
        let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields.
            private: true,
            flat: true
        };
        logger('\nMerging packages...\n');
        mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog);
        logger('\nMerge complete.\n');

        // Yarn automatically removes extraneous packages.

        // Perform installation.
        logger('Installing npm/yarn assets...');
        let childProcess = require('child_process');
        childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', {
            cwd: '../app/assets',
            stdio: doILog ? 'inherit' : ''
        });
    }
    else del.sync([
        '../app/assets/package.json',
        '../app/assets/node_modules/**'
    ], { force: true });

    // See if there are any bower packages.
    let bowerPaths = [];
    for (let sprinkle of sprinkles) {
        // bower
        if (fs.existsSync(`../app/sprinkles/${sprinkle}/bower.json`)) {
            console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`);
            bowerPaths.push(`../app/sprinkles/${sprinkle}/bower.json`);
        }
    }
    if (bowerPaths.length > 0) {
        // Yes there are!

        // Delete old bower.json
        del.sync('../app/assets/bower.json', { force: true });

        // Generate bower.json
        let bowerTemplate = {
            name: 'uf-vendor-assets'
        };
        logger('\nMerging packages...\n');
        mergePkg.bower(bowerTemplate, bowerPaths, '../app/assets/', doILog);
        logger('\nMerge complete.\n');

        let childProcess = require('child_process');

        // Remove extraneous packages
        childProcess.execSync('bower prune', {
            cwd: '../app/assets',
            stdio: doILog ? 'inherit' : ''
        });

        // Perform installation
        childProcess.execSync('bower install -q --allow-root', { // --allow-root stops bower from complaining about being in 'sudo'.
            cwd: '../app/assets',
            stdio: doILog ? 'inherit' : ''
        });
        // Yarn is able to output its completion. Bower... not so much.
        logger('Done.\n');
    }
    else del.sync([
        '../app/assets/bower.json',
        '../app/assets/bower_components/**'
    ], { force: true });
});

/**
 * Bundling tasks
 */

// Executes bundling tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order.
// Respects bundle collision rules.
gulp.task('bundle-build', () => {
    'use strict';
    let copy = require('recursive-copy');
    let merge = require('merge-array-object');
    let cleanup = (e) => {
        'use strict';
        // Delete temporary directory if exists
        fs.rmdirSync('./temp');
        // Delete created bundle.config.json file
        fs.unlinkSync(bundleConfigFile);
        // Propagate error
        throw e;
    };
    let config = {
        bundle: {},
        copy: []
    };
    sprinkles.forEach((sprinkle) => {
        'use strict';
        let location = `${sprinklesDir}/${sprinkle}/`;
        if (fs.existsSync(`${location}${bundleFile}`)) {
            let currentConfig = require(`${location}${bundleFile}`);
            // Add bundles to config, respecting collision rules.
            for (let bundleName in currentConfig.bundle) {
                // If bundle already defined, handle as per collision rules.
                if (bundleName in config.bundle) {
                    let onCollision = 'replace';
                    try {
                        onCollision = (typeof currentConfig.bundle[bundleName].options.sprinkle.onCollision !== 'undefined' ? currentConfig.bundle[bundleName].options.sprinkle.onCollision : 'replace');
                    }
                    catch (e) {

                    }
                    switch (onCollision) {
                        case 'replace':
                            config.bundle[bundleName] = currentConfig.bundle[bundleName];
                            break;
                        case 'merge':
                            // If using this collision rule, keep in mind any bundling options will also be merged.
                            // Inspect the produced 'bundle.config.json' file in the 'build' folder to ensure options are correct.
                            config.bundle[bundleName] = merge(config.bundle[bundleName], currentConfig.bundle[bundleName]);
                            break;
                        case 'ignore':
                            // Do nothing. This simply exists to prevent falling through to error catchment.
                            break;
                        case 'error':
                            cleanup(`The bundle '${bundleName}' in the Sprinkle '${sprinkle}' has been previously defined, and the bundle's 'onCollision' property is set to 'error'.`);
                        default:
                            cleanup(`Unexpected input '${onCollision}' for 'onCollision' for the bundle '${bundleName}' in the Sprinkle '${sprinkle}'.`);
                    }
                }
                // Otherwise, just add.
                else {
                    config.bundle[bundleName] = currentConfig.bundle[bundleName];
                }
            }
            // Add/merge copy files to config
            if ('copy' in currentConfig) {
                config.copy = new Set(config.copy, currentConfig.copy);
            }
        }
    });
    // Save bundle rules to bundle.config.json
    fs.writeFileSync(bundleConfigFile, JSON.stringify(config));

    // Copy vendor assets (bower, then npm)
    /** @todo Should really keep the garbage files out. A filter function can be passed to the copySync settings object. */
    let paths = [
        '../app/assets/bower_components/',
        '../app/assets/node_modules/'
    ];
    for (let path of paths) {
        if (fs.pathExistsSync(path)) fs.copySync(path, `${publicAssetsDir}vendor/`, { overwrite: true });
    }
    // Copy sprinkle assets
    paths = [];
    for (let sprinkle of sprinkles) {
        paths.push(`../app/sprinkles/${sprinkle}/assets/`);
    }
    for (let path of paths) {
        fs.copySync(path, '../public/assets/', { overwrite: true });
    }
    return;
});

// Execute gulp-bundle-assets
gulp.task('bundle', () => {
    'use strict';
    return gulp.src(bundleConfigFile)
        .pipe(plugins.ufBundleAssets({
            base: publicAssetsDir
        }))
        .pipe(plugins.ufBundleAssets.results({
            dest: './'
        }))
        .pipe(gulp.dest(publicAssetsDir));
});

/**
 * Clean up tasks
 */

gulp.task('public-clean', () => {
    'use strict';
    return del(publicAssetsDir, { force: true });
});

// Clean up temporary bundling files
gulp.task('bundle-clean', () => {
    'use strict';
    return del(bundleConfigFile, { force: true });
});

// Deletes assets fetched by assets-install
gulp.task('assets-clean', () => {
    'use strict';
    return del('../app/assets/*', { force: true });
});

// Deletes all generated, or acquired files.
gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean']);<|endoftext|>


<commit_before>import React from 'react';
import { Swipeable } from 'react-touch';
import { SelectPlayer } from '../components/select_player';
import { PlayerIcon } from '../components/player_icon';

const POINTS_PER_SET = 6;
const POINTS_PER_MATCH = 2;

export class Match extends React.Component {
  constructor(props) {
    super(props);

    this.initState();
  }

  initState() {
    this.state = {
      selectPlayerFor: null,
      sets: [],
    };

    const newTeam = { won: 0, attack: null, defense: null };
    this.addSet(newTeam, newTeam);
  }

  get currentSet() {
    return this.state.sets[this.state.sets.length - 1];
  }

  changeGoals(team, diff) {
    this.currentSet[team].goals += diff;

    if (this.currentSet[team].goals < 0) {
      this.currentSet[team].goals = 0;
    } else if (this.currentSet[team].goals >= POINTS_PER_SET) {
      this.endSet(team);
    }

    this.forceUpdate();
  }

  incGoals(team) {
    this.changeGoals(team, 1);
  }

  decGoals(team) {
    this.changeGoals(team, -1);
  }

  addSet(blueTeam, redTeam) {
    this.state.sets.push({
      number: this.state.sets.length + 1,
      blue: Object.assign({}, blueTeam, { goals : 0}),
      red: Object.assign({}, redTeam, { goals : 0})
    });
  }

  endSet(winnerTeam) {
    if (++this.currentSet[winnerTeam].won >= POINTS_PER_MATCH) {
      this.endMatch(winnerTeam);
      return;
    }

    // match is not ended, so start a new set with switched teams
    this.addSet(this.currentSet.red, this.currentSet.blue);

    // switch player positions per team
    // TODO: calculate "best" positions for last turn?
    this.switchPlayerPositions('red');
    this.switchPlayerPositions('blue');

    // reset goals
    this.currentSet.red.goals = 0;
    this.currentSet.blue.goals = 0;
  }

  endMatch(winnerTeam) {
    // TODO

    const team = this.currentSet[winnerTeam];
    setTimeout(() => {
      alert(`${team.attack.name} und ${team.defense.name} haben gewonnen!`);
    }, 100);

    this.initState();
  }

  switchPlayerPositions(teamColor) {
    const team = this.currentSet[teamColor];
    [team.attack, team.defense] = [team.defense, team.attack];
    this.forceUpdate();
  }

  selectPlayer(team, position) {
    this.state.selectPlayerFor = { team, position };
    this.forceUpdate();
  }

  removePlayer(player) {
    if (this.currentSet.blue.attack === player) {
      this.currentSet.blue.attack = null;
    }

    if (this.currentSet.blue.defense === player) {
      this.currentSet.blue.defense = null;
    }

    if (this.currentSet.red.attack === player) {
      this.currentSet.red.attack = null;
    }

    if (this.currentSet.red.defense === player) {
      this.currentSet.red.defense = null;
    }
  }

  playerSelected(player) {
    this.removePlayer(player);
    this.currentSet[this.state.selectPlayerFor.team][this.state.selectPlayerFor.position] = player;
    this.state.selectPlayerFor = null;
    this.forceUpdate();
  }

  isLastSet() {
    return this.currentSet.number == POINTS_PER_MATCH * 2 - 1;
  }

  render() {
    return (

        <SelectPlayer
          visible={ !!this.state.selectPlayerFor }
          upsideDown={ !!this.state.selectPlayerFor && this.state.selectPlayerFor.team == 'red' }
          select={ (player) => this.playerSelected(player) } ></SelectPlayer>

            <Swipeable onSwipeRight={ () => this.incGoals('red') } onSwipeLeft={ () => this.decGoals('red') }>

 this.incGoals('red') }>
                { this.currentSet.red.goals }

            </Swipeable>

 this.selectPlayer('red', 'defense') }>
            {
              !this.currentSet.red.defense ?
                 :
                <PlayerIcon name={ this.currentSet.red.defense.name } img={ this.currentSet.red.defense.img }></PlayerIcon>
            }
            Tor

 this.switchPlayerPositions('red') }>
            

 this.selectPlayer('red', 'attack') }>
            {
              !this.currentSet.red.attack ?
                 :
                <PlayerIcon name={ this.currentSet.red.attack.name } img={ this.currentSet.red.attack.img }></PlayerIcon>
            }
            Angriff

            { this.currentSet.number }

            <Swipeable onSwipeLeft={ () => this.incGoals('blue') } onSwipeRight={ () => this.decGoals('blue') }>

 this.incGoals('blue') }>
                { this.currentSet.blue.goals }

            </Swipeable>

 this.selectPlayer('blue', 'defense') }>
            {
              !this.currentSet.blue.defense ?
                 :
                <PlayerIcon name={ this.currentSet.blue.defense.name } img={ this.currentSet.blue.defense.img }></PlayerIcon>
            }
            Tor

 this.switchPlayerPositions('blue') }>
            

 this.selectPlayer('blue', 'attack') }>
            {
              !this.currentSet.blue.attack ?
                 :
                <PlayerIcon name={ this.currentSet.blue.attack.name } img={ this.currentSet.blue.attack.img }></PlayerIcon>
            }
            Angriff

    );
  }
}
<commit_msg>UI improvement: Make the whole team area clickable for goal incresement<commit_after>import React from 'react';
import { Swipeable } from 'react-touch';
import { SelectPlayer } from '../components/select_player';
import { PlayerIcon } from '../components/player_icon';

const POINTS_PER_SET = 6;
const POINTS_PER_MATCH = 2;

export class Match extends React.Component {
  constructor(props) {
    super(props);

    this.initState();
  }

  initState() {
    this.state = {
      selectPlayerFor: null,
      sets: [],
    };

    const newTeam = { won: 0, attack: null, defense: null };
    this.addSet(newTeam, newTeam);
  }

  get currentSet() {
    return this.state.sets[this.state.sets.length - 1];
  }

  changeGoals(team, diff) {
    this.currentSet[team].goals += diff;

    if (this.currentSet[team].goals < 0) {
      this.currentSet[team].goals = 0;
    } else if (this.currentSet[team].goals >= POINTS_PER_SET) {
      this.endSet(team);
    }

    this.forceUpdate();
  }

  incGoals(team) {
    this.changeGoals(team, 1);
  }

  decGoals(team) {
    this.changeGoals(team, -1);
  }

  addSet(blueTeam, redTeam) {
    this.state.sets.push({
      number: this.state.sets.length + 1,
      blue: Object.assign({}, blueTeam, { goals : 0}),
      red: Object.assign({}, redTeam, { goals : 0})
    });
  }

  endSet(winnerTeam) {
    if (++this.currentSet[winnerTeam].won >= POINTS_PER_MATCH) {
      this.endMatch(winnerTeam);
      return;
    }

    // match is not ended, so start a new set with switched teams
    this.addSet(this.currentSet.red, this.currentSet.blue);

    // switch player positions per team
    // TODO: calculate "best" positions for last turn?
    this.switchPlayerPositions('red');
    this.switchPlayerPositions('blue');

    // reset goals
    this.currentSet.red.goals = 0;
    this.currentSet.blue.goals = 0;
  }

  endMatch(winnerTeam) {
    // TODO

    const team = this.currentSet[winnerTeam];
    setTimeout(() => {
      alert(`${team.attack.name} und ${team.defense.name} haben gewonnen!`);
    }, 100);

    this.initState();
  }

  switchPlayerPositions(teamColor) {
    const team = this.currentSet[teamColor];
    [team.attack, team.defense] = [team.defense, team.attack];
    this.forceUpdate();
  }

  selectPlayer(team, position, event) {
    event.preventDefault();
    event.stopPropagation();

    this.state.selectPlayerFor = { team, position };
    this.forceUpdate();
  }

  removePlayer(player) {
    if (this.currentSet.blue.attack === player) {
      this.currentSet.blue.attack = null;
    }

    if (this.currentSet.blue.defense === player) {
      this.currentSet.blue.defense = null;
    }

    if (this.currentSet.red.attack === player) {
      this.currentSet.red.attack = null;
    }

    if (this.currentSet.red.defense === player) {
      this.currentSet.red.defense = null;
    }
  }

  playerSelected(player) {
    this.removePlayer(player);
    this.currentSet[this.state.selectPlayerFor.team][this.state.selectPlayerFor.position] = player;
    this.state.selectPlayerFor = null;
    this.forceUpdate();
  }

  isLastSet() {
    return this.currentSet.number == POINTS_PER_MATCH * 2 - 1;
  }

  render() {
    return (

        <SelectPlayer
          visible={ !!this.state.selectPlayerFor }
          upsideDown={ !!this.state.selectPlayerFor && this.state.selectPlayerFor.team == 'red' }
          select={ (player) => this.playerSelected(player) } ></SelectPlayer>

 this.incGoals('red') }>

            <Swipeable onSwipeRight={ () => this.incGoals('red') } onSwipeLeft={ () => this.decGoals('red') }>

                { this.currentSet.red.goals }

            </Swipeable>

 this.selectPlayer('red', 'defense', e) }>
            {
              !this.currentSet.red.defense ?
                 :
                <PlayerIcon name={ this.currentSet.red.defense.name } img={ this.currentSet.red.defense.img }></PlayerIcon>
            }
            Tor

 this.switchPlayerPositions('red') }>
            

 this.selectPlayer('red', 'attack', e) }>
            {
              !this.currentSet.red.attack ?
                 :
                <PlayerIcon name={ this.currentSet.red.attack.name } img={ this.currentSet.red.attack.img }></PlayerIcon>
            }
            Angriff

            { this.currentSet.number }

 this.incGoals('blue') }>

            <Swipeable onSwipeLeft={ () => this.incGoals('blue') } onSwipeRight={ () => this.decGoals('blue') }>

                { this.currentSet.blue.goals }

            </Swipeable>

 this.selectPlayer('blue', 'defense', e) }>
            {
              !this.currentSet.blue.defense ?
                 :
                <PlayerIcon name={ this.currentSet.blue.defense.name } img={ this.currentSet.blue.defense.img }></PlayerIcon>
            }
            Tor

 this.switchPlayerPositions('blue') }>
            

 this.selectPlayer('blue', 'attack', e) }>
            {
              !this.currentSet.blue.attack ?
                 :
                <PlayerIcon name={ this.currentSet.blue.attack.name } img={ this.currentSet.blue.attack.img }></PlayerIcon>
            }
            Angriff

    );
  }
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2016 The IBM Research Emergent Solutions authors. All rights reserved.
 * This code may only be used under the MIT style license found at https://ibmresearch.github.io/LICENSE.txt
 * The complete set of authors may be found at https://ibmresearch.github.io/AUTHORS.txt
 * The complete set of contributors may be found at https://ibmresearch.github.io/CONTRIBUTORS.txt
 */

/* eslint-disable no-console */

'use strict';

const path = require('path');

const del = require('del');
const gulp = require('gulp');
const gulpif = require('gulp-if');
const htmlmin = require('gulp-htmlmin');
const imagemin = require('gulp-imagemin');
const jsonmin = require('gulp-jsonmin');
const mergeStream = require('merge-stream');
const polymerBuild = require('polymer-build');
const uglify = require('gulp-uglify');

const swPrecacheConfigPath = path.join(process.cwd(), 'sw-precache-config.js');
const swPrecacheConfig = require(swPrecacheConfigPath);
const polymerJsonPath = path.join(process.cwd(), 'polymer.json');
const polymerJson = require(polymerJsonPath);
const polymerProject = new polymerBuild.PolymerProject(polymerJson);
const buildDirectory = 'build';

/**
 * Waits for the given ReadableStream
 */
function waitFor(stream) {
  return new Promise((resolve, reject) => {
    stream.on('end', resolve);
    stream.on('error', reject);
  });
}

function build() {
  return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
    // Okay, so first thing we do is clear the build directory
    console.log(`Deleting ${buildDirectory} directory...`);
    del([buildDirectory])
      .then(() => {
        // Okay, now lets get your source files
        let sourcesStream = polymerProject.sources()
          .pipe(polymerProject.splitHtml())
          .pipe(gulpif(/\.js$/, uglify()))
          // .pipe(gulpif(/\.css$/, cssSlam()))
          .pipe(gulpif(/\.html$/, htmlmin({
            collapseWhitespace: true
          })))
          .pipe(gulpif(/\.(png|gif|jpg|svg)$/, imagemin()))
          .pipe(gulpif(/\.json$/, jsonmin()))
          .pipe(polymerProject.rejoinHtml());

        // Okay, now lets do the same to your dependencies
        let dependenciesStream = polymerProject.dependencies()
          .pipe(polymerProject.splitHtml())
          // .pipe(gulpif(/\.js$/, uglify()))
          // .pipe(gulpif(/\.css$/, cssSlam()))
          // .pipe(gulpif(/\.html$/, htmlMinifier()))
          .pipe(polymerProject.rejoinHtml());

        // Okay, now lets merge them into a single build stream
        let buildStream = mergeStream(sourcesStream, dependenciesStream)
          .once('data', () => {
            console.log('Analyzing build dependencies...');
          });

        // Okay, now do some bundling
        buildStream = buildStream.pipe(polymerProject.bundler);

        // Okay, time to pipe to the build directory
        buildStream = buildStream.pipe(gulp.dest(buildDirectory));

        // waitFor the buildStream to complete
        return waitFor(buildStream);
      })
      .then(() => {
        console.log('Generating the Service Worker...');
        return polymerBuild.addServiceWorker({
          project: polymerProject,
          buildRoot: buildDirectory,
          bundled: true,
          swPrecacheConfig: swPrecacheConfig
        });
      })
      .then(() => {
        console.log('Build complete!');
        resolve();
      });
  });
}

gulp.task('build', build);
<commit_msg>Refactor the swPrecacheConfig and polymerJson paths<commit_after>/**
 * @license
 * Copyright (c) 2016 The IBM Research Emergent Solutions authors. All rights reserved.
 * This code may only be used under the MIT style license found at https://ibmresearch.github.io/LICENSE.txt
 * The complete set of authors may be found at https://ibmresearch.github.io/AUTHORS.txt
 * The complete set of contributors may be found at https://ibmresearch.github.io/CONTRIBUTORS.txt
 */

/* eslint-disable no-console */

'use strict';

const del = require('del');
const gulp = require('gulp');
const gulpif = require('gulp-if');
const htmlmin = require('gulp-htmlmin');
const imagemin = require('gulp-imagemin');
const jsonmin = require('gulp-jsonmin');
const mergeStream = require('merge-stream');
const polymerBuild = require('polymer-build');
const uglify = require('gulp-uglify');

const swPrecacheConfig = require('./sw-precache-config.js');
const polymerJson = require('./polymer.json');
const polymerProject = new polymerBuild.PolymerProject(polymerJson);
const buildDirectory = 'build';

/**
 * Waits for the given ReadableStream
 */
function waitFor(stream) {
  return new Promise((resolve, reject) => {
    stream.on('end', resolve);
    stream.on('error', reject);
  });
}

function build() {
  return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
    // Okay, so first thing we do is clear the build directory
    console.log(`Deleting ${buildDirectory} directory...`);
    del([buildDirectory])
      .then(() => {
        // Okay, now lets get your source files
        let sourcesStream = polymerProject.sources()
          .pipe(polymerProject.splitHtml())
          .pipe(gulpif(/\.js$/, uglify()))
          // .pipe(gulpif(/\.css$/, cssSlam()))
          .pipe(gulpif(/\.html$/, htmlmin({
            collapseWhitespace: true
          })))
          .pipe(gulpif(/\.(png|gif|jpg|svg)$/, imagemin()))
          .pipe(gulpif(/\.json$/, jsonmin()))
          .pipe(polymerProject.rejoinHtml());

        // Okay, now lets do the same to your dependencies
        let dependenciesStream = polymerProject.dependencies()
          .pipe(polymerProject.splitHtml())
          // .pipe(gulpif(/\.js$/, uglify()))
          // .pipe(gulpif(/\.css$/, cssSlam()))
          // .pipe(gulpif(/\.html$/, htmlMinifier()))
          .pipe(polymerProject.rejoinHtml());

        // Okay, now lets merge them into a single build stream
        let buildStream = mergeStream(sourcesStream, dependenciesStream)
          .once('data', () => {
            console.log('Analyzing build dependencies...');
          });

        // Okay, now do some bundling
        buildStream = buildStream.pipe(polymerProject.bundler);

        // Okay, time to pipe to the build directory
        buildStream = buildStream.pipe(gulp.dest(buildDirectory));

        // waitFor the buildStream to complete
        return waitFor(buildStream);
      })
      .then(() => {
        console.log('Generating the Service Worker...');
        return polymerBuild.addServiceWorker({
          project: polymerProject,
          buildRoot: buildDirectory,
          bundled: true,
          swPrecacheConfig: swPrecacheConfig
        });
      })
      .then(() => {
        console.log('Build complete!');
        resolve();
      });
  });
}

gulp.task('build', build);
<|endoftext|>


<commit_before>/*
 * Copyright 2016 EPAM Systems
 *
 *
 * This file is part of EPAM Report Portal.
 * https://github.com/reportportal/service-ui
 *
 * Report Portal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Report Portal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Report Portal.  If not, see <http://www.gnu.org/licenses/>.
 */
define(function (require) {
    'use strict';

    var $ = require('jquery');
    var _ = require('underscore');
    var Localization = require('localization');

    var getCriteriaItems = function () {
        var executions = {
            statistics$executions$failed: Localization.launchesHeaders.failed,
            statistics$executions$skipped: Localization.launchesHeaders.skipped
        };
        var defects = {
            statistics$defects$product_bug$total: Localization.launchesHeaders.product_bug,
            statistics$defects$automation_bug$total: Localization.launchesHeaders.automation_bug,
            statistics$defects$system_issue$total: Localization.launchesHeaders.system_issue,
            statistics$defects$no_defect$total: Localization.launchesHeaders.no_defect,
        };
        return _.map(_.merge(executions, defects), function (key, val) {
            return { name: key, value: val };
        });
    };

    return {
        getConfig: function () {
            return {
                gadget_name: Localization.widgets.failedTestCasesTable,
                img: 'most-failure-test-cases-table.svg',
                description: Localization.widgets.failedTestCasesTableDescription,
                widget_type: 'table', // TODO remove after refactoring,
                hasPreview: false
            };
        },
        getSettings: function () {
            var async = $.Deferred();
            async.resolve([
                {
                    control: 'dropDown',
                    options: {
                        label: Localization.widgets.widgetCriteria,
                        items: getCriteriaItems(),
                        placeholder: Localization.wizard.criteriaSelectTitle,
                        multiple: false,
                        getValue: function (model, self) {
                            var contentFields = model.getContentFields();

                            if (contentFields.length) {
                                return contentFields;
                            }
                            return [self.model.get('items')[0].value];
                        },
                        setValue: function (value, model) {
                            model.setContentFields(value);
                        }
                    }
                },
                {
                    control: 'input',
                    options: {
                        name: Localization.widgets.launchesCount,
                        min: 2,
                        max: 150,
                        def: 30,
                        numOnly: true,
                        action: 'limit'
                    }
                },
                {
                    control: 'inputItems',
                    options: {
                        entity: 'launchName',
                        label: Localization.widgets.typeLaunchName,
                        placeholder: Localization.wizard.enterLaunchName,
                        minItems: 1,
                        maxItems: 1,
                        getValue: function (model) {
                            var widgetOptions = model.getWidgetOptions();
                            if (widgetOptions.launchNameFilter) {
                                return widgetOptions.launchNameFilter;
                            }
                            return [];
                        },
                        setValue: function (value, model) {
                            var widgetOptions = model.getWidgetOptions();
                            widgetOptions.launchNameFilter = value;
                            model.setWidgetOptions(widgetOptions);
                        }
                    }
                },
                {
                    control: 'static',
                    options: {
                        action: 'metadata_fields',
                        fields: ['name', 'start_time']
                    }
                }
            ]);

            return async.promise();
        }
    };
});
<commit_msg>Most failure test cases table widget JS error fix.<commit_after>/*
 * Copyright 2016 EPAM Systems
 *
 *
 * This file is part of EPAM Report Portal.
 * https://github.com/reportportal/service-ui
 *
 * Report Portal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Report Portal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Report Portal.  If not, see <http://www.gnu.org/licenses/>.
 */
define(function (require) {
    'use strict';

    var $ = require('jquery');
    var _ = require('underscore');
    var Localization = require('localization');

    var getCriteriaItems = function () {
        var executions = {
            statistics$executions$failed: Localization.launchesHeaders.failed,
            statistics$executions$skipped: Localization.launchesHeaders.skipped
        };
        var defects = {
            statistics$defects$product_bug$total: Localization.launchesHeaders.product_bug,
            statistics$defects$automation_bug$total: Localization.launchesHeaders.automation_bug,
            statistics$defects$system_issue$total: Localization.launchesHeaders.system_issue,
            statistics$defects$no_defect$total: Localization.launchesHeaders.no_defect,
        };
        return _.map(_.merge(executions, defects), function (key, val) {
            return { name: key, value: val };
        });
    };

    return {
        getConfig: function () {
            return {
                gadget_name: Localization.widgets.failedTestCasesTable,
                img: 'most-failure-test-cases-table.svg',
                description: Localization.widgets.failedTestCasesTableDescription,
                widget_type: 'table', // TODO remove after refactoring,
                hasPreview: false
            };
        },
        getSettings: function () {
            var async = $.Deferred();
            async.resolve([
                {
                    control: 'dropDown',
                    options: {
                        label: Localization.widgets.widgetCriteria,
                        items: getCriteriaItems(),
                        placeholder: Localization.wizard.criteriaSelectTitle,
                        multiple: false,
                        getValue: function (model, self) {
                            var contentFields = model.getContentFields();

                            if (contentFields.length) {
                                return contentFields;
                            }
                            return self.model.get('items')[0].value;
                        },
                        setValue: function (value, model) {
                            Array.isArray(value) ? model.setContentFields(value) : model.setContentFields([value]);
                        }
                    }
                },
                {
                    control: 'input',
                    options: {
                        name: Localization.widgets.launchesCount,
                        min: 2,
                        max: 150,
                        def: 30,
                        numOnly: true,
                        action: 'limit'
                    }
                },
                {
                    control: 'inputItems',
                    options: {
                        entity: 'launchName',
                        label: Localization.widgets.typeLaunchName,
                        placeholder: Localization.wizard.enterLaunchName,
                        minItems: 1,
                        maxItems: 1,
                        getValue: function (model) {
                            var widgetOptions = model.getWidgetOptions();
                            if (widgetOptions.launchNameFilter) {
                                return widgetOptions.launchNameFilter;
                            }
                            return [];
                        },
                        setValue: function (value, model) {
                            var widgetOptions = model.getWidgetOptions();
                            widgetOptions.launchNameFilter = value;
                            model.setWidgetOptions(widgetOptions);
                        }
                    }
                },
                {
                    control: 'static',
                    options: {
                        action: 'metadata_fields',
                        fields: ['name', 'start_time']
                    }
                }
            ]);

            return async.promise();
        }
    };
});
<|endoftext|>


<commit_before>/*
 * @project {{=it.name}}
 * @author Larry Battle
 * @license {{=it.license.overview}}
 * @date 07/02/2012
 */
(function(root){
	var Input = function () {
		this.z = null;
		this.type = null;
		this.terms = null;
		this.constraints = null;
		this.isStandardMode = false;
	};
	// Holds constants
	Input.parse = function (type, z, constraints) {
		Input.checkForInputError(type, z, constraints);
		var obj = new Input();
		obj.type = type;
		obj.z = YASMIJ.Expression.parse(z);
		obj.constraints = YASMIJ.Input.getArrOfConstraints(constraints);
		obj.setTermNames();
		obj.checkConstraints();
		return obj;
	};
	Input.getArrOfConstraints = function (arr) {
		arr = (YASMIJ.Matrix.isArray(arr)) ? arr : [arr];
		var constraints = [],
		i = arr.length;
		while (i--) {
			constraints[i] = YASMIJ.Constraint.parse(arr[i]);
		}
		return constraints;
	};
	Input.getErrors = function (type, z, constraints) {
		var errMsgs = [];
		if (typeof z !== "string") {
			errMsgs.push("z must be a string.");
		}
		if (type !== "maximize" && type !== "minimize") {
			errMsgs.push("`maximize` and `minimize` are the only types that is currently supported.");
		}
		if (!YASMIJ.Matrix.isArray(constraints) || !constraints.length) {
			errMsgs.push("Constraints must be an array with at least one element.");
		}
		return errMsgs;
	};
	/**
	* Returns the problem type, this function assume all the constraints have
	* variables on the left and constants on the right.
	* @return {String}
	*/
	Input.prototype.computeType = function(){
		var type;
		var allLessThan = this.doAllConstrainsHaveRelation( /<=?/ );
		var allGreaterThan = this.doAllConstrainsHaveRelation( />=?/ );
		return Input.TYPES.STANDARD_MAX;
		if( /max/.test( this.type ) ){
			return allLessThan ? Input.TYPES.STANDARD_MAX : Input.TYPES.NONSTANDARD_MAX;
		}
		if( /min/.test( this.type ) ){
			return allGreaterThan ? Input.TYPES.STANDARD_MIN : Input.TYPES.NONSTANDARD_MIN;
		}
		return type;
	};
	/**
	* Checks if all constraints the same comparison.
	* @param {String|RegExp} comparison
	* @return {Boolean}
	*/
	Input.prototype.doAllConstrainsHaveRelation = function(comparison){
		comparison = new RegExp(comparison);
		return this.allConstraints(function(i, constraint){
			return comparison.test(constraint.comparison);
		});
	};
	/**
	* Checks if the callback returns a truthy value for all constraints.
	* @param {Function} fn - callback
	* @return {Boolean}
	*/
	Input.prototype.allConstraints = function (fn) {
		var result = true;
		for (var i = 0, len = this.constraints.length; i < len; i++) {
			result = result && !!fn(i, this.constraints[i], this.constraints);
		}
		return result;
	};
	/**
	* Iterates over a the constraints, executing the callback for each element.
	* @param {Function} fn - callback
	* @return {Boolean}
	*/
	Input.prototype.forEachConstraint = function (fn) {
		for (var i = 0, len = this.constraints.length; i < len; i++) {
			fn(i, this.constraints[i], this.constraints);
		}
	};
	Input.prototype.addNumbersToSlacks = function () {
		var c = this.constraints,
		slackI = 1;
		for (var i = 0, len = c.length; i < len; i++) {
			if (c[i].slack) {
				c[i].updateSlack("slack" + slackI);
				slackI++;
			}
		}
	};
	Input.prototype.getTermNames = function (onlyVariables) {
		var vars = [],
		i = this.constraints.length;
		while (i--) {
			vars = vars.concat(this.constraints[i].getTermNames(onlyVariables));
		}
		return YASMIJ.getUniqueArray(vars).sort();
	};
	Input.prototype.setTermNames = function () {
		this.terms = this.getTermNames();
	};
	Input.prototype.getZTermNotInAnyOfTheConstraints = function () {
		var varMissing = "",
		terms = this.z.getTermNames(),
		term,
		i = 0,
		iLen = terms.length;

		for (; !varMissing && i < iLen; i++) {
			term = terms[i];
			for (var j = 0, jLen = this.constraints.length; j < jLen; j++) {
				if (this.constraints[j].leftSide.terms[term]) {
					break;
				}
			}
			if (j === jLen) {
				varMissing = term;
			}
		}
		return varMissing;
	};
	Input.prototype.checkConstraints = function () {
		var errMsg = [],
		missingZVar = this.getZTermNotInAnyOfTheConstraints();
		if (missingZVar) {
			errMsg.push("`" + missingZVar + "`, from the objective function, should appear least once in a constraint.");
		}
		return errMsg;
	};
	Input.checkForInputError = function (type, z, constraints) {
		var arr = Input.getErrors(type, z, constraints);
		if (arr && arr.length) {
			throw new Error("Input Error: " + arr.join('\n'));
		}
	};
	Input.prototype.toString = function () {
		return [this.type + " z = " + this.z, "where " + this.constraints.join(", ")].join(", ");
	};
	Input.prototype.convertConstraintsToMaxForm = function () {
		var c = this.constraints;
		for (var i = 0, len = c.length; i < len; i++) {
			c[i] = c[i].convertToStandardMaxForm();
		}
	};
	Input.prototype.convertToStandardForm = function () {
		if (this.isStandardMode) {
			return this;
		}
		if (/min/.test(this.type)) {
			this.z = this.z.inverse();
		}
		this.convertConstraintsToMaxForm();
		this.addNumbersToSlacks();
		this.setTermNames();
		this.isStandardMode = true;
		return this;
	};
	root.Input = Input;
}(YASMIJ));
<commit_msg>Update YASMIJ.Input.js<commit_after>/*
 * @project {{=it.name}}
 * @author Larry Battle
 * @license {{=it.license.overview}}
 * @date 07/02/2012
 */
(function(root){
	var Input = function () {
		this.z = null;
		this.type = null;
		this.terms = null;
		this.constraints = null;
		this.isStandardMode = false;
	};
	// Holds constants
	Input.parse = function (type, z, constraints) {
		Input.checkForInputError(type, z, constraints);
		var obj = new Input();
		obj.type = type;
		obj.z = YASMIJ.Expression.parse(z);
		obj.constraints = YASMIJ.Input.getArrOfConstraints(constraints);
		obj.setTermNames();
		obj.checkConstraints();
		return obj;
	};
	Input.getArrOfConstraints = function (arr) {
		arr = (YASMIJ.Matrix.isArray(arr)) ? arr : [arr];
		var constraints = [],
		i = arr.length;
		while (i--) {
			constraints[i] = YASMIJ.Constraint.parse(arr[i]);
		}
		return constraints;
	};
	Input.getErrors = function (type, z, constraints) {
		var errMsgs = [];
		if (typeof z !== "string") {
			errMsgs.push("z must be a string.");
		}
		if (type !== "maximize" && type !== "minimize") {
			errMsgs.push("`maximize` and `minimize` are the only types that is currently supported.");
		}
		if (!YASMIJ.Matrix.isArray(constraints) || !constraints.length) {
			errMsgs.push("Constraints must be an array with at least one element.");
		}
		return errMsgs;
	};
	/**
	* Returns the problem type.
	* @note this function assume all the constraints have
	* variables on the left and constants on the right.
	* @return {String}
	*/
	Input.prototype.computeType = function(){
		var hasLessThan = this.doAnyConstrainsHaveRelation( /<=?/ );
		var hasGreaterThan = this.doAnyConstrainsHaveRelation( />=?/ );

		if( /max/.test( this.type ) ){
			return hasGreaterThan ? YASMIJ.CONST.NONSTANDARD_MAX : YASMIJ.CONST.STANDARD_MAX;
		}
		if( /min/.test( this.type ) ){
			return hasLessThan ? YASMIJ.CONST.NONSTANDARD_MIN : YASMIJ.CONST.STANDARD_MIN;
		}
	};
	/**
	* Checks if any constraints the same comparison.
	* @param {String|RegExp} comparison
	* @return {Boolean}
	*/
	Input.prototype.doAnyConstrainsHaveRelation = function(comparison){
		comparison = new RegExp(comparison);
		return this.anyConstraints(function(i, constraint){
			return comparison.test(constraint.comparison);
		});
	};
	/**
	* Checks if all constraints the same comparison.
	* @param {String|RegExp} comparison
	* @return {Boolean}
	*/
	Input.prototype.doAllConstrainsHaveRelation = function(comparison){
		comparison = new RegExp(comparison);
		return this.allConstraints(function(i, constraint){
			return comparison.test(constraint.comparison);
		});
	};
	/**
	* Checks if the callback returns a truthy value for any constraints.
	* @param {Function} fn - callback
	* @return {Boolean}
	*/
	Input.prototype.anyConstraints = function (fn) {
		for (var i = 0, len = this.constraints.length; i < len; i++) {
			if( fn(i, this.constraints[i], this.constraints) ){
				return true;
			}
		}
		return false;
	};
	/**
	* Checks if the callback returns a truthy value for all constraints.
	* @param {Function} fn - callback
	* @return {Boolean}
	*/
	Input.prototype.allConstraints = function (fn) {
		var result = true;
		for (var i = 0, len = this.constraints.length; i < len; i++) {
			result = result && !!fn(i, this.constraints[i], this.constraints);
		}
		return result;
	};
	/**
	* Iterates over a the constraints, executing the callback for each element.
	* @param {Function} fn - callback
	* @return {Boolean}
	*/
	Input.prototype.forEachConstraint = function (fn) {
		for (var i = 0, len = this.constraints.length; i < len; i++) {
			fn(i, this.constraints[i], this.constraints);
		}
	};
	Input.prototype.addNumbersToSlacks = function () {
		var c = this.constraints,
		slackI = 1;
		for (var i = 0, len = c.length; i < len; i++) {
			if (c[i].slack) {
				c[i].updateSlack("slack" + slackI);
				slackI++;
			}
		}
	};
	Input.prototype.getTermNames = function (onlyVariables) {
		var vars = [],
		i = this.constraints.length;
		while (i--) {
			vars = vars.concat(this.constraints[i].getTermNames(onlyVariables));
		}
		return YASMIJ.getUniqueArray(vars).sort();
	};
	Input.prototype.setTermNames = function () {
		this.terms = this.getTermNames();
	};
	Input.prototype.getZTermNotInAnyOfTheConstraints = function () {
		var varMissing = "",
		terms = this.z.getTermNames(),
		term,
		i = 0,
		iLen = terms.length;

		for (; !varMissing && i < iLen; i++) {
			term = terms[i];
			for (var j = 0, jLen = this.constraints.length; j < jLen; j++) {
				if (this.constraints[j].leftSide.terms[term]) {
					break;
				}
			}
			if (j === jLen) {
				varMissing = term;
			}
		}
		return varMissing;
	};
	Input.prototype.checkConstraints = function () {
		var errMsg = [],
		missingZVar = this.getZTermNotInAnyOfTheConstraints();
		if (missingZVar) {
			errMsg.push("`" + missingZVar + "`, from the objective function, should appear least once in a constraint.");
		}
		return errMsg;
	};
	Input.checkForInputError = function (type, z, constraints) {
		var arr = Input.getErrors(type, z, constraints);
		if (arr && arr.length) {
			throw new Error("Input Error: " + arr.join('\n'));
		}
	};
	Input.prototype.toString = function () {
		return [this.type + " z = " + this.z, "where " + this.constraints.join(", ")].join(", ");
	};
	Input.prototype.convertConstraintsToMaxForm = function () {
		var c = this.constraints;
		for (var i = 0, len = c.length; i < len; i++) {
			c[i] = c[i].convertToStandardMaxForm();
		}
	};
	Input.prototype.convertToStandardForm = function () {
		if (this.isStandardMode) {
			return this;
		}
		if (/min/.test(this.type)) {
			this.z = this.z.inverse();
		}
		this.convertConstraintsToMaxForm();
		this.addNumbersToSlacks();
		this.setTermNames();
		this.isStandardMode = true;
		return this;
	};
	root.Input = Input;
}(YASMIJ));
<|endoftext|>


<commit_before>/**
 * @file Thead component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Th from '../_Th';

import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableFragment from '../_statics/TableFragment';
import TableCalculation from '../_vendors/TableCalculation';

class Thead extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    render() {

        const {
                className, style, columns, data,
                sorting, defaultSortingType, sortingAscIconCls, sortingDescIconCls,
                onSortChange
            } = this.props,

            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.HEAD, columns);

        return (

                    {
                        columnsWithSpan ?
                            columnsWithSpan.map(({column, span}, index) => column ?
                                <Th key={index}
                                    className={column.headClassName}
                                    style={column.headStyle}
                                    renderer={column.headRenderer}
                                    align={column.headAlign}
                                    colIndex={index}
                                    data={data}
                                    span={span}
                                    sorting={sorting}
                                    defaultSortingType={column.defaultSortingType || defaultSortingType}
                                    sortingAscIconCls={sortingAscIconCls}
                                    sortingDescIconCls={sortingDescIconCls}
                                    sortable={column.sortable}
                                    sortingProp={column.sortingProp}
                                    onSortChange={onSortChange}/>
                                :
                                null
                            )
                            :
                            null
                    }

        );

    }
}

Thead.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in header.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        headRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table.
         * (1) data key，example： 'id'
         * (2) data key tamplate，example：'${id} - ${name}'
         * (3) callback，example：function (rowData, rowIndex, colIndex) {return rowData.id;}
         */
        bodyRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in footer.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        footRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.array,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),
    defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType)),
    sortingAscIconCls: PropTypes.string,
    sortingDescIconCls: PropTypes.string,

    onSortChange: PropTypes.func

};

Thead.defaultProps = {
    defaultSortingType: SortingType.ASC,
    sortingAscIconCls: 'fas fa-angle-up',
    sortingDescIconCls: 'fas fa-angle-down'
};

export default Thead;
<commit_msg>update Thead<commit_after>/**
 * @file Thead component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Th from '../_Th';

import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableFragment from '../_statics/TableFragment';
import TableCalculation from '../_vendors/TableCalculation';

class Thead extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    render() {

        const {
                className, style, columns, baseColIndex,
                sorting, defaultSortingType, sortingAscIconCls, sortingDescIconCls,
                onSortChange,
                ...restProps
            } = this.props,

            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.HEAD, columns);

        return (

                    {
                        columnsWithSpan ?
                            columnsWithSpan.map(({column, span}, colIndex) => column ?
                                <Th {...restProps}
                                    key={colIndex}
                                    className={column.headClassName}
                                    style={column.headStyle}
                                    renderer={column.headRenderer}
                                    align={column.headAlign}
                                    colIndex={baseColIndex + colIndex}
                                    span={span}
                                    sorting={sorting}
                                    defaultSortingType={column.defaultSortingType || defaultSortingType}
                                    sortingAscIconCls={sortingAscIconCls}
                                    sortingDescIconCls={sortingDescIconCls}
                                    sortable={column.sortable}
                                    sortingProp={column.sortingProp}
                                    onSortChange={onSortChange}/>
                                :
                                null
                            )
                            :
                            null
                    }

        );

    }
}

Thead.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in header.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        headRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table.
         * (1) data key，example： 'id'
         * (2) data key tamplate，example：'${id} - ${name}'
         * (3) callback，example：function (rowData, rowIndex, colIndex) {return rowData.id;}
         */
        bodyRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in footer.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        footRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.array,
    baseColIndex: PropTypes.number,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),
    defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType)),
    sortingAscIconCls: PropTypes.string,
    sortingDescIconCls: PropTypes.string,

    onSortChange: PropTypes.func

};

Thead.defaultProps = {

    baseColIndex: 0,

    defaultSortingType: SortingType.ASC,
    sortingAscIconCls: 'fas fa-angle-up',
    sortingDescIconCls: 'fas fa-angle-down'

};

export default Thead;
<|endoftext|>


<commit_before>/**
 * @file Thead component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Components
import ResizableTh from '../_ResizableTh';
import Th from '../_Th';

// Statics
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';
import TableFragment from '../_statics/TableFragment';

// Vendors
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';

class Thead extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getColumnsSpan = row => {
        const {data, onRequestColumnsSpan} = this.props;
        return onRequestColumnsSpan ?
            onRequestColumnsSpan(TableFragment.HEAD, row, data)
            :
            TC.getColumnsSpan(TableFragment.HEAD, row, data);
    };

    render() {

        const {
            className, style, columns, baseColIndex, data, ignoreColumnSpan,
            sorting, defaultSortingType, sortingAscIconCls, sortingDescIconCls,
            isColumnResizable, minColumnWidth, maxColumnWidth,
            onSortChange,
            ...restProps
        } = this.props;

        return (

                {
                    columns && columns.map((row, rowIndex) => row ?

                            {
                                (
                                    this.getColumnsSpan(row)?.map(({column, span}, colIndex) => column ?
                                        <ResizableTh resizable={isColumnResizable && !column.children}
                                                     minWidth={minColumnWidth}
                                                     maxWidth={maxColumnWidth}>
                                            <Th {...restProps}
                                                key={colIndex}
                                                className={column.headClassName}
                                                style={column.headStyle}
                                                data={data}
                                                renderer={column.headRenderer}
                                                align={column.headAlign || column.align}
                                                colIndex={baseColIndex + colIndex}
                                                rowSpan={column.rowSpan}
                                                colSpan={ignoreColumnSpan ? null : column.colSpan}
                                                noWrap={TC.handleNoWrap(column.headNoWrap, column.noWrap, {
                                                    data,
                                                    rowIndex,
                                                    colIndex: baseColIndex + colIndex,
                                                    tableData: data
                                                })}
                                                sorting={sorting}
                                                defaultSortingType={column.defaultSortingType || defaultSortingType}
                                                sortingAscIconCls={sortingAscIconCls}
                                                sortingDescIconCls={sortingDescIconCls}
                                                sortable={column.sortable}
                                                sortingProp={column.sortingProp}
                                                onSortChange={onSortChange}/>
                                        </ResizableTh>
                                        :
                                        null
                                    )
                                ) || null
                            }

                        :
                        null
                    )
                }

        );

    }
}

Thead.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    }))).isRequired,

    data: PropTypes.array,
    baseColIndex: PropTypes.number,
    ignoreColumnSpan: PropTypes.bool,
    scrollEl: PropTypes.object,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),
    defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType)),
    sortingAscIconCls: PropTypes.string,
    sortingDescIconCls: PropTypes.string,
    isClickSorting: PropTypes.bool,

    /**
     * column resizable
     */
    isColumnResizable: PropTypes.bool,
    minColumnWidth: PropTypes.number,
    maxColumnWidth: PropTypes.number,

    onSortChange: PropTypes.func,
    onRequestColumnsSpan: PropTypes.func

};

Thead.defaultProps = {

    baseColIndex: 0,
    ignoreColumnSpan: false,

    /**
     * sorting
     */
    defaultSortingType: SortingType.ASC,
    sortingAscIconCls: 'fas fa-sort-up',
    sortingDescIconCls: 'fas fa-sort-down',
    isClickSorting: true,

    /**
     * column resizable
     */
    isColumnResizable: false,
    minColumnWidth: 40,
    maxColumnWidth: Infinity

};

export default Thead;
<commit_msg>update Thead<commit_after>/**
 * @file Thead component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Components
import Th from '../_Th';

// Statics
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';
import TableFragment from '../_statics/TableFragment';

// Vendors
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';

class Thead extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getColumnsSpan = row => {
        const {data, onRequestColumnsSpan} = this.props;
        return onRequestColumnsSpan ?
            onRequestColumnsSpan(TableFragment.HEAD, row, data)
            :
            TC.getColumnsSpan(TableFragment.HEAD, row, data);
    };

    render() {

        const {

            className, style, columns, baseColIndex, data, ignoreColumnSpan,
            sorting, defaultSortingType, sortingAscIconCls, sortingDescIconCls,
            onSortChange,

            ...restProps

        } = this.props;

        return (

                {
                    columns && columns.map((row, rowIndex) => row ?

                            {
                                (
                                    this.getColumnsSpan(row)?.map(({column, span}, colIndex) => column ?
                                        <Th {...restProps}
                                            key={colIndex}
                                            className={column.headClassName}
                                            style={column.headStyle}
                                            width={column.width}
                                            data={data}
                                            renderer={column.headRenderer}
                                            align={column.headAlign || column.align}
                                            colIndex={baseColIndex + colIndex}
                                            rowSpan={column.rowSpan}
                                            colSpan={ignoreColumnSpan ? null : column.colSpan}
                                            noWrap={TC.handleNoWrap(column.headNoWrap, column.noWrap, {
                                                data,
                                                rowIndex,
                                                colIndex: baseColIndex + colIndex,
                                                tableData: data
                                            })}
                                            sorting={sorting}
                                            defaultSortingType={column.defaultSortingType || defaultSortingType}
                                            sortingAscIconCls={sortingAscIconCls}
                                            sortingDescIconCls={sortingDescIconCls}
                                            sortable={column.sortable}
                                            sortingProp={column.sortingProp}
                                            onSortChange={onSortChange}/>
                                        :
                                        null
                                    )
                                ) || null
                            }

                        :
                        null
                    )
                }

        );

    }
}

Thead.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    }))).isRequired,

    data: PropTypes.array,
    baseColIndex: PropTypes.number,
    ignoreColumnSpan: PropTypes.bool,
    scrollEl: PropTypes.object,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),
    defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType)),
    sortingAscIconCls: PropTypes.string,
    sortingDescIconCls: PropTypes.string,
    isClickSorting: PropTypes.bool,

    /**
     * column resizable
     */
    isColumnResizable: PropTypes.bool,
    minColumnWidth: PropTypes.number,
    maxColumnWidth: PropTypes.number,

    onSortChange: PropTypes.func,
    onRequestColumnsSpan: PropTypes.func,
    onColumnsWidthChange: PropTypes.func

};

Thead.defaultProps = {

    baseColIndex: 0,
    ignoreColumnSpan: false,

    /**
     * sorting
     */
    defaultSortingType: SortingType.ASC,
    sortingAscIconCls: 'fas fa-sort-up',
    sortingDescIconCls: 'fas fa-sort-down',
    isClickSorting: true,

    /**
     * column resizable
     */
    isColumnResizable: false,
    minColumnWidth: 40,
    maxColumnWidth: Infinity

};

export default Thead;
<|endoftext|>