<commit_before>'use strict';

var dragOps = {
    addClass: false,
    cursorAt: { left: 17, top: 17 },
    revert: 'invalid',
    zIndex: 900,
    start: function(event, ui) {
        var self = $(this);
        //console.log('drag-start', self);
        self.addClass('ui-state-disabled');
    },
    stop: function(event, ui) {
        var self = $(this);
        //console.log('drag-stop', self);
        if (!self.data('dropped')) {
            self.draggable('enable');
            self.removeClass('ui-state-disabled');
        }
    }
},
dropOps = {
    addClasses: false,
    tolerance: 'intersect',
    over: function(event, ui) {
        var self = $(this);
        //console.log('drop-over', self);
        self.add(self.siblings()).addClass('ui-state-hover');
    },
    out: function(event, ui) {
        var self = $(this);
        //console.log('drop-out', self);
        self.add(self.siblings()).removeClass('ui-state-hover');
    },
    drop: function(event, ui) {
        $('.alert-error').remove();

        var self = $(this),
        selfGroup = self.add(self.siblings()),
        prevPart = ui.draggable,
        prevGroup = prevPart.add(prevPart.siblings()),
        letter = prevPart.data('part-id').replace(/[a-z]/g, ''), // remove lowercase letters to leave the single uppercase part letter
        oldID = self.data('part-id');
        //console.log('drop-drop', self);

        if (selfGroup.hasClass('ui-state-hover')) { selfGroup.removeClass('ui-state-hover'); }

        // Dragged from the list to a spot...
        if (!prevPart.hasClass('part-drop')) {
            // that is empty
            if (self.data('part-id') === undefined) {
                //console.log('list to empty');
                prevPart.data('dropped', true).draggable('disable');
            }
            // that is already occupied
            else {
                //console.log('list to occupied');
                //console.log(self.clone());

                prevPart.data('dropped', true).draggable('disable');
                prevPart.siblings().each(function(){
                    var self = $(this);

                    if (self.data('part-id') === oldID) {
                        self.data('dropped', false).draggable('enable').removeClass('ui-state-disabled');

                        return false;
                    }
                });
            }

            selfGroup.addClass('ui-state-highlight').text(letter).data('part-id', prevPart.data('part-id'));
        }
        // Rearrange...
        else {
            // to a different part...
            if (self.data('part-id') !== prevPart.data('part-id')) {
                // that is empty
                if (self.data('part-id') === undefined) {
                    //console.log('rearrange to empty');
                    prevGroup.removeClass('ui-state-highlight').text('');
                }
                // that is already occupied
                else {
                    //console.log('rearrange to occupied', prevPart.data('part-id'), '>', self.data('part-id'));

                    selfGroup.data('part-id', prevPart.data('part-id'));
                   //console.log(self.data('part-id'));
                    selfGroup.text(prevPart.text());

                    prevGroup.data('part-id', oldID);
                    prevGroup.text(oldID.replace(/[a-z]/g, ''));

                    return;
                }
            }
            // to a spot that is of the same part
            else if (self.data('part-id') === prevPart.data('part-id')) {
                //console.log('canceled drop b/c part was the same', self.data('part-id'), prevPart.data('part-id'))
                return false;
            }

            selfGroup.addClass('ui-state-highlight').text(letter).data('part-id', prevPart.data('part-id'));
            prevGroup.removeData('part-id');
        }

        //console.log(self.data());
    }
},
rearrangeOps = {
    addClass: false,
    cursorAt: { left: 17, top: 17 },
    revert: 'invalid',
    zIndex: 900,
    start: function(event, ui) {
        var self = $(this);
        //console.log('rearrange-start', self);

        if (!self.data('part-id')) {
            //console.log('canceled rearrange b/c it has no partID');
            return false;
        } else {
            self.add(self.siblings()).addClass('ui-draggable-disabled');
        }
    },
    stop: function(event, ui) {
        var self = $(this);
        //console.log('rearrange-stop', self);

        self.add(self.siblings()).removeClass('ui-draggable-disabled');
    }
};

/* Directives */

app.directive('uiDraggable', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.uiDraggable),
            options = dragOps;

            //console.log(vars);
            options.scope = vars.scope;
            options.helper = function(event) {
                return $('

').text(vars.helper.letter);
            };

            elem.draggable(options);
            //console.log('drAGGable:', options);
        }
    };
}).directive('uiDroppable', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.uiDroppable),
                options = dropOps;

                options.scope = vars.scope;

            elem.droppable(options);
            //console.log('drOPPable:', options);
        }
    };
}).directive('uiRearrange', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.uiRearrange),
            options = rearrangeOps;

            //console.log(vars);
            options.scope = vars.scope;

            options.helper = function(event) {
                return $('

').text(elem.data('part-id') ? elem.data('part-id').replace(/[a-z]/g, '') : '');
            };

            elem.draggable(options);
            //console.log('rearrange:', options);
        }
    };
}).directive('addPartId', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            elem.data('part-id', scope.partId);
            //console.log(elem.data('part-id'));
        }
    };
}).directive('stylePart', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.stylePart),
                part = vars.part,
                count = vars.count,
                viewIndex = vars.viewIndex,
                borderColors = scope.borderColors,

                style = {top: part['y' + count], left: part['x' + count]},
                colors = scope.colors,
                currentColor,
                randColor = function() {
                    if (colors.currentviewIndex !== viewIndex) {
                        //console.log('currentviewIndex:', colors.currentviewIndex, 'viewIndex:', viewIndex);
                        colors.currentviewIndex = viewIndex;
                        colors.colors = borderColors.slice(0);
                        //console.log(borderColors);
                    }

                    if (colors.currentPart !== part.name) {
                        colors.currentPart = part.name;

                        if (colors.currentIndex !== null) {
                            colors.colors.splice(colors.currentIndex, 1);
                        }

                        colors.currentIndex = Math.floor(Math.random() * colors.colors.length);
                    }

                    currentColor = colors.colors[colors.currentIndex];

                    scope.colors = colors;
                    //console.log(colors.colors, colors.currentIndex, currentColor);
                    return currentColor;
                };

            style['border-color'] = randColor();

            elem.css(style);
        }
    };
});
<commit_msg>Fixed part letters when dragging when view name has capitals and underscores. Added a directive to add a description/hint to a part, so long as one in given.<commit_after>'use strict';

var VIEW_NAME_REGEX = new RegExp(/[a-zA-Z_]+[a-z]/g),
dragOps = {
    addClass: false,
    cursorAt: { left: 17, top: 17 },
    revert: 'invalid',
    zIndex: 900,
    start: function(event, ui) {
        var self = $(this);
        //console.log('drag-start', self);
        self.addClass('ui-state-disabled');
    },
    stop: function(event, ui) {
        var self = $(this);
        //console.log('drag-stop', self);
        if (!self.data('dropped')) {
            self.draggable('enable');
            self.removeClass('ui-state-disabled');
        }
    }
},
dropOps = {
    addClasses: false,
    tolerance: 'intersect',
    over: function(event, ui) {
        var self = $(this);
        //console.log('drop-over', self);
        self.add(self.siblings()).addClass('ui-state-hover');
    },
    out: function(event, ui) {
        var self = $(this);
        //console.log('drop-out', self);
        self.add(self.siblings()).removeClass('ui-state-hover');
    },
    drop: function(event, ui) {
        $('.alert-error').remove();

        var self = $(this),
        selfGroup = self.add(self.siblings()),
        prevPart = ui.draggable,
        prevGroup = prevPart.add(prevPart.siblings()),
        letter = prevPart.data('part-id').replace(VIEW_NAME_REGEX, ''), // remove lowercase letters to leave the single uppercase part letter
        oldID = self.data('part-id');
        //console.log('drop-drop', self);

        if (selfGroup.hasClass('ui-state-hover')) { selfGroup.removeClass('ui-state-hover'); }

        // Dragged from the list to a spot...
        if (!prevPart.hasClass('part-drop')) {
            // that is empty
            if (self.data('part-id') === undefined) {
                //console.log('list to empty');
                prevPart.data('dropped', true).draggable('disable');
            }
            // that is already occupied
            else {
                //console.log('list to occupied');
                //console.log(self.clone());

                prevPart.data('dropped', true).draggable('disable');
                prevPart.siblings().each(function(){
                    var self = $(this);

                    if (self.data('part-id') === oldID) {
                        self.data('dropped', false).draggable('enable').removeClass('ui-state-disabled');

                        return false;
                    }
                });
            }

            selfGroup.addClass('ui-state-highlight').text(letter).data('part-id', prevPart.data('part-id'));
        }
        // Rearrange...
        else {
            // to a different part...
            if (self.data('part-id') !== prevPart.data('part-id')) {
                // that is empty
                if (self.data('part-id') === undefined) {
                    //console.log('rearrange to empty');
                    prevGroup.removeClass('ui-state-highlight').text('');
                }
                // that is already occupied
                else {
                    //console.log('rearrange to occupied', prevPart.data('part-id'), '>', self.data('part-id'));

                    selfGroup.data('part-id', prevPart.data('part-id'));
                   //console.log(self.data('part-id'));
                    selfGroup.text(prevPart.text());

                    prevGroup.data('part-id', oldID);
                    prevGroup.text(oldID.replace(VIEW_NAME_REGEX, ''));

                    return;
                }
            }
            // to a spot that is of the same part
            else if (self.data('part-id') === prevPart.data('part-id')) {
                //console.log('canceled drop b/c part was the same', self.data('part-id'), prevPart.data('part-id'))
                return false;
            }

            selfGroup.addClass('ui-state-highlight').text(letter).data('part-id', prevPart.data('part-id'));
            prevGroup.removeData('part-id');
        }

        //console.log(self.data());
    }
},
rearrangeOps = {
    addClass: false,
    cursorAt: { left: 17, top: 17 },
    revert: 'invalid',
    zIndex: 900,
    start: function(event, ui) {
        var self = $(this);
        //console.log('rearrange-start', self);

        if (!self.data('part-id')) {
            //console.log('canceled rearrange b/c it has no partID');
            return false;
        } else {
            self.add(self.siblings()).addClass('ui-draggable-disabled');
        }
    },
    stop: function(event, ui) {
        var self = $(this);
        //console.log('rearrange-stop', self);

        self.add(self.siblings()).removeClass('ui-draggable-disabled');
    }
};

/* Directives */

