<commit_before>import React from 'react';

import SPELLS from 'common/SPELLS';
import SpellLink from 'common/SpellLink';
import CoreAbilities from 'parser/core/modules/Abilities';

class Abilities extends CoreAbilities {
  spellbook() {
    const combatant = this.selectedCombatant;
    return [
      //Rotation Spells
      {
        spell: SPELLS.DEMONS_BITE,
        enabled: !combatant.hasTalent(SPELLS.DEMON_BLADES_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CHAOS_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.ANNIHILATION, //During meta chaos strike becomes this.
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: [SPELLS.BLADE_DANCE, SPELLS.DEATH_SWEEP],
        category: combatant.hasTalent(SPELLS.FIRST_BLOOD_TALENT.id) ? Abilities.SPELL_CATEGORIES.ROTATIONAL : Abilities.SPELL_CATEGORIES.ROTATIONAL_AOE,
        cooldown: haste => combatant.hasBuff(SPELLS.METAMORPHOSIS_HAVOC_BUFF.id) ? 9 / (1 + haste) : 15 / (1 + haste),
        //Blade dance = 15s cd
        //Death Sweep = 9s cd
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: combatant.hasTalent(SPELLS.FIRST_BLOOD_TALENT.id),
          recommendedEfficiency: 0.95,
          extraSuggestion: <>This should be part of your single target rotation due to the <SpellLink id={SPELLS.FIRST_BLOOD_TALENT.id} /> talent. This includes the <SpellLink id={SPELLS.DEATH_SWEEP.id} /> casts since they are the same ability and share their cooldowns.</>,
        },
      },
      {
        spell: SPELLS.FELBLADE_TALENT,
        enabled: combatant.hasTalent(SPELLS.FELBLADE_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        // Felblade cooldown can be reset by Shear or Demon Blades (when talented). But it's CD reset is not any event, so can't track if it resets or not.
        cooldown: haste => 15 / (1 + haste),
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: 'This is an important Fury generator spell. Try to always cast on cooldown, but beware to not waste the Fury generation it provides. And also it can be used to charge to the desired target, making it very strong movement spell.',
        },
      },
      {
        spell: SPELLS.IMMOLATION_AURA,
        // IMMOLATION_AURA is the ID for cast and the buff. But damage is done from IMMOLATION_AURA_INITIAL_HIT_DAMAGE and IMMOLATION_AURA_BUFF_DAMAGE
        buffSpellId: SPELLS.IMMOLATION_AURA.id,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 30 / (1 + haste),
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: 'This is an important Fury generator spell. Try to always cast on cooldown, but beware to not waste the Fury generation it provides.',
        },
      },
      {
        spell: SPELLS.ESSENCE_BREAK_TALENT,
        enabled: combatant.hasTalent(SPELLS.ESSENCE_BREAK_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 20,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: <>Pool your Fury before hand to maximizing casting <SpellLink id={SPELLS.CHAOS_STRIKE.id} /> / <SpellLink id={SPELLS.ANNIHILATION.id} /> during its buff window.</>,
        },
      },
      {
        spell: SPELLS.THROW_GLAIVE_HAVOC,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 9 / (1 + haste),
        gcd: {
          base: 1500,
        },
      },

      //Movement
      {
        spell: SPELLS.FEL_RUSH_CAST, //Becomes a rotational ability with the Momentum talent
        category: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id) ? Abilities.SPELL_CATEGORIES.ROTATIONAL : Abilities.SPELL_CATEGORIES.UTILITY,
        charges: 2,
        cooldown: 10,
        gcd: {
          static: 250,
        },
        castEfficiency: {
          suggestion: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id),
          recommendedEfficiency: 0.95,
          extraSuggestion: <>Use it to keep your <SpellLink id={SPELLS.MOMENTUM_TALENT.id} /> buff going.</>,
        },
      },
      {
        spell: SPELLS.VENGEFUL_RETREAT, //Becomes a rotational ability with the Momentum talent
        category: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id) ? Abilities.SPELL_CATEGORIES.ROTATIONAL : Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id) ? 20 : 25,
        // Not actually on the GCD but blocks all spells during its animation for 1 second. The issue is you can follow up any ability on the GCD with Vengeful Retreat, so it can still cause overlap.
        gcd: null,
        castEfficiency: {
          suggestion: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id),
          recommendedEfficiency: 0.95,
          extraSuggestion: <>Use it to generate Fury due to the <SpellLink id={SPELLS.MOMENTUM_TALENT.id} /> talent.</>,
        },
      },
      {
        spell: SPELLS.GLIDE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 1.5,
        gcd: null,
      },

      // CC, interupts, and utility
      {
        spell: SPELLS.FEL_ERUPTION_TALENT,
        enabled: combatant.hasTalent(SPELLS.FEL_ERUPTION_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CHAOS_NOVA,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: combatant.hasTalent(SPELLS.UNLEASHED_POWER_TALENT.id) ? 40 : 60,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.DISRUPT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 15,
        gcd: null,
      },
      {
        spell: SPELLS.CONSUME_MAGIC,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 10,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.TORMENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 8,
        gcd: null,
      },
      {
        spell: SPELLS.IMPRISON,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 45,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.SPECTRAL_SIGHT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },

      // DPS Cooldowns
      {
        spell: SPELLS.EYE_BEAM,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.FEL_BARRAGE_TALENT,
        enabled: combatant.hasTalent(SPELLS.FEL_BARRAGE_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 60,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: `This is a great AoE damage spell, but also does a great damage on single target. You should cast it as soon as it gets off cooldown. The only moment you can delay it's cast is if you already expect an add wave to maximize it's efficiency and damage output.`,
        },
      },
      {
        spell: SPELLS.GLAIVE_TEMPEST_TALENT,
        enabled: combatant.hasTalent(SPELLS.GLAIVE_TEMPEST_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 20,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: <>The only time you should delay casting <SpellLink id={SPELLS.GLAIVE_TEMPEST_TALENT.id} /> is when you're expecting adds to spawn soon.</>,
        },
      },

      // Big DPS Cooldowns
      {
        spell: SPELLS.METAMORPHOSIS_HAVOC,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        buffSpellId: SPELLS.METAMORPHOSIS_HAVOC_BUFF.id,
        cooldown: 300,
        gcd: null, // Logs track the "landing" spell which is not on GCD
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.80, //5 minute cd. You want some leeway in when to burn it.
        },
      },

      // Defensives
      {
        spell: SPELLS.BLUR,
        buffSpellId: SPELLS.BLUR.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 60,
      },
      {
        spell: SPELLS.DARKNESS,
        buffSpellId: SPELLS.DARKNESS.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 180,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.NETHERWALK_TALENT,
        enabled: combatant.hasTalent(SPELLS.NETHERWALK_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 180,
        gcd: {
          base: 1500,
        },
      },
    ];
  }
}

export default Abilities;
<commit_msg>Corrected glaive tempest cd with haste<commit_after>import React from 'react';

import SPELLS from 'common/SPELLS';
import SpellLink from 'common/SpellLink';
import CoreAbilities from 'parser/core/modules/Abilities';

class Abilities extends CoreAbilities {
  spellbook() {
    const combatant = this.selectedCombatant;
    return [
      //Rotation Spells
      {
        spell: SPELLS.DEMONS_BITE,
        enabled: !combatant.hasTalent(SPELLS.DEMON_BLADES_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CHAOS_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.ANNIHILATION, //During meta chaos strike becomes this.
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: [SPELLS.BLADE_DANCE, SPELLS.DEATH_SWEEP],
        category: combatant.hasTalent(SPELLS.FIRST_BLOOD_TALENT.id) ? Abilities.SPELL_CATEGORIES.ROTATIONAL : Abilities.SPELL_CATEGORIES.ROTATIONAL_AOE,
        cooldown: haste => combatant.hasBuff(SPELLS.METAMORPHOSIS_HAVOC_BUFF.id) ? 9 / (1 + haste) : 15 / (1 + haste),
        //Blade dance = 15s cd
        //Death Sweep = 9s cd
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: combatant.hasTalent(SPELLS.FIRST_BLOOD_TALENT.id),
          recommendedEfficiency: 0.95,
          extraSuggestion: <>This should be part of your single target rotation due to the <SpellLink id={SPELLS.FIRST_BLOOD_TALENT.id} /> talent. This includes the <SpellLink id={SPELLS.DEATH_SWEEP.id} /> casts since they are the same ability and share their cooldowns.</>,
        },
      },
      {
        spell: SPELLS.FELBLADE_TALENT,
        enabled: combatant.hasTalent(SPELLS.FELBLADE_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        // Felblade cooldown can be reset by Shear or Demon Blades (when talented). But it's CD reset is not any event, so can't track if it resets or not.
        cooldown: haste => 15 / (1 + haste),
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: 'This is an important Fury generator spell. Try to always cast on cooldown, but beware to not waste the Fury generation it provides. And also it can be used to charge to the desired target, making it very strong movement spell.',
        },
      },
      {
        spell: SPELLS.IMMOLATION_AURA,
        // IMMOLATION_AURA is the ID for cast and the buff. But damage is done from IMMOLATION_AURA_INITIAL_HIT_DAMAGE and IMMOLATION_AURA_BUFF_DAMAGE
        buffSpellId: SPELLS.IMMOLATION_AURA.id,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 30 / (1 + haste),
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: 'This is an important Fury generator spell. Try to always cast on cooldown, but beware to not waste the Fury generation it provides.',
        },
      },
      {
        spell: SPELLS.ESSENCE_BREAK_TALENT,
        enabled: combatant.hasTalent(SPELLS.ESSENCE_BREAK_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 20,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: <>Pool your Fury before hand to maximizing casting <SpellLink id={SPELLS.CHAOS_STRIKE.id} /> / <SpellLink id={SPELLS.ANNIHILATION.id} /> during its buff window.</>,
        },
      },
      {
        spell: SPELLS.THROW_GLAIVE_HAVOC,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 9 / (1 + haste),
        gcd: {
          base: 1500,
        },
      },

      //Movement
      {
        spell: SPELLS.FEL_RUSH_CAST, //Becomes a rotational ability with the Momentum talent
        category: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id) ? Abilities.SPELL_CATEGORIES.ROTATIONAL : Abilities.SPELL_CATEGORIES.UTILITY,
        charges: 2,
        cooldown: 10,
        gcd: {
          static: 250,
        },
        castEfficiency: {
          suggestion: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id),
          recommendedEfficiency: 0.95,
          extraSuggestion: <>Use it to keep your <SpellLink id={SPELLS.MOMENTUM_TALENT.id} /> buff going.</>,
        },
      },
      {
        spell: SPELLS.VENGEFUL_RETREAT, //Becomes a rotational ability with the Momentum talent
        category: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id) ? Abilities.SPELL_CATEGORIES.ROTATIONAL : Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id) ? 20 : 25,
        // Not actually on the GCD but blocks all spells during its animation for 1 second. The issue is you can follow up any ability on the GCD with Vengeful Retreat, so it can still cause overlap.
        gcd: null,
        castEfficiency: {
          suggestion: combatant.hasTalent(SPELLS.MOMENTUM_TALENT.id),
          recommendedEfficiency: 0.95,
          extraSuggestion: <>Use it to generate Fury due to the <SpellLink id={SPELLS.MOMENTUM_TALENT.id} /> talent.</>,
        },
      },
      {
        spell: SPELLS.GLIDE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 1.5,
        gcd: null,
      },

      // CC, interupts, and utility
      {
        spell: SPELLS.FEL_ERUPTION_TALENT,
        enabled: combatant.hasTalent(SPELLS.FEL_ERUPTION_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.CHAOS_NOVA,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: combatant.hasTalent(SPELLS.UNLEASHED_POWER_TALENT.id) ? 40 : 60,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.DISRUPT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 15,
        gcd: null,
      },
      {
        spell: SPELLS.CONSUME_MAGIC,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 10,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.TORMENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 8,
        gcd: null,
      },
      {
        spell: SPELLS.IMPRISON,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 45,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.SPECTRAL_SIGHT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },

      // DPS Cooldowns
      {
        spell: SPELLS.EYE_BEAM,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 30,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.FEL_BARRAGE_TALENT,
        enabled: combatant.hasTalent(SPELLS.FEL_BARRAGE_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 60,
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: `This is a great AoE damage spell, but also does a great damage on single target. You should cast it as soon as it gets off cooldown. The only moment you can delay it's cast is if you already expect an add wave to maximize it's efficiency and damage output.`,
        },
      },
      {
        spell: SPELLS.GLAIVE_TEMPEST_TALENT,
        enabled: combatant.hasTalent(SPELLS.GLAIVE_TEMPEST_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: haste => 20 / (1 + haste),
        gcd: {
          base: 1500,
        },
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
          extraSuggestion: <>The only time you should delay casting <SpellLink id={SPELLS.GLAIVE_TEMPEST_TALENT.id} /> is when you're expecting adds to spawn soon.</>,
        },
      },

      // Big DPS Cooldowns
      {
        spell: SPELLS.METAMORPHOSIS_HAVOC,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        buffSpellId: SPELLS.METAMORPHOSIS_HAVOC_BUFF.id,
        cooldown: 300,
        gcd: null, // Logs track the "landing" spell which is not on GCD
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.80, //5 minute cd. You want some leeway in when to burn it.
        },
      },

      // Defensives
      {
        spell: SPELLS.BLUR,
        buffSpellId: SPELLS.BLUR.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 60,
      },
      {
        spell: SPELLS.DARKNESS,
        buffSpellId: SPELLS.DARKNESS.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 180,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.NETHERWALK_TALENT,
        enabled: combatant.hasTalent(SPELLS.NETHERWALK_TALENT.id),
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 180,
        gcd: {
          base: 1500,
        },
      },
    ];
  }
}