app.directive('uiDraggable', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.uiDraggable),
            options = dragOps;

            //console.log(vars);
            options.scope = vars.scope;
            options.helper = function(event) {
                return $('

').text(vars.helper.letter);
            };

            elem.draggable(options);
            //console.log('drAGGable:', options);
        }
    };
}).directive('uiDroppable', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.uiDroppable),
                options = dropOps;

                options.scope = vars.scope;

            elem.droppable(options);
            //console.log('drOPPable:', options);
        }
    };
}).directive('uiRearrange', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.uiRearrange),
            options = rearrangeOps;

            //console.log(vars);
            options.scope = vars.scope;

            options.helper = function(event) {
                return $('

').text(elem.data('part-id') ? elem.data('part-id').replace(VIEW_NAME_REGEX, '') : '');
            };

            elem.draggable(options);
            //console.log('rearrange:', options);
        }
    };
}).directive('addPartId', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            elem.data('part-id', scope.partId);
            //console.log(elem.data('part-id'));
        }
    };
}).directive('addPartDescription', function(){
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var icon, description;

            if (scope.part.description) {
                icon = $('').click(function(){scope.toggle(event)});
                description = $('' + scope.part.description + '');

                elem.append(icon).append(description);
                console.log('description', elem);
            }
        }
    };
}).directive('stylePart', function() {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var vars = scope.$eval(attrs.stylePart),
                part = vars.part,
                count = vars.count,
                viewIndex = vars.viewIndex,
                borderColors = scope.borderColors,

                style = {left: part['x' + count], top: part['y' + count]},
                colors = scope.colors,
                currentColor,
                randColor = function() {
                    if (colors.currentviewIndex !== viewIndex) {
                        //console.log('currentviewIndex:', colors.currentviewIndex, 'viewIndex:', viewIndex);
                        colors.currentviewIndex = viewIndex;
                        colors.colors = borderColors.slice(0);
                        //console.log(borderColors);
                    }

                    if (colors.currentPart !== part.name) {
                        colors.currentPart = part.name;

                        if (colors.currentIndex !== null) {
                            colors.colors.splice(colors.currentIndex, 1);
                        }

                        colors.currentIndex = Math.floor(Math.random() * colors.colors.length);
                    }

                    currentColor = colors.colors[colors.currentIndex];

                    scope.colors = colors;
                    //console.log(colors.colors, colors.currentIndex, currentColor);
                    return currentColor;
                };

            style['border-color'] = randColor();

            elem.css(style);
        }
    };
});
<|endoftext|>


<commit_before>import {
  props,
  define,
  declarativeClickHandler,
  sanitizeBoltClasses,
  hasNativeShadowDomSupport,
  afterNextRender,
  watchForComponentMutations,
} from '@bolt/core/utils';
import classNames from 'classnames/bind';
import {
  withLitHtml,
  html,
  render,
} from '@bolt/core/renderers/renderer-lit-html';
import Ajv from 'ajv';

import styles from './link.scss';
import schema from '../link.schema.yml';

const ajv = new Ajv({ useDefaults: 'shared' });

let cx = classNames.bind(styles);

@define
class BoltLink extends withLitHtml() {
  static is = 'bolt-link';

  static props = {
    url: props.string,
    target: props.string,
    isHeadline: props.boolean,
    onClick: props.string, // Managed by base class
    onClickTarget: props.string, // Managed by base class
  };

  // https://github.com/WebReflection/document-register-element#upgrading-the-constructor-context
  constructor(self) {
    self = super(self);
    self.useShadow = hasNativeShadowDomSupport;
    self.validate = ajv.compile(schema);
    return self;
  }

  // @todo: move to the global Bolt Base component after we're done testing this out with the new refactored Card component
  validateProps(propData) {
    var validatedData = propData;

    // remove default strings in prop data so schema validation can fill in the default
    for (let property in validatedData) {
      if (validatedData[property] === '') {
        delete validatedData[property];
      }
    }

    let isValid = this.validate(validatedData);

    // bark at any schema validation errors
    if (!isValid) {
      console.log(this.validate.errors);
    }

    return validatedData;
  }

  connecting() {
    const root = this;

    // If the initial <bolt-link> element contains a link, break apart the original HTML so we can retain the a tag but swap out the inner content with slots.

    // Make sure the button component ONLY ever reuses any existing HTML ONCE. This, in part, helps to prevent rendering diff errors in HyperHTML after booting up!
    if (this._wasInitiallyRendered === false) {
      this.childNodes.forEach((childElement, i) => {
        if (childElement.tagName === 'A') {
          root.rootElement = document.createDocumentFragment();

          // Take any existing elements and move them to the root of the custom element
          while (childElement.firstChild) {
            root.appendChild(childElement.firstChild);
          }

          if (childElement.className) {
            childElement.className = sanitizeBoltClasses(childElement);
          }

          if (
            childElement.getAttribute('is') &&
            childElement.getAttribute('is') === 'shadow-root'
          ) {
            childElement.removeAttribute('is');
          }

          root.rootElement.appendChild(childElement);
        }
      });
    }

    // When possible, use afterNextRender to defer non-critical work until after first paint.
    afterNextRender(this, function() {
      this.addEventListener('click', this.clickHandler);
    });
  }

  rendered() {
    super.rendered(); // ensure any events emitted by the Bolt Base class fire as expected

    // re-render if Shadow DOM is supported and enabled; temp workaround to dealing w/ components already rendered, but without slot support
    if (hasNativeShadowDomSupport && this.useShadow) {
      this.observer = watchForComponentMutations(this);

      this.observer.observe(this, {
        attributes: false,
        childList: true,
        characterData: false,
      });
    }
  }

  disconnecting() {
    this.removeEventListener('click', this.clickHandler);

    if (hasNativeShadowDomSupport && this.useShadow) {
      if (this.observer) {
        this.observer.disconnect();
      }
    }
  }

  // Attach external events declaratively
  clickHandler(event) {
    declarativeClickHandler(this);
  }

  render() {
    // validate the original prop data passed along -- returns back the validated data w/ added default values
    const { url, target, isHeadline } = this.validateProps(this.props);

    const classes = cx('c-bolt-link', {
      'c-bolt-link--headline': isHeadline,
    });

    // Decide on if the rendered button tag should be a <button> or  tag, based on if a URL exists OR if a link was passed in from the getgo
    const hasUrl = this.props.url.length > 0 && this.props.url !== 'null';

    // Assign default target attribute value if one isn't specified
    const anchorTarget =
      this.props.target && hasUrl ? this.props.target : '_self';

    // The linkElement to render, based on the initial HTML passed alone.
    let renderedLink;

    const slotMarkup = name => {
      switch (name) {
        case 'before':
        case 'after':
          const iconClasses = cx('c-bolt-link__icon', {
            'is-empty': name in this.slots === false,
          });

          return html`
            ${
                name in this.slots
                  ? this.slot(name)
                  : html`<slot name="${name}" />`
              }
          `;
        default:
          const itemClasses = cx('c-bolt-link__text', {
            'is-empty': name in this.slots === false,
          });

          return html`
            ${
                name in this.slots ? this.slot('default') : html`<slot/>`
              }
          `;
      }
    };

    const innerSlots = [
      slotMarkup('before'),
      slotMarkup('default'),
      slotMarkup('after'),
    ];

    if (this.rootElement) {
      renderedLink = this.rootElement.firstChild.cloneNode(true);
      if (renderedLink.getAttribute('href') === null && hasUrl) {
        renderedLink.setAttribute('href', this.props.url);
      }
      renderedLink.className += ' ' + classes;
      render(innerSlots, renderedLink);
    } else {
      renderedLink = html`
        ${innerSlots}
      `;
    }

    return html`
      ${this.addStyles([styles])} ${renderedLink}
    `;
  }
}

export { BoltLink };
<commit_msg>style: prettier fixes<commit_after>import {
  props,
  define,
  declarativeClickHandler,
  sanitizeBoltClasses,
  hasNativeShadowDomSupport,
  afterNextRender,
  watchForComponentMutations,
} from '@bolt/core/utils';
import classNames from 'classnames/bind';
import {
  withLitHtml,
  html,
  render,
} from '@bolt/core/renderers/renderer-lit-html';
import Ajv from 'ajv';

import styles from './link.scss';
import schema from '../link.schema.yml';

const ajv = new Ajv({ useDefaults: 'shared' });

let cx = classNames.bind(styles);

@define
class BoltLink extends withLitHtml() {
  static is = 'bolt-link';

  static props = {
    url: props.string,
    target: props.string,
    isHeadline: props.boolean,
    onClick: props.string, // Managed by base class
    onClickTarget: props.string, // Managed by base class
  };

  // https://github.com/WebReflection/document-register-element#upgrading-the-constructor-context
  constructor(self) {
    self = super(self);
    self.useShadow = hasNativeShadowDomSupport;
    self.validate = ajv.compile(schema);
    return self;
  }

  // @todo: move to the global Bolt Base component after we're done testing this out with the new refactored Card component
  validateProps(propData) {
    var validatedData = propData;

    // remove default strings in prop data so schema validation can fill in the default
    for (let property in validatedData) {
      if (validatedData[property] === '') {
        delete validatedData[property];
      }
    }

    let isValid = this.validate(validatedData);

    // bark at any schema validation errors
    if (!isValid) {
      console.log(this.validate.errors);
    }

    return validatedData;
  }

  connecting() {
    const root = this;

    // If the initial <bolt-link> element contains a link, break apart the original HTML so we can retain the a tag but swap out the inner content with slots.

    // Make sure the button component ONLY ever reuses any existing HTML ONCE. This, in part, helps to prevent rendering diff errors in HyperHTML after booting up!
    if (this._wasInitiallyRendered === false) {
      this.childNodes.forEach((childElement, i) => {
        if (childElement.tagName === 'A') {
          root.rootElement = document.createDocumentFragment();

          // Take any existing elements and move them to the root of the custom element
          while (childElement.firstChild) {
            root.appendChild(childElement.firstChild);
          }

          if (childElement.className) {
            childElement.className = sanitizeBoltClasses(childElement);
          }

          if (
            childElement.getAttribute('is') &&
            childElement.getAttribute('is') === 'shadow-root'
          ) {
            childElement.removeAttribute('is');
          }

          root.rootElement.appendChild(childElement);
        }
      });
    }

    // When possible, use afterNextRender to defer non-critical work until after first paint.
    afterNextRender(this, function() {
      this.addEventListener('click', this.clickHandler);
    });
  }

  rendered() {
    super.rendered(); // ensure any events emitted by the Bolt Base class fire as expected

    // re-render if Shadow DOM is supported and enabled; temp workaround to dealing w/ components already rendered, but without slot support
    if (hasNativeShadowDomSupport && this.useShadow) {
      this.observer = watchForComponentMutations(this);

      this.observer.observe(this, {
        attributes: false,
        childList: true,
        characterData: false,
      });
    }
  }

  disconnecting() {
    this.removeEventListener('click', this.clickHandler);

    if (hasNativeShadowDomSupport && this.useShadow) {
      if (this.observer) {
        this.observer.disconnect();
      }
    }
  }

  // Attach external events declaratively
  clickHandler(event) {
    declarativeClickHandler(this);
  }