export default Abilities;
<|endoftext|>


<commit_before>/**
 * @module select
 */

modules.define(
    'select',
    ['i-bem__dom', 'popup', 'menu', 'button', 'jquery', 'dom', 'keyboard__codes', 'strings__escape'],
    function(provide, BEMDOM, Popup, Menu, Button, $, dom, keyCodes, escape) {

/**
 * @exports
 * @class select
 * @bem
 *
 * @bemmod opened Represents opened state
 */
provide(BEMDOM.decl(this.name, /** @lends select.prototype */{
    beforeSetMod : {
        'opened' : {
            'true' : function() {
                return !this.hasMod('disabled');
            }
        },

        'focused' : {
            '' : function() {
                return !this._isPointerPressInProgress;
            }
        }
    },

    onSetMod : {
        'js' : {
            'inited' : function() {
                this._button = this.findBlockInside('button')
                    .on('click', this._onButtonClick, this);

                this._popup = this.findBlockInside('popup')
                    .setTarget(this._button)
                    .on({ modName : 'visible', modVal : '' }, this._onPopupHide, this);

                this._menu = this._popup.findBlockInside('menu')
                    .on({
                        'change' : this._onMenuChange,
                        'item-click' : this._onMenuItemClick
                    }, this);

                this._isPointerPressInProgress = false;

                this.hasMod('focused') && this._focus();

                this._updateMenuWidth();
            }
        },

        'focused' : {
            'true' : function() {
                this._focus();
            },

            '' : function() {
                this
                    .unbindFromDoc('keydown', this._onKeyDown)
                    .delMod('opened')
                    ._button
                        .delMod('focused');
            }
        },

        'opened' : {
            '*' : function(_, modVal) {
                this._menu.setMod('focused', modVal);
            },

            'true' : function() {
                this._updateMenuHeight();
                this._popup.setMod('visible');
                this
                    .bindToDoc('pointerpress', this._onDocPointerPress)
                    .setMod('focused')
                    ._hoverCheckedOrFirstItem();
            },

            '' : function() {
                this
                    .unbindFromDoc('pointerpress', this._onDocPointerPress)
                    ._popup.delMod('visible');
            }
        },

        'disabled' : {
            '*' : function(modName, modVal) {
                this._button.setMod(modName, modVal);
                this._menu.setMod(modName, modVal);
                this.elem('control').prop('disabled', modVal);
            },

            'true' : function() {
                this._popup.delMod('visible');
            }
        }
    },

    /**
     * Get value
     * @returns {*}
     */
    getVal : function() {
        return this._menu.getVal();
    },

    /**
     * Set value
     * @param {*} val
     * @returns {select} this
     */
    setVal : function(val) {
        this._menu.setVal(val);
        return this;
    },

    getName : function() {
        return this.params.name;
    },

    getDefaultParams : function() {
        return {
            optionsMaxHeight : Number.POSITIVE_INFINITY
        };
    },

    _focus : function() {
        this
            .bindToDoc('keydown', this._onKeyDown)
            ._button.setMod('focused');
    },

    _updateMenuWidth : function() {
        this._menu.domElem.css('min-width', this._button.domElem.outerWidth());

        this._popup.redraw();
    },

    _updateMenuHeight : function() {
        var drawingParams = this._popup.calcPossibleDrawingParams(),
            menuDomElem = this._menu.domElem,
            menuWidth = menuDomElem.outerWidth(),
            bestHeight = 0;

        drawingParams.forEach(function(params) {
            params.width >= menuWidth && params.height > bestHeight && (bestHeight = params.height);
        });

        bestHeight && menuDomElem.css('max-height', Math.min(this.params.optionsMaxHeight, bestHeight));
    },

    _getCheckedItems : function() {
        return this._menu.getItems().filter(function(item) {
            return item.hasMod('checked');
        });
    },

    _hoverCheckedOrFirstItem : function() { // NOTE: may be it should be moved to menu
        (this._getCheckedItems()[0] || this._menu.getItems()[0])
            .setMod('hovered');
    },

    _onKeyDown : function(e) {
        if(!this.hasMod('opened') &&
                (e.keyCode === keyCodes.UP || e.keyCode === keyCodes.DOWN) && !e.shiftKey) {
            e.preventDefault();
            this.setMod('opened');
        }
    },

    _onMenuChange : function() {
        this._updateControl();
        this._updateButton();
        this._updateMenuWidth();

        this.emit('change');
    },

    _onMenuItemClick : function() {},

    _updateControl : function() {},

    _updateButton : function() {},

    _onButtonClick : function() {
        this.toggleMod('opened');
    },

    _onButtonFocusChange : function(e, data) {
        this.setMod('focused', data.modVal);
    },

    _onPopupHide : function() {
        this.delMod('opened');
    },

    _onDocPointerPress : function(e) {
        if(this._isEventInPopup(e)) {
            e.pointerType === 'mouse' && e.preventDefault(); // prevents button blur in most desktop browsers
            this._isPointerPressInProgress = true;
            this.bindToDoc(
                'pointerrelease',
                { focusedHardMod : this._button.getMod('focused-hard') },
                this._onDocPointerRelease);
        }
    },

    _onDocPointerRelease : function(e) {
        this._isPointerPressInProgress = false;
        this
            .unbindFromDoc('pointerrelease', this._onDocPointerRelease)
            ._button
                .toggleMod('focused', true, '', this._isEventInPopup(e))
                .setMod('focused-hard', e.data.focusedHardMod);
    },

    _isEventInPopup : function(e) {
        return dom.contains(this._popup.domElem, $(e.target));
    }
}, /** @lends select */{
    live : function() {
        this.liveInitOnBlockInsideEvent(
            { modName : 'focused', modVal : '*' },
            'button',
            this.prototype._onButtonFocusChange);
    },

    _createControlHTML : function(name, val) {
        // Using string concatenation to not depend on template engines
        return '<input ' +
            'type="hidden" ' +
            'name="' + name + '" ' +
            'class="' + this.buildClass('control') + '" ' +
            'value="' + escape.attr(typeof val === 'object'? JSON.stringify(val) : val) + '"/>';
    }
}));

});
<commit_msg>select: Check jsdoc<commit_after>/**
 * @module select
 */

modules.define(
    'select',
    ['i-bem__dom', 'popup', 'menu', 'button', 'jquery', 'dom', 'keyboard__codes', 'strings__escape'],
    function(provide, BEMDOM, Popup, Menu, Button, $, dom, keyCodes, escape) {

/**
 * @exports
 * @class select
 * @bem
 *
 * @bemmod opened Represents opened state
 */
provide(BEMDOM.decl(this.name, /** @lends select.prototype */{
    beforeSetMod : {
        'opened' : {
            'true' : function() {
                return !this.hasMod('disabled');
            }
        },

        'focused' : {
            '' : function() {
                return !this._isPointerPressInProgress;
            }
        }
    },

    onSetMod : {
        'js' : {
            'inited' : function() {
                this._button = this.findBlockInside('button')
                    .on('click', this._onButtonClick, this);

                this._popup = this.findBlockInside('popup')
                    .setTarget(this._button)
                    .on({ modName : 'visible', modVal : '' }, this._onPopupHide, this);

                this._menu = this._popup.findBlockInside('menu')
                    .on({
                        'change' : this._onMenuChange,
                        'item-click' : this._onMenuItemClick
                    }, this);

                this._isPointerPressInProgress = false;

                this.hasMod('focused') && this._focus();

                this._updateMenuWidth();
            }
        },

        'focused' : {
            'true' : function() {
                this._focus();
            },

            '' : function() {
                this
                    .unbindFromDoc('keydown', this._onKeyDown)
                    .delMod('opened')
                    ._button
                        .delMod('focused');
            }
        },

        'opened' : {
            '*' : function(_, modVal) {
                this._menu.setMod('focused', modVal);
            },

            'true' : function() {
                this._updateMenuHeight();
                this._popup.setMod('visible');
                this
                    .bindToDoc('pointerpress', this._onDocPointerPress)
                    .setMod('focused')
                    ._hoverCheckedOrFirstItem();
            },

            '' : function() {
                this
                    .unbindFromDoc('pointerpress', this._onDocPointerPress)
                    ._popup.delMod('visible');
            }
        },

        'disabled' : {
            '*' : function(modName, modVal) {
                this._button.setMod(modName, modVal);
                this._menu.setMod(modName, modVal);
                this.elem('control').prop('disabled', modVal);
            },

            'true' : function() {
                this._popup.delMod('visible');
            }
        }
    },

    /**
     * Get value
     * @returns {*}
     */
    getVal : function() {
        return this._menu.getVal();
    },

    /**
     * Set value
     * @param {*} val
     * @returns {select} this
     */
    setVal : function(val) {
        this._menu.setVal(val);
        return this;
    },

    /**
     * Get name
     * @returns {String}
     */
    getName : function() {
        return this.params.name;
    },

    getDefaultParams : function() {
        return {
            optionsMaxHeight : Number.POSITIVE_INFINITY
        };
    },

    _focus : function() {
        this
            .bindToDoc('keydown', this._onKeyDown)
            ._button.setMod('focused');
    },

    _updateMenuWidth : function() {
        this._menu.domElem.css('min-width', this._button.domElem.outerWidth());

        this._popup.redraw();
    },

    _updateMenuHeight : function() {
        var drawingParams = this._popup.calcPossibleDrawingParams(),
            menuDomElem = this._menu.domElem,
            menuWidth = menuDomElem.outerWidth(),
            bestHeight = 0;

        drawingParams.forEach(function(params) {
            params.width >= menuWidth && params.height > bestHeight && (bestHeight = params.height);
        });

        bestHeight && menuDomElem.css('max-height', Math.min(this.params.optionsMaxHeight, bestHeight));
    },

    _getCheckedItems : function() {
        return this._menu.getItems().filter(function(item) {
            return item.hasMod('checked');
        });
    },

    _hoverCheckedOrFirstItem : function() { // NOTE: may be it should be moved to menu
        (this._getCheckedItems()[0] || this._menu.getItems()[0])
            .setMod('hovered');
    },

    _onKeyDown : function(e) {
        if(!this.hasMod('opened') &&
                (e.keyCode === keyCodes.UP || e.keyCode === keyCodes.DOWN) && !e.shiftKey) {
            e.preventDefault();
            this.setMod('opened');
        }
    },

    _onMenuChange : function() {
        this._updateControl();
        this._updateButton();
        this._updateMenuWidth();

        this.emit('change');
    },

    _onMenuItemClick : function() {},

    _updateControl : function() {},

    _updateButton : function() {},

    _onButtonClick : function() {
        this.toggleMod('opened');
    },

    _onButtonFocusChange : function(e, data) {
        this.setMod('focused', data.modVal);
    },

    _onPopupHide : function() {
        this.delMod('opened');
    },

    _onDocPointerPress : function(e) {
        if(this._isEventInPopup(e)) {
            e.pointerType === 'mouse' && e.preventDefault(); // prevents button blur in most desktop browsers
            this._isPointerPressInProgress = true;
            this.bindToDoc(
                'pointerrelease',
                { focusedHardMod : this._button.getMod('focused-hard') },
                this._onDocPointerRelease);
        }
    },

    _onDocPointerRelease : function(e) {
        this._isPointerPressInProgress = false;
        this
            .unbindFromDoc('pointerrelease', this._onDocPointerRelease)
            ._button
                .toggleMod('focused', true, '', this._isEventInPopup(e))
                .setMod('focused-hard', e.data.focusedHardMod);
    },

    _isEventInPopup : function(e) {
        return dom.contains(this._popup.domElem, $(e.target));
    }
}, /** @lends select */{
    live : function() {
        this.liveInitOnBlockInsideEvent(
            { modName : 'focused', modVal : '*' },
            'button',
            this.prototype._onButtonFocusChange);
    },

    _createControlHTML : function(name, val) {
        // Using string concatenation to not depend on template engines
        return '<input ' +
            'type="hidden" ' +
            'name="' + name + '" ' +
            'class="' + this.buildClass('control') + '" ' +
            'value="' + escape.attr(typeof val === 'object'? JSON.stringify(val) : val) + '"/>';
    }
}));

});
<|endoftext|>


<commit_before>const defaultState = {
  allPlaylists: [],
  pinnedPlaylists: [],
  loadMoreButton: false,

  videoThumbsForModal: [],
  loadMoreButtonForModal: false,
  allVideosLoadedForModal: false,

  addPlaylistModalShown: false,
  editPlaylistModalType: null,
  selectedModalThumbs: [],

  selectPlaylistsToPinModalShown: false,
  loadMorePlaylistsToPinButton: false,
  playlistsToPin: [],

  reorderPinnedPlaylistsModalShown: false
};

let defaultPlaylists,
    defaultPinnedPlaylists

export default function PlaylistReducer(state = defaultState, action) {
  let loadMoreButtonForModal = false;
  let allVideosLoadedForModal = false;
  let loadMorePlaylistsToPinButton = false;
  switch(action.type) {
    case 'GET_PLAYLISTS':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      let loadMoreButton = false;
      if (action.data.playlists.length > 3) {
        action.data.playlists.pop();
        loadMoreButton = true;
      }
      if (action.initialRun) {
        defaultPlaylists = action.data.playlists;
        return {
          ...state,
          allPlaylists: defaultPlaylists,
          loadMoreButton
        }
      } else {
        return {
          ...state,
          allPlaylists: state.allPlaylists.concat(action.data.playlists),
          loadMoreButton
        };
      }
    case 'GET_PINNED_PLAYLISTS':
      defaultPinnedPlaylists = action.data.playlists;
      return {
        ...state,
        pinnedPlaylists: defaultPinnedPlaylists
      }
    case 'GET_VIDEOS_FOR_MODAL':
      if (action.data.length > 18) {
        action.data.pop();
        loadMoreButtonForModal = true;
      } else {
        allVideosLoadedForModal = true;
      }
      if (action.initialRun) {
        return {
          ...state,
          videoThumbsForModal: action.data,
          loadMoreButtonForModal,
          allVideosLoadedForModal
        }
      } else {
        return {
          ...state,
          videoThumbsForModal: state.videoThumbsForModal.concat(action.data),
          loadMoreButtonForModal,
          allVideosLoadedForModal
        }
      }
    case 'ADD_PL_MODAL_OPEN':
      return {
        ...state,
        addPlaylistModalShown: true
      };
    case 'ADD_PL_MODAL_CLOSE':
      return {
        ...state,
        addPlaylistModalShown: false
      }
    case 'SELECT_PL_TO_PIN_OPEN':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      if (action.data.result.length > 10) {
        action.data.result.pop();
        loadMorePlaylistsToPinButton = true;
      }
      let playlistsToPin = action.data.result.map(item => {
        return {
          title: item.title,
          id: item.id
        }
      })
      return {
        ...state,
        playlistsToPin,
        loadMorePlaylistsToPinButton,
        selectPlaylistsToPinModalShown: true
      }
    case 'SELECT_PL_TO_PIN_CLOSE':
      return {
        ...state,
        loadMorePlaylistsToPinButton: false,
        selectPlaylistsToPinModalShown: false
      }
    case 'LOAD_MORE_PLAYLIST_LIST':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      if (action.data.result.length > 10) {
        action.data.result.pop();
        loadMorePlaylistsToPinButton = true;
      }
      let morePlaylistsToPin = action.data.result.map(item => {
        return {
          title: item.title,
          id: item.id
        }
      })
      return {
        ...state,
        playlistsToPin: state.playlistsToPin.concat(morePlaylistsToPin),
        loadMorePlaylistsToPinButton
      }
    case 'CHANGE_PINNED_PLAYLISTS':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      if (action.data.playlists) {
        defaultPinnedPlaylists = action.data.playlists;
        return {
          ...state,
          pinnedPlaylists: defaultPinnedPlaylists
        }
      }
      return state;
    case 'REORDER_PINNED_PL_OPEN':
      return {
        ...state,
        reorderPinnedPlaylistsModalShown: true
      }
    case 'REORDER_PINNED_PL_CLOSE':
      return {
        ...state,
        reorderPinnedPlaylistsModalShown: false
      }
    case 'CHANGE_PL_VIDS_MODAL_OPEN':
      if (action.data.length > 18) {
        action.data.pop();
        loadMoreButtonForModal = true;
      } else {
        allVideosLoadedForModal = true;
      }
      return {
        ...state,
        editPlaylistModalType: action.modalType,
        videoThumbsForModal: action.data,
        loadMoreButtonForModal,
        allVideosLoadedForModal
      }
    case 'REORDER_PL_VIDS_MODAL_OPEN':
      const videoThumbs = action.playlistVideos.map(video => {
        return {
          id: video.videoid,
          title: video.video_title,
          uploadername: video.video_uploader,
          videocode: video.videocode
        }
      })
      return {
        ...state,
        editPlaylistModalType: action.modalType,
        videoThumbsForModal: videoThumbs
      }
    case 'UPLOAD_PLAYLIST':
      let loadMoreButtonDisplayed = false;
      if (defaultPlaylists.length > 2) {
        defaultPlaylists.pop();
        defaultPlaylists = [action.data.result].concat(defaultPlaylists);
        if (!state.loadMoreButton) loadMoreButtonDisplayed = true;
      } else {
        defaultPlaylists = [action.data.result].concat(state.allPlaylists);
      }
      return {
        ...state,
        allPlaylists: [action.data.result].concat(state.allPlaylists),
        loadMoreButton: loadMoreButtonDisplayed,
        addPlaylistModalShown: false
      }
    case 'EDIT_PLAYLIST_TITLE':
    if (action.data.result) {
      defaultPlaylists = state.allPlaylists.map(playlist => {
        if (playlist.id === action.playlistId) {
          playlist.title = action.data.result
        }
        return playlist;
      })
      defaultPinnedPlaylists = state.pinnedPlaylists.map(playlist => {
        if (playlist.id === action.playlistId) {
          playlist.title = action.data.result
        }
        return playlist;
      })
      return {
        ...state,
        pinnedPlaylists: defaultPinnedPlaylists,
        allPlaylists: defaultPlaylists
      }
    } else {
      console.error(action.data.error);
      return state;
    }
    case 'CHANGE_PLAYLIST_VIDEOS':
      if (action.data.error) {
        let { error } = action.data;
        console.error(error);
        return state;
      }
      if (action.data.result) {
        let { result } = action.data;
        defaultPlaylists = state.allPlaylists.map(playlist => {
          if (playlist.id === action.playlistId) {
            playlist.playlist = result;
          }
          return playlist;
        })
        defaultPinnedPlaylists = state.pinnedPlaylists.map(playlist => {
          if (playlist.id === action.playlistId) {
            playlist.playlist = result;
          }
          return playlist;
        })
        return {
          ...state,
          pinnedPlaylists: defaultPinnedPlaylists,
          allPlaylists: defaultPlaylists
        }
      }
    case 'DELETE_PLAYLIST':
      if (action.data.success) {
        defaultPlaylists = state.allPlaylists.filter(playlist => {
          if (playlist.id === action.playlistId) {
            return false;
          }
          return true;
        })
        defaultPinnedPlaylists = state.pinnedPlaylists.filter(playlist => {
          if (playlist.id === action.playlistId) {
            return false;
          }
          return true;
        })
        return {
          ...state,
          pinnedPlaylists: defaultPinnedPlaylists,
          allPlaylists: defaultPlaylists
        }
      }
      return state;
    case 'RESET_PL_STATE':
      return {
        allPlaylists: defaultPlaylists,
        pinnedPlaylists: defaultPinnedPlaylists,
        loadMoreButton: false,

        videoThumbsForModal: [],
        loadMoreButtonForModal: false,
        allVideosLoadedForModal: false,

        addPlaylistModalShown: false,
        editPlaylistModalType: null,
        selectedModalThumbs: [],

        selectPlaylistsToPinModalShown: false,
        loadMorePlaylistsToPinButton: false,
        playlistsToPin: [],

        reorderPinnedPlaylistsModalShown: false
      }
    case 'RESET_PL_MODAL_STATE':
      return {
        videoThumbsForModal: [],
        loadMoreButtonForModal: false,
        allVideosLoadedForModal: false,

        addPlaylistModalShown: false,
        editPlaylistModalType: null,
        selectedModalThumbs: [],

        selectPlaylistsToPinModalShown: false,
        loadMorePlaylistsToPinButton: false,
        playlistsToPin: []
      }
    default:
      return state;
  }
}
<commit_msg>fixed bug where load more playlist button disappears<commit_after>const defaultState = {
  allPlaylists: [],
  pinnedPlaylists: [],
  loadMoreButton: false,

  videoThumbsForModal: [],
  loadMoreButtonForModal: false,
  allVideosLoadedForModal: false,

  addPlaylistModalShown: false,
  editPlaylistModalType: null,
  selectedModalThumbs: [],

  selectPlaylistsToPinModalShown: false,
  loadMorePlaylistsToPinButton: false,
  playlistsToPin: [],

  reorderPinnedPlaylistsModalShown: false
};