  render() {
    // validate the original prop data passed along -- returns back the validated data w/ added default values
    const { url, target, isHeadline } = this.validateProps(this.props);

    const classes = cx('c-bolt-link', {
      'c-bolt-link--headline': isHeadline,
    });

    // Decide on if the rendered button tag should be a <button> or  tag, based on if a URL exists OR if a link was passed in from the getgo
    const hasUrl = this.props.url.length > 0 && this.props.url !== 'null';

    // Assign default target attribute value if one isn't specified
    const anchorTarget =
      this.props.target && hasUrl ? this.props.target : '_self';

    // The linkElement to render, based on the initial HTML passed alone.
    let renderedLink;

    const slotMarkup = name => {
      switch (name) {
        case 'before':
        case 'after':
          const iconClasses = cx('c-bolt-link__icon', {
            'is-empty': name in this.slots === false,
          });

          return html`
            ${
                name in this.slots
                  ? this.slot(name)
                  : html`
                      <slot name="${name}" />
                    `
              }
          `;
        default:
          const itemClasses = cx('c-bolt-link__text', {
            'is-empty': name in this.slots === false,
          });

          return html`
            ${
                name in this.slots
                  ? this.slot('default')
                  : html`
                      <slot />
                    `
              }
          `;
      }
    };

    const innerSlots = [
      slotMarkup('before'),
      slotMarkup('default'),
      slotMarkup('after'),
    ];

    if (this.rootElement) {
      renderedLink = this.rootElement.firstChild.cloneNode(true);
      if (renderedLink.getAttribute('href') === null && hasUrl) {
        renderedLink.setAttribute('href', this.props.url);
      }
      renderedLink.className += ' ' + classes;
      render(innerSlots, renderedLink);
    } else {
      renderedLink = html`
        ${innerSlots}
      `;
    }

    return html`
      ${this.addStyles([styles])} ${renderedLink}
    `;
  }
}

export { BoltLink };
<|endoftext|>


<commit_before>'use strict';

var directiveModule = angular.module('uchiwa.directives', []);

directiveModule.directive('bootstrapTooltip', function () {
  return {
    restrict: 'EA',
    link: function (scope, element) {
      element.tooltip();
    }
  };
});

directiveModule.directive('siteTheme', ['$cookieStore', 'settings', function ($cookieStore, settings) {
  return {
    restrict: 'EA',
    link: function (scope, element) {
      scope.themes = [
        {
          name: 'default'
        },
        {
          name: 'dark'
        }
      ];
      var lookupTheme = function (themeName) {
        return scope.themes[scope.themes.map(function (t) {
          return t.name;
        }).indexOf(themeName)];
      };
      var setTheme = function (theme) {
        var themeName = angular.isObject(theme) && angular.isDefined(theme.name) ? theme.name : settings.theme;
        scope.currentTheme = lookupTheme(themeName);
        $cookieStore.put('currentTheme', scope.currentTheme);
        var fullThemeName = 'uchiwa-' + scope.currentTheme.name;
        element.attr('href', 'css/' + fullThemeName + '/' + fullThemeName + '.css');
      };
      scope.$on('theme:changed', function (event, theme) {
        setTheme(theme);
      });

      setTheme($cookieStore.get('currentTheme'));
    }
  };
}]);

directiveModule.directive('statusGlyph', function() {
  return {
    restrict: 'EA',
    link: function(scope, element, attrs) {
      var style;

      function updateGlyph() {
        element.removeAttr('class');
        element.addClass('fa fa-fw');
        switch(style) {
          case 'success':
            element.addClass('fa-check-circle text-success');
            break;
          case 'warning':
            element.addClass('fa-exclamation-circle');
            break;
          case 'danger':
            element.addClass('fa-bomb');
            break;
          case 'muted':
            element.addClass('fa-question-circle');
            break;
        }
        element.addClass('text-' + style);
      }

      scope.$watch(attrs.statusGlyph, function(value) {
        style = value;
        updateGlyph();
      });
    }
  }
});
<commit_msg>fix coloring for critical/unknown states<commit_after>'use strict';

var directiveModule = angular.module('uchiwa.directives', []);

directiveModule.directive('bootstrapTooltip', function () {
  return {
    restrict: 'EA',
    link: function (scope, element) {
      element.tooltip();
    }
  };
});

directiveModule.directive('siteTheme', ['$cookieStore', 'settings', function ($cookieStore, settings) {
  return {
    restrict: 'EA',
    link: function (scope, element) {
      scope.themes = [
        {
          name: 'default'
        },
        {
          name: 'dark'
        }
      ];
      var lookupTheme = function (themeName) {
        return scope.themes[scope.themes.map(function (t) {
          return t.name;
        }).indexOf(themeName)];
      };
      var setTheme = function (theme) {
        var themeName = angular.isObject(theme) && angular.isDefined(theme.name) ? theme.name : settings.theme;
        scope.currentTheme = lookupTheme(themeName);
        $cookieStore.put('currentTheme', scope.currentTheme);
        var fullThemeName = 'uchiwa-' + scope.currentTheme.name;
        element.attr('href', 'css/' + fullThemeName + '/' + fullThemeName + '.css');
      };
      scope.$on('theme:changed', function (event, theme) {
        setTheme(theme);
      });

      setTheme($cookieStore.get('currentTheme'));
    }
  };
}]);

directiveModule.directive('statusGlyph', function() {
  return {
    restrict: 'EA',
    link: function(scope, element, attrs) {
      var style;

      function updateGlyph() {
        element.removeAttr('class');
        element.addClass('fa fa-fw');
        switch(style) {
          case 'success':
            element.addClass('fa-check-circle');
            break;
          case 'warning':
            element.addClass('fa-exclamation-circle');
            break;
          case 'danger':
            element.addClass('fa-bomb');
            break;
          case 'muted':
            element.addClass('fa-question-circle');
            break;
        }
        element.addClass('text-' + style);
      }

      scope.$watch(attrs.statusGlyph, function(value) {
        // convert sensu state to CSS class name
        var styleOverrides = {
          'critical': 'danger',
          'unknown': 'muted'
        };
        style = styleOverrides[value] ? styleOverrides[value] : value;
        updateGlyph();
      });
    }
  }
});
<|endoftext|>


<commit_before>const assert = require("chai").assert;
const command = require("../../../lib/commands/obtain");
const sinon = require("sinon");
const CompilerSupplier = require("@truffle/compile-solidity").CompilerSupplier;
let options, solc;

describe("obtain", () => {
  describe(".run(options)", function () {
    beforeEach(() => {
      options = {solc: "0.5.3"};
      solc = {version: () => "0.5.3"};
      sinon
        .stub(CompilerSupplier.prototype, "downloadAndCacheSolc")
        .returns(solc);
    });
    afterEach(() => {
      CompilerSupplier.prototype.downloadAndCacheSolc.restore();
    });

    it("calls downloadAndCacheSolc on the supplier with the version", async function () {
      await command.run(options);
      assert(
        CompilerSupplier.prototype.downloadAndCacheSolc.calledWith("0.5.3")
      );
    });

    describe("when options.solc is not present", async () {
      beforeEach(() => {
        options.solc = undefined;
      });

      it("throws an error", async function() {
        try {
          await command.run(options);
          assert.fail("The run command should have failed");
        } catch (error) {
          assert(
            error.message.includes(
              "You have specified a compiler that is unsupported"
            )
          );
        }
      });
    });
  });
});
<commit_msg>Update packages/core/test/lib/commands/obtain.js<commit_after>const assert = require("chai").assert;
const command = require("../../../lib/commands/obtain");
const sinon = require("sinon");
const CompilerSupplier = require("@truffle/compile-solidity").CompilerSupplier;
let options, solc;

describe("obtain", () => {
  describe(".run(options)", function () {
    beforeEach(() => {
      options = {solc: "0.5.3"};
      solc = {version: () => "0.5.3"};
      sinon
        .stub(CompilerSupplier.prototype, "downloadAndCacheSolc")
        .returns(solc);
    });
    afterEach(() => {
      CompilerSupplier.prototype.downloadAndCacheSolc.restore();
    });

    it("calls downloadAndCacheSolc on the supplier with the version", async function () {
      await command.run(options);
      assert(
        CompilerSupplier.prototype.downloadAndCacheSolc.calledWith("0.5.3")
      );
    });

    describe("when options.solc is not present", async function () {
      beforeEach(() => {
        options.solc = undefined;
      });

      it("throws an error", async function() {
        try {
          await command.run(options);
          assert.fail("The run command should have failed");
        } catch (error) {
          assert(
            error.message.includes(
              "You have specified a compiler that is unsupported"
            )
          );
        }
      });
    });
  });
});
<|endoftext|>