let defaultPlaylists,
    defaultPinnedPlaylists

export default function PlaylistReducer(state = defaultState, action) {
  let loadMoreButtonForModal = false;
  let allVideosLoadedForModal = false;
  let loadMorePlaylistsToPinButton = false;
  switch(action.type) {
    case 'GET_PLAYLISTS':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      let loadMoreButton = false;
      if (action.data.playlists.length > 3) {
        action.data.playlists.pop();
        loadMoreButton = true;
      }
      if (action.initialRun) {
        defaultPlaylists = action.data.playlists;
        return {
          ...state,
          allPlaylists: defaultPlaylists,
          loadMoreButton
        }
      } else {
        return {
          ...state,
          allPlaylists: state.allPlaylists.concat(action.data.playlists),
          loadMoreButton
        };
      }
    case 'GET_PINNED_PLAYLISTS':
      defaultPinnedPlaylists = action.data.playlists;
      return {
        ...state,
        pinnedPlaylists: defaultPinnedPlaylists
      }
    case 'GET_VIDEOS_FOR_MODAL':
      if (action.data.length > 18) {
        action.data.pop();
        loadMoreButtonForModal = true;
      } else {
        allVideosLoadedForModal = true;
      }
      if (action.initialRun) {
        return {
          ...state,
          videoThumbsForModal: action.data,
          loadMoreButtonForModal,
          allVideosLoadedForModal
        }
      } else {
        return {
          ...state,
          videoThumbsForModal: state.videoThumbsForModal.concat(action.data),
          loadMoreButtonForModal,
          allVideosLoadedForModal
        }
      }
    case 'ADD_PL_MODAL_OPEN':
      return {
        ...state,
        addPlaylistModalShown: true
      };
    case 'ADD_PL_MODAL_CLOSE':
      return {
        ...state,
        addPlaylistModalShown: false
      }
    case 'SELECT_PL_TO_PIN_OPEN':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      if (action.data.result.length > 10) {
        action.data.result.pop();
        loadMorePlaylistsToPinButton = true;
      }
      let playlistsToPin = action.data.result.map(item => {
        return {
          title: item.title,
          id: item.id
        }
      })
      return {
        ...state,
        playlistsToPin,
        loadMorePlaylistsToPinButton,
        selectPlaylistsToPinModalShown: true
      }
    case 'SELECT_PL_TO_PIN_CLOSE':
      return {
        ...state,
        loadMorePlaylistsToPinButton: false,
        selectPlaylistsToPinModalShown: false
      }
    case 'LOAD_MORE_PLAYLIST_LIST':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      if (action.data.result.length > 10) {
        action.data.result.pop();
        loadMorePlaylistsToPinButton = true;
      }
      let morePlaylistsToPin = action.data.result.map(item => {
        return {
          title: item.title,
          id: item.id
        }
      })
      return {
        ...state,
        playlistsToPin: state.playlistsToPin.concat(morePlaylistsToPin),
        loadMorePlaylistsToPinButton
      }
    case 'CHANGE_PINNED_PLAYLISTS':
      if (action.data.error) {
        console.error(action.data.error);
        return state;
      }
      if (action.data.playlists) {
        defaultPinnedPlaylists = action.data.playlists;
        return {
          ...state,
          pinnedPlaylists: defaultPinnedPlaylists
        }
      }
      return state;
    case 'REORDER_PINNED_PL_OPEN':
      return {
        ...state,
        reorderPinnedPlaylistsModalShown: true
      }
    case 'REORDER_PINNED_PL_CLOSE':
      return {
        ...state,
        reorderPinnedPlaylistsModalShown: false
      }
    case 'CHANGE_PL_VIDS_MODAL_OPEN':
      if (action.data.length > 18) {
        action.data.pop();
        loadMoreButtonForModal = true;
      } else {
        allVideosLoadedForModal = true;
      }
      return {
        ...state,
        editPlaylistModalType: action.modalType,
        videoThumbsForModal: action.data,
        loadMoreButtonForModal,
        allVideosLoadedForModal
      }
    case 'REORDER_PL_VIDS_MODAL_OPEN':
      const videoThumbs = action.playlistVideos.map(video => {
        return {
          id: video.videoid,
          title: video.video_title,
          uploadername: video.video_uploader,
          videocode: video.videocode
        }
      })
      return {
        ...state,
        editPlaylistModalType: action.modalType,
        videoThumbsForModal: videoThumbs
      }
    case 'UPLOAD_PLAYLIST':
      let loadMoreButtonDisplayed = false;
      if (defaultPlaylists.length > 2) {
        defaultPlaylists.pop();
        defaultPlaylists = [action.data.result].concat(defaultPlaylists);
        if (!state.loadMoreButton) loadMoreButtonDisplayed = true;
      } else {
        defaultPlaylists = [action.data.result].concat(state.allPlaylists);
      }
      return {
        ...state,
        allPlaylists: [action.data.result].concat(state.allPlaylists),
        loadMoreButton: loadMoreButtonDisplayed,
        addPlaylistModalShown: false
      }
    case 'EDIT_PLAYLIST_TITLE':
    if (action.data.result) {
      defaultPlaylists = state.allPlaylists.map(playlist => {
        if (playlist.id === action.playlistId) {
          playlist.title = action.data.result
        }
        return playlist;
      })
      defaultPinnedPlaylists = state.pinnedPlaylists.map(playlist => {
        if (playlist.id === action.playlistId) {
          playlist.title = action.data.result
        }
        return playlist;
      })
      return {
        ...state,
        pinnedPlaylists: defaultPinnedPlaylists,
        allPlaylists: defaultPlaylists
      }
    } else {
      console.error(action.data.error);
      return state;
    }
    case 'CHANGE_PLAYLIST_VIDEOS':
      if (action.data.error) {
        let { error } = action.data;
        console.error(error);
        return state;
      }
      if (action.data.result) {
        let { result } = action.data;
        defaultPlaylists = state.allPlaylists.map(playlist => {
          if (playlist.id === action.playlistId) {
            playlist.playlist = result;
          }
          return playlist;
        })
        defaultPinnedPlaylists = state.pinnedPlaylists.map(playlist => {
          if (playlist.id === action.playlistId) {
            playlist.playlist = result;
          }
          return playlist;
        })
        return {
          ...state,
          pinnedPlaylists: defaultPinnedPlaylists,
          allPlaylists: defaultPlaylists
        }
      }
    case 'DELETE_PLAYLIST':
      if (action.data.success) {
        defaultPlaylists = state.allPlaylists.filter(playlist => {
          if (playlist.id === action.playlistId) {
            return false;
          }
          return true;
        })
        defaultPinnedPlaylists = state.pinnedPlaylists.filter(playlist => {
          if (playlist.id === action.playlistId) {
            return false;
          }
          return true;
        })
        return {
          ...state,
          pinnedPlaylists: defaultPinnedPlaylists,
          allPlaylists: defaultPlaylists
        }
      }
      return state;
    case 'RESET_PL_STATE':
      return {
        allPlaylists: defaultPlaylists,
        pinnedPlaylists: defaultPinnedPlaylists,
        loadMoreButton: false,

        videoThumbsForModal: [],
        loadMoreButtonForModal: false,
        allVideosLoadedForModal: false,

        addPlaylistModalShown: false,
        editPlaylistModalType: null,
        selectedModalThumbs: [],

        selectPlaylistsToPinModalShown: false,
        loadMorePlaylistsToPinButton: false,
        playlistsToPin: [],

        reorderPinnedPlaylistsModalShown: false
      }
    case 'RESET_PL_MODAL_STATE':
      return {
        ...state,
        videoThumbsForModal: [],
        loadMoreButtonForModal: false,
        allVideosLoadedForModal: false,

        addPlaylistModalShown: false,
        editPlaylistModalType: null,
        selectedModalThumbs: [],

        selectPlaylistsToPinModalShown: false,
        loadMorePlaylistsToPinButton: false,
        playlistsToPin: []
      }
    default:
      return state;
  }
}
<|endoftext|>