<commit_before>/* globals Kinetic, twitter */
var GameBoard = (function() {
	var _boardId = 'gameboard';
	var _boardStage;
	var _boardLayer;
	var _boardCenter;

	var _positions = [];
	var _enemies = [];

	var BOARD_SIZE = { w: 650, h: 550 },
		ENEMY_ICON_SIZE = 30,
		PROFILE_GRAVATAR_SIZE = 30,
		ATTACK_SPEED = 200, // ms
		MATH_DEG_TO_RAD = Math.PI / 180,
		ENEMY_HYPOTENUSE = Math.sqrt(2 * Math.pow(ENEMY_ICON_SIZE, 2)),
		ENEMY_HYPOTENUSE_HALF = ENEMY_HYPOTENUSE / 2,
		POSITION_OFFSET = Math.sqrt(2 * Math.pow(PROFILE_GRAVATAR_SIZE, 2)) / 2,
		POSITION_WIDTH = ENEMY_HYPOTENUSE + 2,
		POSITION_PADDING = (POSITION_WIDTH - ENEMY_ICON_SIZE) / 2,
		PLAYER_GRAVATAR_DEFAULT = 'http://c.dryicons.com/images/icon_sets/simplistica/png/32x32/user.png',
		ENEMY_ICONS = {
			grunt: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			swarmer: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			trooper: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			'speed-demon': 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			flyer: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			cluster: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			bruiser: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png'
		};

	function Position(num, center) {
		this.num = num;
		this.center = center;
		this.spots = [];

		this.radius = POSITION_OFFSET + this.num * POSITION_WIDTH;
		this.enemyRadius = this.getRadius() + POSITION_PADDING;
		this.maxOfSpots = Math.floor((2 * Math.PI * (this.radius + POSITION_WIDTH / 2)) / (ENEMY_ICON_SIZE * 1.5));
		this.spotAngle = 2 * Math.PI / this.maxOfSpots;
		this.startAngle = Math.asin((ENEMY_ICON_SIZE / 2) / this.enemyRadius);

		this.renderMark();
	}

	Position.prototype.getMaxSpots = function() {
		return this.maxOfSpots;
	};

	Position.prototype.getFreeSpot = function() {
		for (var i = 0; i < this.getMaxSpots(); i++) {
			if (typeof this.spots[i] === 'undefined' || this.spots[i] === false) {
				return this.spots[i] = {
					id: i,
					position: this,
					enemyAngle: this.spotAngle * i - this.startAngle
				};
			}
		}
		return false;
	};

	Position.prototype.renderMark = function() {
		this.mark = new Kinetic.Circle({
			x: this.center.x,
			y: this.center.y,
			radius: this.radius,
			stroke: '#555',
			strokeWidth: 1,
			dashArray: [10, 10]
		});
		_boardLayer.add(this.mark);
	};

	Position.prototype.getRadius = function() {
		return this.radius;
	};

	Position.prototype.getEnemyRadius = function() {
		return this.enemyRadius;
	};

	Position.prototype.getInitialAngle = function() {
		return this.startAngle;
	};

	Position.prototype.setSpot = function(spot, enemy) {
		if (spot >= this.maxOfSpots) {
			return;
		}
		this.spots[spot] = enemy;
	};

	Position.prototype.reset = function() {
		this.spots = [];
	};

	function Enemy(mob) {
		this.mob = mob;
		this.spot = null;
		this.image = null;
	}

	Enemy.prototype.render = function() {
		var pos = _positions[this.mob.position];
		var posSpot = pos.getFreeSpot();
		if (posSpot === false) {
			// No spot available
			return;
		}
		pos.setSpot(posSpot.id, this);
		this.spot = posSpot;

		var enemy = this,
			imageObj = new Image();
		imageObj.onload = function() {
			var enemyRadius = pos.getEnemyRadius(),
				posX = enemyRadius * Math.cos(posSpot.enemyAngle),
				posY = enemyRadius * Math.sin(posSpot.enemyAngle);

			enemy.image = new Kinetic.Image({
				x: _boardCenter.x + posX,
				y: _boardCenter.y + posY,
				image: imageObj,
				rotation: posSpot.enemyAngle,
				width: ENEMY_ICON_SIZE,
				height: ENEMY_ICON_SIZE
			});
			_boardLayer.add(enemy.image);
			_boardLayer.draw();
		};
		imageObj.src = ENEMY_ICONS[this.mob.type];
	};

	Enemy.prototype.updatePosition = function(posNum) {
		if (!this.spot || !this.image) {
			this.mob.position = posNum;
			this.render();
			return;
		}

		var oldSpot = this.spot,
			newPos = _positions[posNum],
			newSpot = newPos.getFreeSpot();

		if (newSpot === false) {
			this.kill();
			return;
		}

		var enemyRadius = newPos.getEnemyRadius(),
			posX = enemyRadius * Math.cos(newSpot.enemyAngle),
			posY = enemyRadius * Math.sin(newSpot.enemyAngle);

		// @todo add animation
		this.image.setPosition(_boardCenter.x + posX, _boardCenter.y + posY);
		this.image.setRotation(newSpot.enemyAngle);
		newPos.setSpot(newSpot.id, this);
		oldSpot.position.setSpot(oldSpot.id, false);
		this.spot = newSpot;
	};

	Enemy.prototype.getRotation = function() {
		return this.image === null ? 0 : this.image.getRotation();
	};

	Enemy.prototype.getCenterPoint = function() {
		if (this.image === null) {
			return { x: 0, y: 0};
		}

		var a45 = Math.PI / 4; // 45 deg to rad
		return {
			x: this.image.getX() + (Math.cos(a45 + this.image.getRotation()) * ENEMY_HYPOTENUSE_HALF),
			y: this.image.getY() + (Math.sin(a45 + this.image.getRotation()) * ENEMY_HYPOTENUSE_HALF),
		};
	};

	Enemy.prototype.kill = function() {
		if (this.spot) {
			this.spot.position.setSpot(this.spot.id, false);
		}
		if (this.image) {
			this.image.remove();
		}
	};

	function GameBoard() {
	}

	GameBoard.prototype.processRound = function(roundInfo, next) {
		this.previousRound = this.round;
		this.round = roundInfo;
		this.renderMobs(this.round.getMobs());

		var gb = this;
		this.displayPlayerAttack(function() {
			gb.displayEnemyAttack(function() {
				gb.displayEnemyMoves(function() {
					next();
				});
			});
		});
	};

	GameBoard.prototype.renderMobs = function(mobs) {
		_.each(mobs, function(mob) {
			if (typeof _enemies[mob.id] !== 'undefined') {
				// Do not render if the enemy is on the board
				return;
			}

			_enemies[mob.id] = new Enemy(mob);
			_enemies[mob.id].render();
		});
	};

	GameBoard.prototype.displayPlayerAttack = function(next) {
		if (!this.round.getMyAttacks()) {
			next();
			return;
		}

		var activeAnimations = 0;
		_.each(this.round.getMyAttacks(), function(attack) {
			var enemyId = attack.enemyId,
				enemy = _enemies[enemyId],
				isEnemyDead = !_.find(this.round.getMobs(), function(mob) { return mob.id === enemyId; });

			var enemyCenter = enemy.getCenterPoint(),
				attackAngle = Math.atan((enemyCenter.y - _boardCenter.y) / (enemyCenter.x - _boardCenter.x)),
				attackLine = new Kinetic.Line({
					x: _boardCenter.x,
					y: _boardCenter.y,
					points: [0, 0, 10, 0],
					stroke: 'red',
					rotation: attackAngle
				});
			_boardLayer.add(attackLine);

			var diffX = enemyCenter.x - attackLine.getX(),
				diffY = enemyCenter.y - attackLine.getY();
			var anim = new Kinetic.Animation(function(frame) {
				if (frame.time >= ATTACK_SPEED) {
					this.stop();
					attackLine.remove();

					if (isEnemyDead) {
						enemy.kill();
						delete _enemies[enemyId];
					}
					if (--activeAnimations === 0) {
						next();
					}
					return;
				}
				var rate = frame.time / ATTACK_SPEED;
				attackLine.setPosition(_boardCenter.x + diffX * rate, _boardCenter.y + diffY * rate);
			}, _boardLayer);
			activeAnimations++;
			anim.start();
		}, this);
	};

	GameBoard.prototype.displayEnemyAttack = function(next) {
		var attacks = _.filter(this.round.getEnemyActions() || [], function(action) {
			return action.type === 'attack';
		});

		var activeAnimations = 0;
		if (attacks.length === 0) {
			next();
			return;
		}

		_.each(attacks, function(attack) {
			var enemyId = attack.id,
				enemy = _enemies[enemyId],
				isEnemyDead = !_.find(this.round.getMobs(), function(mob) { return mob.id === enemyId; });

			var enemyCenter = enemy.getCenterPoint(),
				attackAngle = Math.atan((enemyCenter.y - _boardCenter.y) / (enemyCenter.x - _boardCenter.x)),
				attackLine = new Kinetic.Line({
					x: enemyCenter.x,
					y: enemyCenter.y,
					points: [0, 0, 10, 0],
					stroke: 'yellow',
					rotation: attackAngle
				});
			_boardLayer.add(attackLine);

			var diffX = attackLine.getX() - _boardCenter.x,
				diffY = attackLine.getY() - _boardCenter.y;
			var anim = new Kinetic.Animation(function(frame) {
				if (frame.time >= ATTACK_SPEED) {
					this.stop();
					attackLine.remove();

					if (--activeAnimations === 0) {
						next();
					}
					return;
				}
				var rate = frame.time / ATTACK_SPEED;
				attackLine.setPosition(enemyCenter.x - diffX * rate, enemyCenter.y - diffY * rate);
			}, _boardLayer);
			activeAnimations++;
			anim.start();
		}, this);
	};

	GameBoard.prototype.displayEnemyMoves = function(next) {
		var moves = _.filter(this.round.getEnemyActions() || [], function(action) {
			return action.type === 'move';
		});

		_.each(moves, function(move) {
			_enemies[move.id].updatePosition(move.position);
		}, this);
		next();
	};

	GameBoard.renderUser = function() {
		GameBoard._profileImage = new Kinetic.Image({
			x: _boardCenter.x - (PROFILE_GRAVATAR_SIZE / 2),
			y: _boardCenter.y - (PROFILE_GRAVATAR_SIZE / 2),
			width: PROFILE_GRAVATAR_SIZE,
			height: PROFILE_GRAVATAR_SIZE
		});
		_boardLayer.add(GameBoard._profileImage);

		GameBoard._originalGravatar = new Image();
		GameBoard._originalGravatar.onload = function() {
			GameBoard._profileImage.setImage(this);
			_boardLayer.draw();
		};
		GameBoard._originalGravatar.src = (typeof twitter !== 'undefined' && twitter.profile_image_url_https) || PLAYER_GRAVATAR_DEFAULT;

		GameBoard._defeatedGravatar = new Image();
		GameBoard._defeatedGravatar.src = '/img/defeated.png';
	};

	GameBoard.defeated = function() {
		GameBoard._profileImage.setImage(GameBoard._defeatedGravatar);
		_boardLayer.draw();
	};

	GameBoard.renderPositionMarks = function() {
		_.each([0, 1, 2, 3, 4, 5], function(pos) {
			_positions[pos] = new Position(pos, _boardCenter);
		});
	};

	GameBoard.renderTemplate = function() {
		GameBoard.renderUser();
		GameBoard.renderPositionMarks();
	};

	GameBoard.boardSetup = function() {
		_boardStage = new Kinetic.Stage({
			container: _boardId,
			width: BOARD_SIZE.w,
			height: BOARD_SIZE.h
		});
		_boardCenter = {
			x: _boardStage.getWidth() / 2,
			y: _boardStage.getHeight() / 2
		};
		_boardLayer = new Kinetic.Layer();
		_boardStage.add(_boardLayer);

		GameBoard.renderTemplate();
		_boardLayer.draw();
	};

	GameBoard.cleanup = function() {
		GameBoard._profileImage.setImage(GameBoard._originalGravatar);

		_.each(_enemies, function(enemy) {
			enemy.kill();
		});
		_enemies = [];

		_.each(_positions, function(position) {
			position.reset();
		});

		_boardLayer.draw();
	};

	return GameBoard;

}());<commit_msg>Making the enemies point to the player center<commit_after>/* globals Kinetic, twitter */
var GameBoard = (function() {
	var _boardId = 'gameboard';
	var _boardStage;
	var _boardLayer;
	var _boardCenter;

	var _positions = [];
	var _enemies = [];

	var BOARD_SIZE = { w: 650, h: 550 },
		ENEMY_ICON_SIZE = 30,
		PROFILE_GRAVATAR_SIZE = 30,
		ATTACK_SPEED = 200, // ms
		MATH_DEG_TO_RAD = Math.PI / 180,
		MATH_45DEG_TO_RAD = Math.PI / 4,
		ENEMY_HYPOTENUSE = Math.sqrt(2 * Math.pow(ENEMY_ICON_SIZE, 2)),
		ENEMY_HYPOTENUSE_HALF = ENEMY_HYPOTENUSE / 2,
		POSITION_OFFSET = Math.sqrt(2 * Math.pow(PROFILE_GRAVATAR_SIZE, 2)) / 2,
		POSITION_WIDTH = ENEMY_HYPOTENUSE + 2,
		POSITION_PADDING = POSITION_WIDTH / 2,
		PLAYER_GRAVATAR_DEFAULT = 'http://c.dryicons.com/images/icon_sets/simplistica/png/32x32/user.png',
		ENEMY_ICONS = {
			grunt: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			swarmer: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			trooper: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			'speed-demon': 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			flyer: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			cluster: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png',
			bruiser: 'http://www.southeastarrow.com/images/icons/blue-left-arrow.png'
		};

	function Position(num, center) {
		this.num = num;
		this.center = center;
		this.spots = [];

		this.radius = POSITION_OFFSET + this.num * POSITION_WIDTH;
		this.enemyRadius = this.getRadius() + POSITION_PADDING;
		this.maxOfSpots = Math.floor((2 * Math.PI * (this.radius + POSITION_WIDTH / 2)) / (ENEMY_ICON_SIZE * 1.5));
		this.spotAngle = 2 * Math.PI / this.maxOfSpots;

		this.renderMark();
	}

	Position.prototype.getMaxSpots = function() {
		return this.maxOfSpots;
	};

	Position.prototype.getFreeSpot = function() {
		for (var i = 0; i < this.getMaxSpots(); i++) {
			if (typeof this.spots[i] === 'undefined' || this.spots[i] === false) {
				return this.spots[i] = {
					id: i,
					position: this,
					enemyAngle: this.spotAngle * i
				};
			}
		}
		return false;
	};

	Position.prototype.renderMark = function() {
		this.mark = new Kinetic.Circle({
			x: this.center.x,
			y: this.center.y,
			radius: this.radius,
			stroke: '#555',
			strokeWidth: 1,
			dashArray: [10, 10]
		});
		_boardLayer.add(this.mark);
	};

	Position.prototype.getRadius = function() {
		return this.radius;
	};

	Position.prototype.getEnemyRadius = function() {
		return this.enemyRadius;
	};

	Position.prototype.setSpot = function(spot, enemy) {
		if (spot >= this.maxOfSpots) {
			return;
		}
		this.spots[spot] = enemy;
	};

	Position.prototype.reset = function() {
		this.spots = [];
	};

	function Enemy(mob) {
		this.mob = mob;
		this.spot = null;
		this.image = null;
	}

	Enemy.prototype.render = function() {
		var pos = _positions[this.mob.position];
		var posSpot = pos.getFreeSpot();
		if (posSpot === false) {
			// No spot available
			return;
		}
		pos.setSpot(posSpot.id, this);
		this.spot = posSpot;

		var enemy = this,
			imageObj = new Image();
		imageObj.onload = function() {
			var enemyRadius = pos.getEnemyRadius(),
				angle = posSpot.enemyAngle,
				posX = enemyRadius * Math.cos(angle) - (Math.cos(MATH_45DEG_TO_RAD + angle) * ENEMY_HYPOTENUSE_HALF),
				posY = enemyRadius * Math.sin(angle) - (Math.sin(MATH_45DEG_TO_RAD + angle) * ENEMY_HYPOTENUSE_HALF);

			enemy.image = new Kinetic.Image({
				x: _boardCenter.x + posX,
				y: _boardCenter.y + posY,
				image: imageObj,
				rotation: angle,
				width: ENEMY_ICON_SIZE,
				height: ENEMY_ICON_SIZE
			});
			_boardLayer.add(enemy.image);
			_boardLayer.draw();
		};
		imageObj.src = ENEMY_ICONS[this.mob.type];
	};

	Enemy.prototype.updatePosition = function(posNum) {
		if (!this.spot || !this.image) {
			this.mob.position = posNum;
			this.render();
			return;
		}

		var oldSpot = this.spot,
			newPos = _positions[posNum],
			newSpot = newPos.getFreeSpot();

		if (newSpot === false) {
			this.kill();
			return;
		}

		var enemyRadius = newPos.getEnemyRadius(),
			angle = newSpot.enemyAngle,
			posX = enemyRadius * Math.cos(angle) - (Math.cos(MATH_45DEG_TO_RAD + angle) * ENEMY_HYPOTENUSE_HALF),
			posY = enemyRadius * Math.sin(angle) - (Math.sin(MATH_45DEG_TO_RAD + angle) * ENEMY_HYPOTENUSE_HALF);

		// @todo add animation
		this.image.setPosition(_boardCenter.x + posX, _boardCenter.y + posY);
		this.image.setRotation(angle);
		newPos.setSpot(newSpot.id, this);
		oldSpot.position.setSpot(oldSpot.id, false);
		this.spot = newSpot;
	};

	Enemy.prototype.getRotation = function() {
		return this.image === null ? 0 : this.image.getRotation();
	};

	Enemy.prototype.getCenterPoint = function() {
		if (this.image === null) {
			return { x: 0, y: 0};
		}

		return {
			x: this.image.getX() + (Math.cos(MATH_45DEG_TO_RAD + this.image.getRotation()) * ENEMY_HYPOTENUSE_HALF),
			y: this.image.getY() + (Math.sin(MATH_45DEG_TO_RAD + this.image.getRotation()) * ENEMY_HYPOTENUSE_HALF),
		};
	};

	Enemy.prototype.kill = function() {
		if (this.spot) {
			this.spot.position.setSpot(this.spot.id, false);
		}
		if (this.image) {
			this.image.remove();
		}
	};

	function GameBoard() {
	}

	GameBoard.prototype.processRound = function(roundInfo, next) {
		this.previousRound = this.round;
		this.round = roundInfo;
		this.renderMobs(this.round.getMobs());

		var gb = this;
		this.displayPlayerAttack(function() {
			gb.displayEnemyAttack(function() {
				gb.displayEnemyMoves(function() {
					next();
				});
			});
		});
	};

	GameBoard.prototype.renderMobs = function(mobs) {
		_.each(mobs, function(mob) {
			if (typeof _enemies[mob.id] !== 'undefined') {
				// Do not render if the enemy is on the board
				return;
			}

			_enemies[mob.id] = new Enemy(mob);
			_enemies[mob.id].render();
		});
	};

	GameBoard.prototype.displayPlayerAttack = function(next) {
		if (!this.round.getMyAttacks()) {
			next();
			return;
		}

		var activeAnimations = 0;
		_.each(this.round.getMyAttacks(), function(attack) {
			var enemyId = attack.enemyId,
				enemy = _enemies[enemyId],
				isEnemyDead = !_.find(this.round.getMobs(), function(mob) { return mob.id === enemyId; });

			var enemyCenter = enemy.getCenterPoint(),
				attackAngle = Math.atan((enemyCenter.y - _boardCenter.y) / (enemyCenter.x - _boardCenter.x)),
				attackLine = new Kinetic.Line({
					x: _boardCenter.x,
					y: _boardCenter.y,
					points: [0, 0, 10, 0],
					stroke: 'red',
					rotation: attackAngle
				});
			_boardLayer.add(attackLine);

			var diffX = enemyCenter.x - attackLine.getX(),
				diffY = enemyCenter.y - attackLine.getY();
			var anim = new Kinetic.Animation(function(frame) {
				if (frame.time >= ATTACK_SPEED) {
					this.stop();
					attackLine.remove();

					if (isEnemyDead) {
						enemy.kill();
						delete _enemies[enemyId];
					}
					if (--activeAnimations === 0) {
						next();
					}
					return;
				}
				var rate = frame.time / ATTACK_SPEED;
				attackLine.setPosition(_boardCenter.x + diffX * rate, _boardCenter.y + diffY * rate);
			}, _boardLayer);
			activeAnimations++;
			anim.start();
		}, this);
	};

	GameBoard.prototype.displayEnemyAttack = function(next) {
		var attacks = _.filter(this.round.getEnemyActions() || [], function(action) {
			return action.type === 'attack';
		});

		var activeAnimations = 0;
		if (attacks.length === 0) {
			next();
			return;
		}

		_.each(attacks, function(attack) {
			var enemyId = attack.id,
				enemy = _enemies[enemyId],
				isEnemyDead = !_.find(this.round.getMobs(), function(mob) { return mob.id === enemyId; });

			var enemyCenter = enemy.getCenterPoint(),
				attackAngle = Math.atan((enemyCenter.y - _boardCenter.y) / (enemyCenter.x - _boardCenter.x)),
				attackLine = new Kinetic.Line({
					x: enemyCenter.x,
					y: enemyCenter.y,
					points: [0, 0, 10, 0],
					stroke: 'yellow',
					rotation: attackAngle
				});
			_boardLayer.add(attackLine);

			var diffX = attackLine.getX() - _boardCenter.x,
				diffY = attackLine.getY() - _boardCenter.y;
			var anim = new Kinetic.Animation(function(frame) {
				if (frame.time >= ATTACK_SPEED) {
					this.stop();
					attackLine.remove();

					if (--activeAnimations === 0) {
						next();
					}
					return;
				}
				var rate = frame.time / ATTACK_SPEED;
				attackLine.setPosition(enemyCenter.x - diffX * rate, enemyCenter.y - diffY * rate);
			}, _boardLayer);
			activeAnimations++;
			anim.start();
		}, this);
	};

	GameBoard.prototype.displayEnemyMoves = function(next) {
		var moves = _.filter(this.round.getEnemyActions() || [], function(action) {
			return action.type === 'move';
		});

		_.each(moves, function(move) {
			_enemies[move.id].updatePosition(move.position);
		}, this);
		next();
	};

	GameBoard.renderUser = function() {
		GameBoard._profileImage = new Kinetic.Image({
			x: _boardCenter.x - (PROFILE_GRAVATAR_SIZE / 2),
			y: _boardCenter.y - (PROFILE_GRAVATAR_SIZE / 2),
			width: PROFILE_GRAVATAR_SIZE,
			height: PROFILE_GRAVATAR_SIZE
		});
		_boardLayer.add(GameBoard._profileImage);

		GameBoard._originalGravatar = new Image();
		GameBoard._originalGravatar.onload = function() {
			GameBoard._profileImage.setImage(this);
			_boardLayer.draw();
		};
		GameBoard._originalGravatar.src = (typeof twitter !== 'undefined' && twitter.profile_image_url_https) || PLAYER_GRAVATAR_DEFAULT;

		GameBoard._defeatedGravatar = new Image();
		GameBoard._defeatedGravatar.src = '/img/defeated.png';
	};

	GameBoard.defeated = function() {
		GameBoard._profileImage.setImage(GameBoard._defeatedGravatar);
		_boardLayer.draw();
	};

	GameBoard.renderPositionMarks = function() {
		_.each([0, 1, 2, 3, 4, 5], function(pos) {
			_positions[pos] = new Position(pos, _boardCenter);
		});
	};

	GameBoard.renderTemplate = function() {
		GameBoard.renderUser();
		GameBoard.renderPositionMarks();
	};

	GameBoard.boardSetup = function() {
		_boardStage = new Kinetic.Stage({
			container: _boardId,
			width: BOARD_SIZE.w,
			height: BOARD_SIZE.h
		});
		_boardCenter = {
			x: _boardStage.getWidth() / 2,
			y: _boardStage.getHeight() / 2
		};
		_boardLayer = new Kinetic.Layer();
		_boardStage.add(_boardLayer);

		GameBoard.renderTemplate();
		_boardLayer.draw();
	};

	GameBoard.cleanup = function() {
		GameBoard._profileImage.setImage(GameBoard._originalGravatar);

		_.each(_enemies, function(enemy) {
			enemy.kill();
		});
		_enemies = [];

		_.each(_positions, function(position) {
			position.reset();
		});

		_boardLayer.draw();
	};

	return GameBoard;

}());<|endoftext|>