<commit_before>define(function (require, exports, module) {
    "use strict";

    var slice = require("base/slice");
    var assert = require("base/assert");
    var trim = require("base/trim");
    var hasOwnProperty = require("base/hasOwnProperty");

    var DEVICE_PIXEL_RATIO = window.devicePixelRatio;

    var validator = {
        map: function (set) {
            return function (value) {
                value = trim(value);
                assert(hasOwnProperty(set, value), "unknow key \"" + value + "\"");
                return set[value];
            };
        },
        oneOf: function ( /*list*/ ) {
            var list = slice(arguments);
            return function (value) {
                value = trim(value);
                assert(list.indexOf(value) > -1, "value mast be one of " + list.join());
                return value;
            };
        },

        string: function (value) {
            return String(value);
        },

        font: function (value) {
            if (value === "boostfont") {
                return "assets:boostfont";
            }
            return String(value);
        },

        dp: function (value) {
            assert(!isNaN(value) && isFinite(value), "must be number");
            value = parseFloat(value);
            return value * DEVICE_PIXEL_RATIO;
        },

        number: function (value) {
            assert(!isNaN(value) && isFinite(value), "must be number");
            value = parseFloat(value);
            return value;
        },

        boolean: function (value) {
            if (value !== true && value !== false) {
                value = trim(String(value)).toLowerCase();
                value = value === "true" ? true : value === "false" ? false : assert(false, "must be boolean");
            }
            return value;
        },

        color: (function () {
            var NAMEED_COLORS = {
                "black": "#ff000000",
                "silver": "#ffc0c0c0",
                "gray": "#ff808080",
                "white": "#ffffffff",
                "maroon": "#ff800000",
                "red": "#ffff0000",
                "purple": "#ff800080",
                "fuchsia": "#ffff00ff",
                "green": "#ff008000",
                "lime": "#ff00ff00",
                "olive": "#ff808000",
                "yellow": "#ffffff00",
                "navy": "#ff000080",
                "blue": "#ff0000ff",
                "teal": "#ff008080",
                "aqua": "#ff00ffff",
                "orange": "#ffffa500"
            };
            var REG_HEX_RGB = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/;
            var REG_HEX_RRGGBB = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/;
            var REG_RGB = /^rgb\s*\(\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*\)$/;
            var REG_RGBA = /^rgba\s*\(\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*\)$/;
            //^[1-9]/d*/./d*|0/./d*[1-9]/d*$

            function getHexValue(value, maxValue) {
                value = Math.round(value * 0xFF / maxValue);
                return value < 0x10 ? "0" + value.toString(16) : value.toString(16);
            }

            return function (value) {

                value = trim(value).toLowerCase();

                if (hasOwnProperty(NAMEED_COLORS, value)) {
                    return NAMEED_COLORS[value];
                }
                if (REG_HEX_RGB.test(value)) {
                    return "#ff" +
                        RegExp.$1 + RegExp.$1 +
                        RegExp.$2 + RegExp.$2 +
                        RegExp.$3 + RegExp.$3;
                }
                if (REG_HEX_RRGGBB.test(value)) {
                    return "#ff" +
                        RegExp.$1 +
                        RegExp.$2 +
                        RegExp.$3;
                }
                if (REG_RGB.test(value)) {
                    return "#ff" +
                        getHexValue(parseFloat(RegExp.$1), 0xFF) + // r
                        getHexValue(parseFloat(RegExp.$2), 0xFF) + // g
                        getHexValue(parseFloat(RegExp.$3), 0xFF); // b
                }
                if (REG_RGBA.test(value)) {
                    return "#" +
                        getHexValue(parseFloat(RegExp.$4), 1) + // a
                        getHexValue(parseFloat(RegExp.$1), 0xFF) + // r
                        getHexValue(parseFloat(RegExp.$2), 0xFF) + // g
                        getHexValue(parseFloat(RegExp.$3), 0xFF); // b
                }
                assert(false, "unknow color: \"" + value + "\"");
            };
        })()

    };

    module.exports = validator;

});
<commit_msg>add transparent in color validator<commit_after>define(function (require, exports, module) {
    "use strict";

    var slice = require("base/slice");
    var assert = require("base/assert");
    var trim = require("base/trim");
    var hasOwnProperty = require("base/hasOwnProperty");

    var DEVICE_PIXEL_RATIO = window.devicePixelRatio;

    var validator = {
        map: function (set) {
            return function (value) {
                value = trim(value);
                assert(hasOwnProperty(set, value), "unknow key \"" + value + "\"");
                return set[value];
            };
        },
        oneOf: function ( /*list*/ ) {
            var list = slice(arguments);
            return function (value) {
                value = trim(value);
                assert(list.indexOf(value) > -1, "value mast be one of " + list.join());
                return value;
            };
        },

        string: function (value) {
            return String(value);
        },

        font: function (value) {
            if (value === "boostfont") {
                return "assets:boostfont";
            }
            return String(value);
        },

        dp: function (value) {
            assert(!isNaN(value) && isFinite(value), "must be number");
            value = parseFloat(value);
            return value * DEVICE_PIXEL_RATIO;
        },

        number: function (value) {
            assert(!isNaN(value) && isFinite(value), "must be number");
            value = parseFloat(value);
            return value;
        },

        boolean: function (value) {
            if (value !== true && value !== false) {
                value = trim(String(value)).toLowerCase();
                value = value === "true" ? true : value === "false" ? false : assert(false, "must be boolean");
            }
            return value;
        },

        color: (function () {
            var NAMEED_COLORS = {
                "black": "#ff000000",
                "silver": "#ffc0c0c0",
                "gray": "#ff808080",
                "white": "#ffffffff",
                "maroon": "#ff800000",
                "red": "#ffff0000",
                "purple": "#ff800080",
                "fuchsia": "#ffff00ff",
                "green": "#ff008000",
                "lime": "#ff00ff00",
                "olive": "#ff808000",
                "yellow": "#ffffff00",
                "navy": "#ff000080",
                "blue": "#ff0000ff",
                "teal": "#ff008080",
                "aqua": "#ff00ffff",
                "orange": "#ffffa500",
                "transparent": "#00000000"
            };
            var REG_HEX_RGB = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/;
            var REG_HEX_RRGGBB = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/;
            var REG_RGB = /^rgb\s*\(\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*\)$/;
            var REG_RGBA = /^rgba\s*\(\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*\)$/;
            //^[1-9]/d*/./d*|0/./d*[1-9]/d*$

            function getHexValue(value, maxValue) {
                value = Math.round(value * 0xFF / maxValue);
                return value < 0x10 ? "0" + value.toString(16) : value.toString(16);
            }

            return function (value) {

                value = trim(value).toLowerCase();

                if (hasOwnProperty(NAMEED_COLORS, value)) {
                    return NAMEED_COLORS[value];
                }
                if (REG_HEX_RGB.test(value)) {
                    return "#ff" +
                        RegExp.$1 + RegExp.$1 +
                        RegExp.$2 + RegExp.$2 +
                        RegExp.$3 + RegExp.$3;
                }
                if (REG_HEX_RRGGBB.test(value)) {
                    return "#ff" +
                        RegExp.$1 +
                        RegExp.$2 +
                        RegExp.$3;
                }
                if (REG_RGB.test(value)) {
                    return "#ff" +
                        getHexValue(parseFloat(RegExp.$1), 0xFF) + // r
                        getHexValue(parseFloat(RegExp.$2), 0xFF) + // g
                        getHexValue(parseFloat(RegExp.$3), 0xFF); // b
                }
                if (REG_RGBA.test(value)) {
                    return "#" +
                        getHexValue(parseFloat(RegExp.$4), 1) + // a
                        getHexValue(parseFloat(RegExp.$1), 0xFF) + // r
                        getHexValue(parseFloat(RegExp.$2), 0xFF) + // g
                        getHexValue(parseFloat(RegExp.$3), 0xFF); // b
                }
                assert(false, "unknow color: \"" + value + "\"");
            };
        })()

    };

    module.exports = validator;

});
<|endoftext|>


<commit_before>const assert = require('assert')
const Shouty = require('../../lib/shouty')
const Coordinate = require('../../lib/coordinate')

const {defineSupportCode} = require('cucumber')

defineSupportCode(({Before, Given, When, Then}) => {
  const ARBITARY_MESSAGE = 'Hello, world'
  let shouty
  Before(function() {
    shouty = new Shouty()
  })

  Given(/^Lucy is at (\d+), (\d+)$/, function (x, y, callback) {
    shouty.setLocation('Lucy', new Coordinate(x, y))
    callback()
  })

  Given(/^Sean is at (\d+), (\d+)$/, function (x, y, callback) {
    shouty.setLocation('Sean', new Coordinate(x, y))
    callback()
  })

  When(/^Sean shouts$/, function (callback) {
    shouty.shout('Sean', ARBITARY_MESSAGE)
    callback()
  })

  Then(/^Lucy should hear Sean$/, function (callback) {
    assert.equal(Object.keys(shouty.getMessagesHeardBy('Lucy')).length, 1)
    callback()
  })

  Then(/^Lucy should hear nothing$/, function (callback) {
    assert.equal(Object.keys(shouty.getMessagesHeardBy('Lucy')).length, 0)
    callback()
  })

})
<commit_msg>Make step definitions synchronous<commit_after>const assert = require('assert')
const Shouty = require('../../lib/shouty')
const Coordinate = require('../../lib/coordinate')