<commit_before>import { guidFor, OWNER } from 'ember-utils';
import { Cache, _instrumentStart } from 'ember-metal';
import { assert, warn } from 'ember-debug';
import { EMBER_MODULE_UNIFICATION } from 'ember/features';
import { DEBUG } from 'ember-env-flags';
import {
  lookupPartial,
  hasPartial,
  lookupComponent,
  constructStyleDeprecationMessage
} from 'ember-views';
import {
  Environment as GlimmerEnvironment,
  AttributeManager,
  isSafeString,
  compileLayout,
  getDynamicVar
} from '@glimmer/runtime';
import {
  CurlyComponentDefinition
} from './component-managers/curly';
import {
  populateMacros
} from './syntax';
import createIterable from './utils/iterable';
import {
  ConditionalReference,
  SimpleHelperReference,
  ClassBasedHelperReference
} from './utils/references';
import DebugStack from './utils/debug-stack';

import {
  inlineIf,
  inlineUnless
} from './helpers/if-unless';
import { default as action } from './helpers/action';
import { default as componentHelper } from './helpers/component';
import { default as concat } from './helpers/concat';
import { default as get } from './helpers/get';
import { default as hash } from './helpers/hash';
import { default as loc } from './helpers/loc';
import { default as log } from './helpers/log';
import { default as mut } from './helpers/mut';
import { default as readonly } from './helpers/readonly';
import { default as unbound } from './helpers/unbound';
import { default as classHelper } from './helpers/-class';
import { default as inputTypeHelper } from './helpers/-input-type';
import { default as queryParams } from './helpers/query-param';
import { default as eachIn } from './helpers/each-in';
import { default as normalizeClassHelper } from './helpers/-normalize-class';
import { default as htmlSafeHelper } from './helpers/-html-safe';

import installPlatformSpecificProtocolForURL from './protocol-for-url';
import { default as ActionModifierManager } from './modifiers/action';

import {
  GLIMMER_CUSTOM_COMPONENT_MANAGER
} from 'ember/features';

function instrumentationPayload(name) {
  return { object: `component:${name}` };
}

export default class Environment extends GlimmerEnvironment {
  static create(options) {
    return new Environment(options);
  }

  constructor({ [OWNER]: owner }) {
    super(...arguments);
    this.owner = owner;
    this.isInteractive = owner.lookup('-environment:main').isInteractive;

    // can be removed once https://github.com/tildeio/glimmer/pull/305 lands
    this.destroyedComponents = [];

    installPlatformSpecificProtocolForURL(this);

    this._definitionCache = new Cache(2000, ({ name, source, owner }) => {
      let { component: componentFactory, layout } = lookupComponent(owner, name, { source });
      let customManager = undefined;

      if (componentFactory || layout) {
        if (GLIMMER_CUSTOM_COMPONENT_MANAGER) {
          let managerId = layout && layout.meta.managerId;

          if (managerId) {
            customManager = owner.factoryFor(`component-manager:${managerId}`).class;
          }
        }
        return new CurlyComponentDefinition(name, componentFactory, layout, undefined, customManager);
      }
    }, ({ name, source, owner }) => {
      let expandedName = source && this._resolveLocalLookupName(name, source, owner) || name;

      let ownerGuid = guidFor(owner);

      return ownerGuid + '|' + expandedName;
    });

    this._templateCache = new Cache(1000, ({ Template, owner }) => {
      if (Template.create) {
        // we received a factory
        return Template.create({ env: this, [OWNER]: owner });
      } else {
        // we were provided an instance already
        return Template;
      }
    }, ({ Template, owner }) => guidFor(owner) + '|' + Template.id);

    this._compilerCache = new Cache(10, Compiler => {
      return new Cache(2000, (template) => {
        let compilable = new Compiler(template);
        return compileLayout(compilable, this);
      }, (template)=> {
        let owner = template.meta.owner;
        return guidFor(owner) + '|' + template.id;
      });
    }, Compiler => Compiler.id);

    this.builtInModifiers = {
      action: new ActionModifierManager()
    };

    this.builtInHelpers = {
      if: inlineIf,
      action,
      concat,
      get,
      hash,
      loc,
      log,
      mut,
      'query-params': queryParams,
      readonly,
      unbound,
      unless: inlineUnless,
      '-class': classHelper,
      '-each-in': eachIn,
      '-input-type': inputTypeHelper,
      '-normalize-class': normalizeClassHelper,
      '-html-safe': htmlSafeHelper,
      '-get-dynamic-var': getDynamicVar
    };

    if (DEBUG) {
      this.debugStack = new DebugStack()
    }
  }

  _resolveLocalLookupName(name, source, owner) {
    return EMBER_MODULE_UNIFICATION ? `${source}:${name}`
      : owner._resolveLocalLookupName(name, source);
  }

  macros() {
    let macros = super.macros();
    populateMacros(macros.blocks, macros.inlines);
    return macros;
  }

  hasComponentDefinition() {
    return false;
  }

  getComponentDefinition(name, { owner, moduleName }) {
    let finalizer = _instrumentStart('render.getComponentDefinition', instrumentationPayload, name);
    let source = moduleName && `template:${moduleName}`;
    let definition = this._definitionCache.get({ name, source, owner });
    finalizer();
    return definition;
  }

  // normally templates should be exported at the proper module name
  // and cached in the container, but this cache supports templates
  // that have been set directly on the component's layout property
  getTemplate(Template, owner) {
    return this._templateCache.get({ Template, owner });
  }

  // a Compiler can wrap the template so it needs its own cache
  getCompiledBlock(Compiler, template) {
    let compilerCache = this._compilerCache.get(Compiler);
    return compilerCache.get(template);
  }

  hasPartial(name, { owner }) {
    return hasPartial(name, owner);
  }

  lookupPartial(name, { owner }) {
    let partial = {
      template: lookupPartial(name, owner)
    };

    if (partial.template) {
      return partial;
    } else {
      throw new Error(`${name} is not a partial`);
    }
  }

  hasHelper(name, { owner, moduleName }) {
    if (name === 'component' || this.builtInHelpers[name]) {
      return true;
    }

    let options = { source: `template:${moduleName}` };

    return owner.hasRegistration(`helper:${name}`, options) ||
      owner.hasRegistration(`helper:${name}`);
  }