const {defineSupportCode} = require('cucumber')

defineSupportCode(({Before, Given, When, Then}) => {
  const ARBITARY_MESSAGE = 'Hello, world'
  let shouty
  Before(function() {
    shouty = new Shouty()
  })

  Given(/^Lucy is at (\d+), (\d+)$/, function (x, y) {
    shouty.setLocation('Lucy', new Coordinate(x, y))
  })

  Given(/^Sean is at (\d+), (\d+)$/, function (x, y) {
    shouty.setLocation('Sean', new Coordinate(x, y))
  })

  When(/^Sean shouts$/, function () {
    shouty.shout('Sean', ARBITARY_MESSAGE)
  })

  Then(/^Lucy should hear Sean$/, function () {
    assert.equal(Object.keys(shouty.getMessagesHeardBy('Lucy')).length, 1)
  })

  Then(/^Lucy should hear nothing$/, function () {
    assert.equal(Object.keys(shouty.getMessagesHeardBy('Lucy')).length, 0)
  })

})
<|endoftext|>


<commit_before>(function(angular, undefined) {
'use strict';

var Module = angular.module('django.shop.filter', []);

// Directive <form shop-product-filter="attribute"> to be used to communicate selected
// attributes used to narrow down the list of products.
Module.directive('shopProductFilter', ['$location', function($location) {
	return {
		require: 'form',
		restrict: 'AC',
		link: function(scope, element, attrs) {
			var params = $location.search(), attr = attrs['shopProductFilter'];
			if (!attr)
				throw new Error("Directive shop-attribute-filter requires an attribute.");

			scope.filters = scope.filters || {};
			if (params[attr]) {
				scope.filters[attr] = params[attr];
			}

			scope.filterChanged = function() {
				var params = {};
				if (scope.filters[attr]) {
					params[attr] = scope.filters[attr];
				}
				$location.search(params);
				scope.searchQuery = '';  // remove content in search field
				scope.$emit('shopCatalogFilter', params);
			};
		}
	};
}]);

})(window.angular);
<commit_msg>attempt to fix #494 filters with more than one field<commit_after>(function(angular, undefined) {
'use strict';

var Module = angular.module('django.shop.filter', []);

// Directive <form shop-product-filter="attribute"> to be used to communicate selected
// attributes used to narrow down the list of products.
Module.directive('shopProductFilter', ['$location', function($location) {
	return {
		require: 'form',
		restrict: 'AC',
		link: function(scope, element, attrs) {
			var params = $location.search(), filter_attrs;
			if (angular.isUndefined(attrs['shopProductFilter']))
				throw new Error("Directive shop-attribute-filter requires an attribute.");
			filter_attrs = scope.$eval(attrs['shopProductFilter']) || [attrs['shopProductFilter']];

			scope.filters = scope.filters || {};
			angular.forEach(filter_attrs, function(attr) {
				if (params[attr]) {
					scope.filters[attr] = params[attr];
				}
			});

			scope.filterChanged = function() {
				var params = {};
				angular.forEach(filter_attrs, function(attr) {
					if (scope.filters[attr]) {
						params[attr] = scope.filters[attr];
					}
				});
				$location.search(params);
				scope.searchQuery = '';  // remove content in search field
				scope.$emit('shopCatalogFilter', params);
			};
		}
	};
}]);

})(window.angular);
<|endoftext|>


<commit_before>const request = require('request-promise-native');
const bot = require('./../bot');
module.exports = async function (user, noDM) {
    var guild = bot.guilds.get('184536578654339072');
    var member = guild.member(user);
    if (!member)
        return false;
    //console.log(user);
    var id = user.id;
    console.log(id);
    return request("http://revive-bot-discord.revive.systems/v0/discord/userinfo/" + id).then(async function (body) {
        console.log(body);
        try { var info = JSON.parse(body); }
        catch (e) {
            throw e;
        }
        if (info.hasOwnProperty('error') && !noDM) {
            user.sendMessage("To link your discord account with your battlelog account follow the link given below\n"
                + "https://battlelog.co/discord_link.php");
            console.log("User " + user.username + " Not Linked. DMing user to link now");
            return false;
        }
        await member.addRole('275317218911322112');
        //member.removeRole(guild.roles.find("name", "members"));
        if (info.is_donator) {
            if (!member.roles.get("273105185566359562"))
                await member.addRole(guild.roles.get("273105185566359562")).then(user.sendMessage('Role added: donators'));
        } else {
            if (member.roles.get("273105185566359562"))
                await member.removeRole(guild.roles.get("273105185566359562")).then(user.sendMessage('Role removed: donators'));
        }
        if (info.is_mod || (info.usergroup == 8)) {
            if (!member.roles.get('184676864630063104'))
                await member.addRole(guild.roles.get('184676864630063104')).then(user.sendMessage('Role added: moderator'));
        }
        if(guild.me.highestRole.comparePositionTo(member.highestRole))
            await member.setNickname(info.username);
        return info;
    });
};
<commit_msg>Update refresh.js<commit_after>const request = require('request-promise-native');
const bot = require('./../bot');
module.exports = async function (user, noDM) {
    var guild = bot.guilds.get('184536578654339072');
    var member = guild.member(user);
    if (!member)
        return false;
    //console.log(user);
    var id = user.id;
    console.log(id);
    return request("http://localhost/v0/discord/userinfo/" + id).then(async function (body) {
        console.log(body);
        try { var info = JSON.parse(body); }
        catch (e) {
            throw e;
        }
        if (info.hasOwnProperty('error') && !noDM) {
            user.sendMessage("To link your discord account with your battlelog account follow the link given below\n"
                + "https://battlelog.co/discord_link.php");
            console.log("User " + user.username + " Not Linked. DMing user to link now");
            return false;
        }
        await member.addRole('275317218911322112');
        //member.removeRole(guild.roles.find("name", "members"));
        if (info.is_donator) {
            if (!member.roles.get("273105185566359562"))
                await member.addRole(guild.roles.get("273105185566359562")).then(user.sendMessage('Role added: donators'));
        } else {
            if (member.roles.get("273105185566359562"))
                await member.removeRole(guild.roles.get("273105185566359562")).then(user.sendMessage('Role removed: donators'));
        }
        if (info.is_mod || (info.usergroup == 8)) {
            if (!member.roles.get('184676864630063104'))
                await member.addRole(guild.roles.get('184676864630063104')).then(user.sendMessage('Role added: moderator'));
        }
        if(guild.me.highestRole.comparePositionTo(member.highestRole))
            await member.setNickname(info.username);
        return info;
    });
};
<|endoftext|>


<commit_before>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ReactFiberBeginWork
 * @flow
 */

'use strict';

import type { ReactCoroutine } from 'ReactCoroutine';
import type { Fiber } from 'ReactFiber';
import type { HostConfig } from 'ReactFiberReconciler';

var ReactChildFiber = require('ReactChildFiber');
var ReactTypeOfWork = require('ReactTypeOfWork');
var {
  IndeterminateComponent,
  FunctionalComponent,
  ClassComponent,
  HostContainer,
  HostComponent,
  CoroutineComponent,
  CoroutineHandlerPhase,
  YieldComponent,
} = ReactTypeOfWork;
var {
  NoWork,
  OffscreenPriority,
} = require('ReactPriorityLevel');
var { findNextUnitOfWorkAtPriority } = require('ReactFiberPendingWork');