  lookupHelper(name, meta) {
    if (name === 'component') {
      return (vm, args) => componentHelper(vm, args, meta);
    }

    let { owner, moduleName } = meta;
    let helper = this.builtInHelpers[name];

    if (helper) {
      return helper;
    }

    let options = moduleName && { source: `template:${moduleName}` } || {};
    let helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`);

    // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations
    if (helperFactory.class.isHelperInstance) {
      return (vm, args) => SimpleHelperReference.create(helperFactory.class.compute, args.capture());
    } else if (helperFactory.class.isHelperFactory) {
      return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture());
    } else {
      throw new Error(`${name} is not a helper`);
    }
  }

  hasModifier(name) {
    return !!this.builtInModifiers[name];
  }

  lookupModifier(name) {
    let modifier = this.builtInModifiers[name];

    if (modifier) {
      return modifier;
    } else {
      throw new Error(`${name} is not a modifier`);
    }
  }

  toConditionalReference(reference) {
    return ConditionalReference.create(reference);
  }

  iterableFor(ref, key) {
    return createIterable(ref, key);
  }

  scheduleInstallModifier() {
    if (this.isInteractive) {
      super.scheduleInstallModifier(...arguments);
    }
  }

  scheduleUpdateModifier() {
    if (this.isInteractive) {
      super.scheduleUpdateModifier(...arguments);
    }
  }

  didDestroy(destroyable) {
    destroyable.destroy();
  }

  begin() {
    this.inTransaction = true;

    super.begin();
  }

  commit() {
    let destroyedComponents = this.destroyedComponents;
    this.destroyedComponents = [];
    // components queued for destruction must be destroyed before firing
    // `didCreate` to prevent errors when removing and adding a component
    // with the same name (would throw an error when added to view registry)
    for (let i = 0; i < destroyedComponents.length; i++) {
      destroyedComponents[i].destroy();
    }

    super.commit();

    this.inTransaction = false;
  }
}

if (DEBUG) {
  class StyleAttributeManager extends AttributeManager {
    setAttribute(dom, element, value) {
      warn(constructStyleDeprecationMessage(value), (() => {
        if (value === null || value === undefined || isSafeString(value)) {
          return true;
        }
        return false;
      })(), { id: 'ember-htmlbars.style-xss-warning' });
      super.setAttribute(...arguments);
    }

    updateAttribute(dom, element, value) {
      warn(constructStyleDeprecationMessage(value), (() => {
        if (value === null || value === undefined || isSafeString(value)) {
          return true;
        }
        return false;
      })(), { id: 'ember-htmlbars.style-xss-warning' });
      super.updateAttribute(...arguments);
    }
  }

  let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager('style');

  Environment.prototype.attributeFor = function(element, attribute, isTrusting, namespace) {
    if (attribute === 'style' && !isTrusting) {
      return STYLE_ATTRIBUTE_MANANGER;
    }

    return GlimmerEnvironment.prototype.attributeFor.call(this, element, attribute, isTrusting);
  };
}
<commit_msg>Properly instantiate subclass from Environment.create.<commit_after>import { guidFor, OWNER } from 'ember-utils';
import { Cache, _instrumentStart } from 'ember-metal';
import { assert, warn } from 'ember-debug';
import { EMBER_MODULE_UNIFICATION } from 'ember/features';
import { DEBUG } from 'ember-env-flags';
import {
  lookupPartial,
  hasPartial,
  lookupComponent,
  constructStyleDeprecationMessage
} from 'ember-views';
import {
  Environment as GlimmerEnvironment,
  AttributeManager,
  isSafeString,
  compileLayout,
  getDynamicVar
} from '@glimmer/runtime';
import {
  CurlyComponentDefinition
} from './component-managers/curly';
import {
  populateMacros
} from './syntax';
import createIterable from './utils/iterable';
import {
  ConditionalReference,
  SimpleHelperReference,
  ClassBasedHelperReference
} from './utils/references';
import DebugStack from './utils/debug-stack';

import {
  inlineIf,
  inlineUnless
} from './helpers/if-unless';
import { default as action } from './helpers/action';
import { default as componentHelper } from './helpers/component';
import { default as concat } from './helpers/concat';
import { default as get } from './helpers/get';
import { default as hash } from './helpers/hash';
import { default as loc } from './helpers/loc';
import { default as log } from './helpers/log';
import { default as mut } from './helpers/mut';
import { default as readonly } from './helpers/readonly';
import { default as unbound } from './helpers/unbound';
import { default as classHelper } from './helpers/-class';
import { default as inputTypeHelper } from './helpers/-input-type';
import { default as queryParams } from './helpers/query-param';
import { default as eachIn } from './helpers/each-in';
import { default as normalizeClassHelper } from './helpers/-normalize-class';
import { default as htmlSafeHelper } from './helpers/-html-safe';

import installPlatformSpecificProtocolForURL from './protocol-for-url';
import { default as ActionModifierManager } from './modifiers/action';

import {
  GLIMMER_CUSTOM_COMPONENT_MANAGER
} from 'ember/features';

function instrumentationPayload(name) {
  return { object: `component:${name}` };
}

export default class Environment extends GlimmerEnvironment {
  static create(options) {
    return new this(options);
  }

  constructor({ [OWNER]: owner }) {
    super(...arguments);
    this.owner = owner;
    this.isInteractive = owner.lookup('-environment:main').isInteractive;

    // can be removed once https://github.com/tildeio/glimmer/pull/305 lands
    this.destroyedComponents = [];

    installPlatformSpecificProtocolForURL(this);

    this._definitionCache = new Cache(2000, ({ name, source, owner }) => {
      let { component: componentFactory, layout } = lookupComponent(owner, name, { source });
      let customManager = undefined;

      if (componentFactory || layout) {
        if (GLIMMER_CUSTOM_COMPONENT_MANAGER) {
          let managerId = layout && layout.meta.managerId;

          if (managerId) {
            customManager = owner.factoryFor(`component-manager:${managerId}`).class;
          }
        }
        return new CurlyComponentDefinition(name, componentFactory, layout, undefined, customManager);
      }
    }, ({ name, source, owner }) => {
      let expandedName = source && this._resolveLocalLookupName(name, source, owner) || name;

      let ownerGuid = guidFor(owner);

      return ownerGuid + '|' + expandedName;
    });

    this._templateCache = new Cache(1000, ({ Template, owner }) => {
      if (Template.create) {
        // we received a factory
        return Template.create({ env: this, [OWNER]: owner });
      } else {
        // we were provided an instance already
        return Template;
      }
    }, ({ Template, owner }) => guidFor(owner) + '|' + Template.id);

    this._compilerCache = new Cache(10, Compiler => {
      return new Cache(2000, (template) => {
        let compilable = new Compiler(template);
        return compileLayout(compilable, this);
      }, (template)=> {
        let owner = template.meta.owner;
        return guidFor(owner) + '|' + template.id;
      });
    }, Compiler => Compiler.id);

    this.builtInModifiers = {
      action: new ActionModifierManager()
    };

    this.builtInHelpers = {
      if: inlineIf,
      action,
      concat,
      get,
      hash,
      loc,
      log,
      mut,
      'query-params': queryParams,
      readonly,
      unbound,
      unless: inlineUnless,
      '-class': classHelper,
      '-each-in': eachIn,
      '-input-type': inputTypeHelper,
      '-normalize-class': normalizeClassHelper,
      '-html-safe': htmlSafeHelper,
      '-get-dynamic-var': getDynamicVar
    };

    if (DEBUG) {
      this.debugStack = new DebugStack()
    }
  }

  _resolveLocalLookupName(name, source, owner) {
    return EMBER_MODULE_UNIFICATION ? `${source}:${name}`
      : owner._resolveLocalLookupName(name, source);
  }

  macros() {
    let macros = super.macros();
    populateMacros(macros.blocks, macros.inlines);
    return macros;
  }

  hasComponentDefinition() {
    return false;
  }

  getComponentDefinition(name, { owner, moduleName }) {
    let finalizer = _instrumentStart('render.getComponentDefinition', instrumentationPayload, name);
    let source = moduleName && `template:${moduleName}`;
    let definition = this._definitionCache.get({ name, source, owner });
    finalizer();
    return definition;
  }

  // normally templates should be exported at the proper module name
  // and cached in the container, but this cache supports templates
  // that have been set directly on the component's layout property
  getTemplate(Template, owner) {
    return this._templateCache.get({ Template, owner });
  }

  // a Compiler can wrap the template so it needs its own cache
  getCompiledBlock(Compiler, template) {
    let compilerCache = this._compilerCache.get(Compiler);
    return compilerCache.get(template);
  }

  hasPartial(name, { owner }) {
    return hasPartial(name, owner);
  }

  lookupPartial(name, { owner }) {
    let partial = {
      template: lookupPartial(name, owner)
    };

    if (partial.template) {
      return partial;
    } else {
      throw new Error(`${name} is not a partial`);
    }
  }

  hasHelper(name, { owner, moduleName }) {
    if (name === 'component' || this.builtInHelpers[name]) {
      return true;
    }

    let options = { source: `template:${moduleName}` };

    return owner.hasRegistration(`helper:${name}`, options) ||
      owner.hasRegistration(`helper:${name}`);
  }

  lookupHelper(name, meta) {
    if (name === 'component') {
      return (vm, args) => componentHelper(vm, args, meta);
    }

    let { owner, moduleName } = meta;
    let helper = this.builtInHelpers[name];

    if (helper) {
      return helper;
    }

    let options = moduleName && { source: `template:${moduleName}` } || {};
    let helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`);

    // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations
    if (helperFactory.class.isHelperInstance) {
      return (vm, args) => SimpleHelperReference.create(helperFactory.class.compute, args.capture());
    } else if (helperFactory.class.isHelperFactory) {
      return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture());
    } else {
      throw new Error(`${name} is not a helper`);
    }
  }

  hasModifier(name) {
    return !!this.builtInModifiers[name];
  }

  lookupModifier(name) {
    let modifier = this.builtInModifiers[name];

    if (modifier) {
      return modifier;
    } else {
      throw new Error(`${name} is not a modifier`);
    }
  }

  toConditionalReference(reference) {
    return ConditionalReference.create(reference);
  }

  iterableFor(ref, key) {
    return createIterable(ref, key);
  }

  scheduleInstallModifier() {
    if (this.isInteractive) {
      super.scheduleInstallModifier(...arguments);
    }
  }

  scheduleUpdateModifier() {
    if (this.isInteractive) {
      super.scheduleUpdateModifier(...arguments);
    }
  }

  didDestroy(destroyable) {
    destroyable.destroy();
  }

  begin() {
    this.inTransaction = true;

    super.begin();
  }

  commit() {
    let destroyedComponents = this.destroyedComponents;
    this.destroyedComponents = [];
    // components queued for destruction must be destroyed before firing
    // `didCreate` to prevent errors when removing and adding a component
    // with the same name (would throw an error when added to view registry)
    for (let i = 0; i < destroyedComponents.length; i++) {
      destroyedComponents[i].destroy();
    }

    super.commit();

    this.inTransaction = false;
  }
}

if (DEBUG) {
  class StyleAttributeManager extends AttributeManager {
    setAttribute(dom, element, value) {
      warn(constructStyleDeprecationMessage(value), (() => {
        if (value === null || value === undefined || isSafeString(value)) {
          return true;
        }
        return false;
      })(), { id: 'ember-htmlbars.style-xss-warning' });
      super.setAttribute(...arguments);
    }

    updateAttribute(dom, element, value) {
      warn(constructStyleDeprecationMessage(value), (() => {
        if (value === null || value === undefined || isSafeString(value)) {
          return true;
        }
        return false;
      })(), { id: 'ember-htmlbars.style-xss-warning' });
      super.updateAttribute(...arguments);
    }
  }

  let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager('style');

  Environment.prototype.attributeFor = function(element, attribute, isTrusting, namespace) {
    if (attribute === 'style' && !isTrusting) {
      return STYLE_ATTRIBUTE_MANANGER;
    }

    return GlimmerEnvironment.prototype.attributeFor.call(this, element, attribute, isTrusting);
  };
}
<|endoftext|>


<commit_before>import createSchema from 'part:@sanity/base/schema-creator'
import blockArray from './block-array'
import moment from 'moment'

// Example of a custom slugify function that
// makes a slug-string and prefixes it with something from the
// schema and then calls the default slugify function.
function slugifyWithPrefix(prefix) {
  return function (type, slug, slugify) {
    let newSlug = slug
    if (slug.substring(0, prefix.length) === `${prefix}`) {
      newSlug = slug.substring(prefix.length, slug.length)
    }
    return slugify(type, `${prefix}-${newSlug}`)
      .substring(0, type.options.maxLength)
  }
}

export default createSchema({
  name: 'example-blog',
  types: [
    ...blockArray,
    {
      name: 'blogpost',
      type: 'object',
      title: 'Blogpost',
      preview: {
        select: {
          title: 'title',
          createdAt: '_createdAt',
          lead: 'lead',
          imageUrl: 'mainImage.asset.url',
          author: 'authorRef.name'
        },
        prepare(value) {
          const timeSince = moment(value.createdAt).fromNow()
          return Object.assign({}, value, {
            subtitle: value.author ? `By ${value.author}, ${timeSince}` : timeSince,
            description: value.lead
          })
        }
      },
      fields: [
        {
          name: 'title',
          title: 'Title',
          type: 'string',
          required: true
        },
        {
          name: 'publishAt',
          title: 'Publish at',
          type: 'date',
          description: 'Blogpost goes live at this date/time',
          options: {
            dateFormat: 'YYYY-MM-DD',
            timeFormat: 'HH:mm',
            timeStep: 60,
            calendarTodayLabel: 'Today',
            inputUtc: false,
            inputDate: true,
            inputTime: true
          }
        },
        {
          name: 'file',
          title: 'Plain file upload',
          type: 'file'
        },
        {
          name: 'mainImage',
          title: 'Main image',
          type: 'image',
          options: {
            hotspot: true
          },
          fields: [
            {
              name: 'caption',
              type: 'string',
              title: 'Caption'
            }
          ]
        },
        {
          name: 'rating',
          title: 'Rating',
          type: 'number',
          options: {
            range: {min: 0, max: 10, step: 0.2}
          },
          required: true
        },
        {
          name: 'selectMultipleStrings',
          title: 'Select multiple strings',
          type: 'array',
          options: {
            direction: 'vertical',
            list: [
              {title: 'Red', value: 'red'},
              {title: 'Green', value: 'green'},
              {title: 'Blue', value: 'blue'},
              {title: 'Black', value: 'black'},
            ]
          },
          of: [{
            type: 'string'
          }]
        },
        {
          name: 'pngImage',
          title: 'PNG image',
          type: 'image',
          options: {
            hotspot: true,
            accept: 'image/png'
          }
        },
        {
          name: 'slug',
          title: 'Slug',
          description: 'The unique identifier for the blogpost in links and urls',
          type: 'slug',
          required: true,
          options: {
            source: 'title',
            maxLength: 64,
            slugifyFn: slugifyWithPrefix('creepy')
          }
        },
        {
          name: 'tags',
          title: 'tags',
          type: 'array',
          options: {
            layout: 'tags'
          },
          of: [
            {type: 'string'}
          ]
        },
        {
          name: 'arrayOfStrings',
          title: 'Array of strings',
          type: 'array',
          of: [
            {type: 'string'}
          ]
        },

        {
          name: 'priority',
          title: 'Priority',
          type: 'number'
        },
        {
          name: 'checked',
          title: 'Checked',
          type: 'boolean'
        },
        {
          name: 'body',
          type: 'array',
          title: 'Blocks',
          of: [
            {
              title: 'Block',
              type: 'block'
            }
          ]
        },
        {
          name: 'imageGallery',
          title: 'Image gallery',
          type: 'array',
          options: {
            layout: 'grid',
            sortable: true
          },
          of: [
            {
              title: 'Image',
              type: 'image',
              preview: {
                select: {
                  imageUrl: 'asset.url',
                  title: 'caption'
                }
              },
              fields: [
                {
                  name: 'caption',
                  type: 'string',
                  title: 'Caption',
                  options: {
                    isHighlighted: true
                  }
                }
              ]
            }
          ]
        },
        {
          name: 'select',
          title: 'Select string',
          type: 'string',
          options: {
            list: [
              {
                title: 'One (1)',
                value: 'one'
              },
              {
                title: 'Two (2)',
                value: 'two'
              },
              {
                title: 'Three (3)',
                value: 'three'
              }
            ]
          }
        },
        {
          name: 'selectObjectOfString',
          title: 'Select string in object',
          description: '',
          type: 'string',
          options: {
            list: ['one', 'two', 'three']
          }
        },
        {
          name: 'radioSelect',
          title: 'Select (layout: radio)',
          type: 'string',
          options: {
            layout: 'radio',
            list: [
              {
                title: 'One (1)',
                value: 'one'
              },
              {
                title: 'Two (2)',
                value: 'two'
              },
              {
                title: 'Three (3)',
                value: 'three'
              }
            ]
          }
        },
        {
          name: 'lead',
          title: 'Lead',
          type: 'text',
          format: 'html',
          required: true
        },
        {
          name: 'email',
          title: 'Email',
          type: 'email'
        },
        {
          name: 'location',
          title: 'Location',
          type: 'geopoint'
        },
        {
          name: 'content',
          title: 'Content tags',
          type: 'array',
          of: [
            {
              title: 'String',
              type: 'string'
            }
          ]
        },
        {
          name: 'firstAuthor',
          title: 'Author',
          type: 'reference',
          to: {type: 'author'},
          required: true
        },
        {
          name: 'coauthors',
          title: 'Co authors',
          type: 'array',
          of: [{
            type: 'reference',
            to: {type: 'author'}
          }],
          required: true
        },
        {
          name: 'extraAuthors',
          title: 'Additional authors',
          description: 'Note: This is an inline array of authors',
          type: 'array',
          options: {
            editModal: 'fold'
          },
          of: [{type: 'author'}],
          required: true
        },
        {
          name: 'superAuthors',
          title: 'Super authors',
          type: 'array',
          options: {
            editModal: 'fullscreen'
          },
          of: [{
            type: 'reference',
            to: {type: 'author'}
          }],
          required: true
        },
      ]
    },
    {
      name: 'author',
      type: 'object',
      title: 'Author',
      fields: [
        {
          name: 'name',
          title: 'Name',
          type: 'string'
        },
        {
          name: 'image',
          title: 'Image',
          type: 'image'
        },
        {
          name: 'awards',
          title: 'Awards',
          type: 'array',
          of: [
            {
              type: 'string'
            }
          ]
        },
        {
          name: 'relatedAuthors',
          title: 'Related authors',
          type: 'array',
          of: [
            {
              type: 'reference',
              to: {type: 'author'}
            }
          ]
        }
      ]
    }
  ]
})
<commit_msg>[example-studio] Example of edit modal settings on array<commit_after>import createSchema from 'part:@sanity/base/schema-creator'
import blockArray from './block-array'
import moment from 'moment'

// Example of a custom slugify function that
// makes a slug-string and prefixes it with something from the
// schema and then calls the default slugify function.
function slugifyWithPrefix(prefix) {
  return function (type, slug, slugify) {
    let newSlug = slug
    if (slug.substring(0, prefix.length) === `${prefix}`) {
      newSlug = slug.substring(prefix.length, slug.length)
    }
    return slugify(type, `${prefix}-${newSlug}`)
      .substring(0, type.options.maxLength)
  }
}

export default createSchema({
  name: 'example-blog',
  types: [
    ...blockArray,
    {
      name: 'blogpost',
      type: 'object',
      title: 'Blogpost',
      preview: {
        select: {
          title: 'title',
          createdAt: '_createdAt',
          lead: 'lead',
          imageUrl: 'mainImage.asset.url',
          author: 'authorRef.name'
        },
        prepare(value) {
          const timeSince = moment(value.createdAt).fromNow()
          return Object.assign({}, value, {
            subtitle: value.author ? `By ${value.author}, ${timeSince}` : timeSince,
            description: value.lead
          })
        }
      },
      fields: [
        {
          name: 'title',
          title: 'Title',
          type: 'string',
          required: true
        },
        {
          name: 'publishAt',
          title: 'Publish at',
          type: 'date',
          description: 'Blogpost goes live at this date/time',
          options: {
            dateFormat: 'YYYY-MM-DD',
            timeFormat: 'HH:mm',
            timeStep: 60,
            calendarTodayLabel: 'Today',
            inputUtc: false,
            inputDate: true,
            inputTime: true
          }
        },
        {
          name: 'file',
          title: 'Plain file upload',
          type: 'file'
        },
        {
          name: 'mainImage',
          title: 'Main image',
          type: 'image',
          options: {
            hotspot: true
          },
          fields: [
            {
              name: 'caption',
              type: 'string',
              title: 'Caption'
            }
          ]
        },
        {
          name: 'rating',
          title: 'Rating',
          type: 'number',
          options: {
            range: {min: 0, max: 10, step: 0.2}
          },
          required: true
        },
        {
          name: 'selectMultipleStrings',
          title: 'Select multiple strings',
          type: 'array',
          options: {
            direction: 'vertical',
            list: [
              {title: 'Red', value: 'red'},
              {title: 'Green', value: 'green'},
              {title: 'Blue', value: 'blue'},
              {title: 'Black', value: 'black'},
            ]
          },
          of: [{
            type: 'string'
          }]
        },
        {
          name: 'pngImage',
          title: 'PNG image',
          type: 'image',
          options: {
            hotspot: true,
            accept: 'image/png'
          }
        },
        {
          name: 'slug',
          title: 'Slug',
          description: 'The unique identifier for the blogpost in links and urls',
          type: 'slug',
          required: true,
          options: {
            source: 'title',
            maxLength: 64,
            slugifyFn: slugifyWithPrefix('creepy')
          }
        },
        {
          name: 'tags',
          title: 'tags',
          type: 'array',
          options: {
            layout: 'tags'
          },
          of: [
            {type: 'string'}
          ]
        },
        {
          name: 'arrayOfStrings',
          title: 'Array of strings',
          type: 'array',
          of: [
            {type: 'string'}
          ]
        },

        {
          name: 'priority',
          title: 'Priority',
          type: 'number'
        },
        {
          name: 'checked',
          title: 'Checked',
          type: 'boolean'
        },
        {
          name: 'body',
          type: 'array',
          title: 'Blocks',
          of: [
            {
              title: 'Block',
              type: 'block'
            }
          ]
        },
        {
          name: 'imageGallery',
          title: 'Image gallery',
          type: 'array',
          options: {
            layout: 'grid',
            sortable: true
          },
          of: [
            {
              title: 'Image',
              type: 'image',
              preview: {
                select: {
                  imageUrl: 'asset.url',
                  title: 'caption'
                }
              },
              fields: [
                {
                  name: 'caption',
                  type: 'string',
                  title: 'Caption',
                  options: {
                    isHighlighted: true
                  }
                }
              ]
            }
          ]
        },
        {
          name: 'select',
          title: 'Select string',
          type: 'string',
          options: {
            list: [
              {
                title: 'One (1)',
                value: 'one'
              },
              {
                title: 'Two (2)',
                value: 'two'
              },
              {
                title: 'Three (3)',
                value: 'three'
              }
            ]
          }
        },
        {
          name: 'selectObjectOfString',
          title: 'Select string in object',
          description: '',
          type: 'string',
          options: {
            list: ['one', 'two', 'three']
          }
        },
        {
          name: 'radioSelect',
          title: 'Select (layout: radio)',
          type: 'string',
          options: {
            layout: 'radio',
            list: [
              {
                title: 'One (1)',
                value: 'one'
              },
              {
                title: 'Two (2)',
                value: 'two'
              },
              {
                title: 'Three (3)',
                value: 'three'
              }
            ]
          }
        },
        {
          name: 'lead',
          title: 'Lead',
          type: 'text',
          format: 'html',
          required: true
        },
        {
          name: 'email',
          title: 'Email',
          type: 'email'
        },
        {
          name: 'location',
          title: 'Location',
          type: 'geopoint'
        },
        {
          name: 'content',
          title: 'Content tags',
          type: 'array',
          of: [
            {
              title: 'String',
              type: 'string'
            }
          ]
        },
        {
          name: 'firstAuthor',
          title: 'Author',
          type: 'reference',
          to: {type: 'author'},
          required: true
        },
        {
          name: 'coauthors',
          title: 'Co authors',
          type: 'array',
          of: [{
            type: 'reference',
            title: 'Reference to co-author',
            to: {
              type: 'author'
            }
          }],
          required: true
        },
        {
          name: 'extraAuthors',
          title: 'Additional authors',
          description: 'Note: This is an inline array of authors',
          type: 'array',
          options: {
            editModal: 'fold'
          },
          of: [
            {
              title: 'Additional author reference',
              type: 'author'
            }
          ],
          required: true
        },
        {
          name: 'extraSuperAuthors',
          title: 'Additional super authors',
          description: 'Note: This is an inline array of authors',
          type: 'array',
          options: {
            editModal: 'fullscreen'
          },
          of: [
            {
              title: 'Additional super author reference',
              type: 'author'
            }
          ],
          required: true
        },
        {
          name: 'superAuthors',
          title: 'Super authors',
          type: 'array',
          options: {
            editModal: 'fullscreen'
          },
          of: [{
            title: 'Reference to super author',
            type: 'reference',
            to: {
              type: 'author'
            }
          }],
          required: true
        },
      ]
    },
    {
      name: 'author',
      type: 'object',
      title: 'Author',
      fields: [
        {
          name: 'name',
          title: 'Name',
          type: 'string'
        },
        {
          name: 'image',
          title: 'Image',
          type: 'image'
        },
        {
          name: 'awards',
          title: 'Awards',
          type: 'array',
          of: [
            {
              type: 'string'
            }
          ]
        },
        {
          name: 'relatedAuthors',
          title: 'Related authors',
          type: 'array',
          of: [
            {
              type: 'reference',
              to: {type: 'author'}
            }
          ]
        }
      ]
    }
  ]
})
<|endoftext|>