module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {

  function reconcileChildren(current, workInProgress, nextChildren) {
    const priority = workInProgress.pendingWorkPriority;
    workInProgress.child = ReactChildFiber.reconcileChildFibers(
      workInProgress,
      current ? current.child : null,
      nextChildren,
      priority
    );
  }

  function updateFunctionalComponent(current, workInProgress) {
    var fn = workInProgress.type;
    var props = workInProgress.pendingProps;
    console.log('update fn:', fn.name);
    var nextChildren = fn(props);
    reconcileChildren(current, workInProgress, nextChildren);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function updateHostComponent(current, workInProgress) {
    console.log(
      'host component', workInProgress.type,
      typeof workInProgress.pendingProps.children === 'string' ? workInProgress.pendingProps.children : ''
    );

    var nextChildren = workInProgress.pendingProps.children;

    let priority = workInProgress.pendingWorkPriority;
    if (workInProgress.pendingProps.hidden && priority !== OffscreenPriority) {
      // If this host component is hidden, we can reconcile its children at
      // the lowest priority and bail out from this particular pass. Unless, we're
      // currently reconciling the lowest priority.
      workInProgress.child = ReactChildFiber.reconcileChildFibers(
        workInProgress,
        current ? current.child : null,
        nextChildren,
        OffscreenPriority
      );
      workInProgress.pendingWorkPriority = OffscreenPriority;
      return null;
    } else {
      workInProgress.child = ReactChildFiber.reconcileChildFibers(
        workInProgress,
        current ? current.child : null,
        nextChildren,
        priority
      );
      workInProgress.pendingWorkPriority = NoWork;
      return workInProgress.child;
    }
  }

  function mountIndeterminateComponent(current, workInProgress) {
    var fn = workInProgress.type;
    var props = workInProgress.pendingProps;
    var value = fn(props);
    if (typeof value === 'object' && value && typeof value.render === 'function') {
      console.log('performed work on class:', fn.name);
      // Proceed under the assumption that this is a class instance
      workInProgress.tag = ClassComponent;
      if (workInProgress.alternate) {
        workInProgress.alternate.tag = ClassComponent;
      }
    } else {
      console.log('performed work on fn:', fn.name);
      // Proceed under the assumption that this is a functional component
      workInProgress.tag = FunctionalComponent;
      if (workInProgress.alternate) {
        workInProgress.alternate.tag = FunctionalComponent;
      }
    }
    reconcileChildren(current, workInProgress, value);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function updateCoroutineComponent(current, workInProgress) {
    var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
    if (!coroutine) {
      throw new Error('Should be resolved by now');
    }
    console.log('begin coroutine', workInProgress.type.name);
    reconcileChildren(current, workInProgress, coroutine.children);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function reuseChildren(returnFiber : Fiber, firstChild : Fiber) {
    // TODO: None of this should be necessary if structured better.
    // The returnFiber pointer only needs to be updated when we walk into this child
    // which we don't do right now. If the pending work priority indicated only
    // if a child has work rather than if the node has work, then we would know
    // by a single lookup on workInProgress rather than having to go through
    // each child.
    let child = firstChild;
    do {
      // Update the returnFiber of the child to the newest fiber.
      child.return = returnFiber;
      // Retain the priority if there's any work left to do in the children.
      if (child.pendingWorkPriority !== NoWork &&
          (returnFiber.pendingWorkPriority === NoWork ||
          returnFiber.pendingWorkPriority > child.pendingWorkPriority)) {
        returnFiber.pendingWorkPriority = child.pendingWorkPriority;
      }
    } while (child = child.sibling);
  }

  function beginWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
    // The current, flushed, state of this fiber is the alternate.
    // Ideally nothing should rely on this, but relying on it here
    // means that we don't need an additional field on the work in
    // progress.
    if (current && workInProgress.pendingProps === current.memoizedProps) {
      // The most likely scenario is that the previous copy of the tree contains
      // the same props as the new one. In that case, we can just copy the output
      // and children from that node.
      workInProgress.memoizedProps = workInProgress.pendingProps;
      workInProgress.output = current.output;
      const priorityLevel = workInProgress.pendingWorkPriority;
      workInProgress.pendingProps = null;
      workInProgress.pendingWorkPriority = NoWork;
      workInProgress.stateNode = current.stateNode;
      if (current.child) {
        // If we bail out but still has work with the current priority in this
        // subtree, we need to go find it right now. If we don't, we won't flush
        // it until the next tick.
        workInProgress.child = current.child;
        reuseChildren(workInProgress, workInProgress.child);
        if (workInProgress.pendingWorkPriority <= priorityLevel) {
          // TODO: This passes the current node and reads the priority level and
          // pending props from that. We want it to read our priority level and
          // pending props from the work in progress. Needs restructuring.
          return findNextUnitOfWorkAtPriority(workInProgress.alternate, priorityLevel);
        } else {
          return null;
        }
      } else {
        workInProgress.child = null;
        return null;
      }
    }

    if (!workInProgress.hasWorkInProgress &&
        workInProgress.pendingProps === workInProgress.memoizedProps &&
        workInProgress.pendingWorkPriority === NoWork) {
      // If we started this work before, and finished it, or if we're in a
      // ping-pong update scenario, this version could already be what we're
      // looking for. In that case, we should be able to just bail out.
      workInProgress.pendingProps = null;
      // TODO: We should be able to bail out if there is remaining work at a lower
      // priority too. However, I don't know if that is safe or even better since
      // the other tree could've potentially finished that work.
      return null;
    }

    workInProgress.hasWorkInProgress = true;

    switch (workInProgress.tag) {
      case IndeterminateComponent:
        mountIndeterminateComponent(current, workInProgress);
        return workInProgress.child;
      case FunctionalComponent:
        updateFunctionalComponent(current, workInProgress);
        return workInProgress.child;
      case ClassComponent:
        console.log('class component', workInProgress.pendingProps.type.name);
        return workInProgress.child;
      case HostContainer:
        reconcileChildren(current, workInProgress, workInProgress.pendingProps);
        // A yield component is just a placeholder, we can just run through the
        // next one immediately.
        workInProgress.pendingWorkPriority = NoWork;
        if (workInProgress.child) {
          return beginWork(
            workInProgress.child.alternate,
            workInProgress.child
          );
        }
        return null;
      case HostComponent:
        return updateHostComponent(current, workInProgress);
      case CoroutineHandlerPhase:
        // This is a restart. Reset the tag to the initial phase.
        workInProgress.tag = CoroutineComponent;
        // Intentionally fall through since this is now the same.
      case CoroutineComponent:
        updateCoroutineComponent(current, workInProgress);
        // This doesn't take arbitrary time so we could synchronously just begin
        // eagerly do the work of workInProgress.child as an optimization.
        if (workInProgress.child) {
          return beginWork(
            workInProgress.child.alternate,
            workInProgress.child
          );
        }
        return workInProgress.child;
      case YieldComponent:
        // A yield component is just a placeholder, we can just run through the
        // next one immediately.
        workInProgress.pendingWorkPriority = NoWork;
        if (workInProgress.sibling) {
          return beginWork(
            workInProgress.sibling.alternate,
            workInProgress.sibling
          );
        }
        return null;
      default:
        throw new Error('Unknown unit of work tag');
    }
  }

  return {
    beginWork,
  };

};
<commit_msg>[Fiber] Rudimentary class support<commit_after>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ReactFiberBeginWork
 * @flow
 */

'use strict';

import type { ReactCoroutine } from 'ReactCoroutine';
import type { Fiber } from 'ReactFiber';
import type { HostConfig } from 'ReactFiberReconciler';

var ReactChildFiber = require('ReactChildFiber');
var ReactTypeOfWork = require('ReactTypeOfWork');
var {
  IndeterminateComponent,
  FunctionalComponent,
  ClassComponent,
  HostContainer,
  HostComponent,
  CoroutineComponent,
  CoroutineHandlerPhase,
  YieldComponent,
} = ReactTypeOfWork;
var {
  NoWork,
  OffscreenPriority,
} = require('ReactPriorityLevel');
var { findNextUnitOfWorkAtPriority } = require('ReactFiberPendingWork');

module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {

  function reconcileChildren(current, workInProgress, nextChildren) {
    const priority = workInProgress.pendingWorkPriority;
    workInProgress.child = ReactChildFiber.reconcileChildFibers(
      workInProgress,
      current ? current.child : null,
      nextChildren,
      priority
    );
  }

  function updateFunctionalComponent(current, workInProgress) {
    var fn = workInProgress.type;
    var props = workInProgress.pendingProps;
    console.log('update fn:', fn.name);
    var nextChildren = fn(props);
    reconcileChildren(current, workInProgress, nextChildren);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function updateClassComponent(current, workInProgress) {
    var props = workInProgress.pendingProps;
    if (!workInProgress.stateNode) {
      var ctor = workInProgress.type;
      console.log('mount class:', workInProgress.type.name);
      workInProgress.stateNode = new ctor(props);
    } else {
      console.log('update class:', workInProgress.type.name);
    }
    var instance = workInProgress.stateNode;
    instance.props = props;
    var nextChildren = instance.render();
    reconcileChildren(current, workInProgress, nextChildren);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function updateHostComponent(current, workInProgress) {
    console.log(
      'host component', workInProgress.type,
      typeof workInProgress.pendingProps.children === 'string' ? workInProgress.pendingProps.children : ''
    );

    var nextChildren = workInProgress.pendingProps.children;

    let priority = workInProgress.pendingWorkPriority;
    if (workInProgress.pendingProps.hidden && priority !== OffscreenPriority) {
      // If this host component is hidden, we can reconcile its children at
      // the lowest priority and bail out from this particular pass. Unless, we're
      // currently reconciling the lowest priority.
      workInProgress.child = ReactChildFiber.reconcileChildFibers(
        workInProgress,
        current ? current.child : null,
        nextChildren,
        OffscreenPriority
      );
      workInProgress.pendingWorkPriority = OffscreenPriority;
      return null;
    } else {
      workInProgress.child = ReactChildFiber.reconcileChildFibers(
        workInProgress,
        current ? current.child : null,
        nextChildren,
        priority
      );
      workInProgress.pendingWorkPriority = NoWork;
      return workInProgress.child;
    }
  }

  function mountIndeterminateComponent(current, workInProgress) {
    var fn = workInProgress.type;
    var props = workInProgress.pendingProps;
    var value = fn(props);
    if (typeof value === 'object' && value && typeof value.render === 'function') {
      console.log('performed work on class:', fn.name);
      // Proceed under the assumption that this is a class instance
      workInProgress.tag = ClassComponent;
      if (workInProgress.alternate) {
        workInProgress.alternate.tag = ClassComponent;
      }
      value = value.render();
    } else {
      console.log('performed work on fn:', fn.name);
      // Proceed under the assumption that this is a functional component
      workInProgress.tag = FunctionalComponent;
      if (workInProgress.alternate) {
        workInProgress.alternate.tag = FunctionalComponent;
      }
    }
    reconcileChildren(current, workInProgress, value);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function updateCoroutineComponent(current, workInProgress) {
    var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
    if (!coroutine) {
      throw new Error('Should be resolved by now');
    }
    console.log('begin coroutine', workInProgress.type.name);
    reconcileChildren(current, workInProgress, coroutine.children);
    workInProgress.pendingWorkPriority = NoWork;
  }

  function reuseChildren(returnFiber : Fiber, firstChild : Fiber) {
    // TODO: None of this should be necessary if structured better.
    // The returnFiber pointer only needs to be updated when we walk into this child
    // which we don't do right now. If the pending work priority indicated only
    // if a child has work rather than if the node has work, then we would know
    // by a single lookup on workInProgress rather than having to go through
    // each child.
    let child = firstChild;
    do {
      // Update the returnFiber of the child to the newest fiber.
      child.return = returnFiber;
      // Retain the priority if there's any work left to do in the children.
      if (child.pendingWorkPriority !== NoWork &&
          (returnFiber.pendingWorkPriority === NoWork ||
          returnFiber.pendingWorkPriority > child.pendingWorkPriority)) {
        returnFiber.pendingWorkPriority = child.pendingWorkPriority;
      }
    } while (child = child.sibling);
  }

  function beginWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
    // The current, flushed, state of this fiber is the alternate.
    // Ideally nothing should rely on this, but relying on it here
    // means that we don't need an additional field on the work in
    // progress.
    if (current && workInProgress.pendingProps === current.memoizedProps) {
      // The most likely scenario is that the previous copy of the tree contains
      // the same props as the new one. In that case, we can just copy the output
      // and children from that node.
      workInProgress.memoizedProps = workInProgress.pendingProps;
      workInProgress.output = current.output;
      const priorityLevel = workInProgress.pendingWorkPriority;
      workInProgress.pendingProps = null;
      workInProgress.pendingWorkPriority = NoWork;
      workInProgress.stateNode = current.stateNode;
      if (current.child) {
        // If we bail out but still has work with the current priority in this
        // subtree, we need to go find it right now. If we don't, we won't flush
        // it until the next tick.
        workInProgress.child = current.child;
        reuseChildren(workInProgress, workInProgress.child);
        if (workInProgress.pendingWorkPriority <= priorityLevel) {
          // TODO: This passes the current node and reads the priority level and
          // pending props from that. We want it to read our priority level and
          // pending props from the work in progress. Needs restructuring.
          return findNextUnitOfWorkAtPriority(workInProgress.alternate, priorityLevel);
        } else {
          return null;
        }
      } else {
        workInProgress.child = null;
        return null;
      }
    }

    if (!workInProgress.hasWorkInProgress &&
        workInProgress.pendingProps === workInProgress.memoizedProps &&
        workInProgress.pendingWorkPriority === NoWork) {
      // If we started this work before, and finished it, or if we're in a
      // ping-pong update scenario, this version could already be what we're
      // looking for. In that case, we should be able to just bail out.
      workInProgress.pendingProps = null;
      // TODO: We should be able to bail out if there is remaining work at a lower
      // priority too. However, I don't know if that is safe or even better since
      // the other tree could've potentially finished that work.
      return null;
    }

    workInProgress.hasWorkInProgress = true;

    switch (workInProgress.tag) {
      case IndeterminateComponent:
        mountIndeterminateComponent(current, workInProgress);
        return workInProgress.child;
      case FunctionalComponent:
        updateFunctionalComponent(current, workInProgress);
        return workInProgress.child;
      case ClassComponent:
        updateClassComponent(current, workInProgress);
        return workInProgress.child;
      case HostContainer:
        reconcileChildren(current, workInProgress, workInProgress.pendingProps);
        // A yield component is just a placeholder, we can just run through the
        // next one immediately.
        workInProgress.pendingWorkPriority = NoWork;
        if (workInProgress.child) {
          return beginWork(
            workInProgress.child.alternate,
            workInProgress.child
          );
        }
        return null;
      case HostComponent:
        return updateHostComponent(current, workInProgress);
      case CoroutineHandlerPhase:
        // This is a restart. Reset the tag to the initial phase.
        workInProgress.tag = CoroutineComponent;
        // Intentionally fall through since this is now the same.
      case CoroutineComponent:
        updateCoroutineComponent(current, workInProgress);
        // This doesn't take arbitrary time so we could synchronously just begin
        // eagerly do the work of workInProgress.child as an optimization.
        if (workInProgress.child) {
          return beginWork(
            workInProgress.child.alternate,
            workInProgress.child
          );
        }
        return workInProgress.child;
      case YieldComponent:
        // A yield component is just a placeholder, we can just run through the
        // next one immediately.
        workInProgress.pendingWorkPriority = NoWork;
        if (workInProgress.sibling) {
          return beginWork(
            workInProgress.sibling.alternate,
            workInProgress.sibling
          );
        }
        return null;
      default:
        throw new Error('Unknown unit of work tag');
    }
  }

  return {
    beginWork,
  };

};
<|endoftext|>


<commit_before>//#region Copyright, Version, and Description
/*
 *  Functions to enable Breeze to use POST for queries when
 *  special parameters are passed using the .withParameters function.
 *
 * Copyright 2014 IdeaBlade, Inc.  All Rights Reserved.
 * Use, reproduction, distribution, and modification of this code is subject to the terms and
 * conditions of the IdeaBlade Breeze license, available at http://www.breezejs.com/license
 *
 * Author: Steve Schmidt
 * Version: 1.0.5
 *
 * Special parameters:
 *  $method: ‘POST’ or ‘GET’ (the default)
 *  $encoding: ‘JSON’ or x-www-form-urlencoded (the default)
 *  $data: contains the data to be sent to the server
 *
 * Example:
 *   var query = breeze.EntityQuery.from('SimilarCustomersPOST')
 *            .withParameters({
 *                $method: 'POST',
 *                $encoding: 'JSON',
 *               $data: { CompanyName: 'Hilo Hattie', ContactName: 'Donald', City: 'Duck', Country: 'USA', Phone: '808-234-5678' }
 *           });
 *
 */
//#endregion
(function (definition, window) {
    if (window.breeze) {
        definition(window.breeze);
    } else if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        // CommonJS or Node
        var b = require('breeze');
        definition(b);
    } else if (typeof define === "function" && define["amd"] && !window.breeze) {
        // Requirejs / AMD
        define(['breeze'], definition);
    } else {
        throw new Error("Can't find breeze");
    }
}(function (breeze) {
    'use strict';
    breeze.ajaxpost = function(ajaxAdapter) {

        divertAjaxImpl(ajaxAdapter);

        return {
            configAjaxAdapter: divertAjaxImpl
        };
    };

    breeze.ajaxpost(); // run it immediately on whatever is the current ajax adapter

    // Add processSettings to ajaxAdapter
    function divertAjaxImpl(ajaxAdapter) {
        if (!ajaxAdapter) {
            ajaxAdapter = breeze.config.getAdapterInstance("ajax");
        }

        var ajaxFunction = ajaxAdapter.ajax;
        if (ajaxFunction) {
            ajaxAdapter.ajax = function (settings) {
                processSettings(settings);
                return ajaxFunction.call(ajaxAdapter, settings);
            };
        }
    }

    // Handle the POST-specific properties in the settings - $method, $data, $encoding
    function processSettings(settings) {
        if (settings) {
            var parameters = settings.params;
            if (parameters) {
                // wrapped data; handle the special properties
                settings.type = parameters.$method || settings.type; // GET is default method

                var data = parameters.$data;
                if (data) {
                 // if $data exists, assume all of other parameters are guidance for building a POST
                    if (parameters.$encoding === 'JSON') {
                        // JSON encoding
                        settings.processData = false; // don't let JQuery form-encode it
                        settings.contentType = "application/json; charset=UTF-8";

                        if (typeof (data) === 'object') {
                            settings.data = JSON.stringify(data); // encode parameters as JSON
                        } else {
                            settings.data = data;
                        }
                    } else {
                        settings.data = data;
                    }
                    // must be null or jQuery ajax adapter won't see settings.data
                    settings.params = null;
                }
            }
        }

        return settings;
    }

}, this));
<commit_msg>Change version number to 1.0.6<commit_after>//#region Copyright, Version, and Description
/*
 *  Functions to enable Breeze to use POST for queries when
 *  special parameters are passed using the .withParameters function.
 *
 * Copyright 2014 IdeaBlade, Inc.  All Rights Reserved.
 * Use, reproduction, distribution, and modification of this code is subject to the terms and
 * conditions of the IdeaBlade Breeze license, available at http://www.breezejs.com/license
 *
 * Author: Steve Schmidt
 * Version: 1.0.6
 *
 * Special parameters:
 *  $method: ‘POST’ or ‘GET’ (the default)
 *  $encoding: ‘JSON’ or x-www-form-urlencoded (the default)
 *  $data: contains the data to be sent to the server
 *
 * Example:
 *   var query = breeze.EntityQuery.from('SimilarCustomersPOST')
 *            .withParameters({
 *                $method: 'POST',
 *                $encoding: 'JSON',
 *               $data: { CompanyName: 'Hilo Hattie', ContactName: 'Donald', City: 'Duck', Country: 'USA', Phone: '808-234-5678' }
 *           });
 *
 */
//#endregion
(function (definition, window) {
    if (window.breeze) {
        definition(window.breeze);
    } else if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        // CommonJS or Node
        var b = require('breeze');
        definition(b);
    } else if (typeof define === "function" && define["amd"] && !window.breeze) {
        // Requirejs / AMD
        define(['breeze'], definition);
    } else {
        throw new Error("Can't find breeze");
    }
}(function (breeze) {
    'use strict';
    breeze.ajaxpost = function(ajaxAdapter) {

        divertAjaxImpl(ajaxAdapter);

        return {
            configAjaxAdapter: divertAjaxImpl
        };
    };

    breeze.ajaxpost(); // run it immediately on whatever is the current ajax adapter

    // Add processSettings to ajaxAdapter
    function divertAjaxImpl(ajaxAdapter) {
        if (!ajaxAdapter) {
            ajaxAdapter = breeze.config.getAdapterInstance("ajax");
        }

        var ajaxFunction = ajaxAdapter.ajax;
        if (ajaxFunction) {
            ajaxAdapter.ajax = function (settings) {
                processSettings(settings);
                return ajaxFunction.call(ajaxAdapter, settings);
            };
        }
    }

    // Handle the POST-specific properties in the settings - $method, $data, $encoding
    function processSettings(settings) {
        if (settings) {
            var parameters = settings.params;
            if (parameters) {
                // wrapped data; handle the special properties
                settings.type = parameters.$method || settings.type; // GET is default method

                var data = parameters.$data;
                if (data) {
                 // if $data exists, assume all of other parameters are guidance for building a POST
                    if (parameters.$encoding === 'JSON') {
                        // JSON encoding
                        settings.processData = false; // don't let JQuery form-encode it
                        settings.contentType = "application/json; charset=UTF-8";

                        if (typeof (data) === 'object') {
                            settings.data = JSON.stringify(data); // encode parameters as JSON
                        } else {
                            settings.data = data;
                        }
                    } else {
                        settings.data = data;
                    }
                    // must be null or jQuery ajax adapter won't see settings.data
                    settings.params = null;
                }
            }
        }

        return settings;
    }

}, this));
<|endoftext|>


<commit_before>angular.
  module('Usuario').
  component('usuarioEntrar', {
    templateUrl: '/app/Usuario/entrar.template.html',
    controller: ['ApiUsuario','$http', function Entrar(ApiUsuario,$http,$scope) {
      this.user = "Lucas";
      this.form = {'usuario':'','senha':''};
      this.entrar = function(teste)
      {
      	console.log(this.form)
       	var resultado = ApiUsuario.Entrar(this.form,function() {
       		$http.defaults.headers.common.Authorization = resultado.corpo.token;
       		window.localStorage.setItem('token_de_acesso', resultado.corpo.token);
   		}, function(error){
   			console.log(error)
   		} );
   	  }
    }]
  });<commit_msg>Frontend<commit_after>angular.
  module('Usuario').
  component('usuarioEntrar', {
    templateUrl: '/app/Usuario/entrar.template.html',
    controller: ['ApiUsuario','$http', function Entrar(ApiUsuario,$http,$scope) {
      this.user = "Lucas";
      this.form = {'usuario':'','senha':''};
      this.entrar = function(teste)
      {
      	console.log(this.form)
       	var resultado = ApiUsuario.Entrar(this.form,function(result) {
       		console.log(result)
       		$http.defaults.headers.common.Authorization = resultado.corpo.token;
       		window.localStorage.setItem('token_de_acesso', resultado.corpo.token);
   		}, function(erro){
   			console.log(erro.data.mensagem)
   		} );
   	  }
    }]
  });<|endoftext|>