<commit_before>import Signal from 'mini-signals';
import ECS from '@fae/ecs';
import GLContext from '../gl/GLContext';
import RenderTarget from './RenderTarget';
import RenderState from './RenderState';
import ObjectRenderer from './ObjectRenderer';
import { uid, removeElements } from '../util';

const defaultSystems = [];

/**
 * The Renderer is just a container for the WebGLRenderingContext, the render state,
 * and the current object renderer that is doing the rendering.
 *
 * @class
 */
export default class Renderer extends ECS
{
    /**
     * Creates a new renderer.
     *
     * @param {!HTMLCanvasElement|WebGLRenderingContext} context - The canvas to create a context from,
     *  or the context to use to draw.
     * @param {object} [options] - Options for the renderer
     * @param {boolean} [options.clearBeforeRender=true] - Should we clear before each render?
     * @param {boolean} [options.preserveDrawingBuffer=false] - Enables drawing buffer preservation,
     *  enable this if you need to call toDataUrl on the webgl context.
     */
    constructor(context, options = {})
    {
        super();

        /**
         * The main rendering context used for drawing.
         *
         * @member {WebGLRenderingContext}
         */
        this.gl = (context.nodeName ? GLContext.create(context) : context);

        /**
         * A unique ID for this renderer, useful for keying maps by renderer
         *
         * @member {number}
         */
        this.uid = uid();

        /**
         * Should we clear before each frame?
         *
         * @member {boolean}
         */
        this.clearBeforeRender = typeof options.clearBeforeRender !== 'undefined' ? options.clearBeforeRender : true;

        /**
         * Should we preserve the drawing buffer each frame?
         *
         * @member {boolean}
         */
        this.preserveDrawingBuffer = options.preserveDrawingBuffer || false;

        /**
         * Dispatched when context has been lost.
         *
         * @member {Signal}
         */
        this.onContextLost = new Signal();

        /**
         * Dispatched when context has been restored, but before the renderer
         * has initialized for the new context.
         *
         * If you are wanting to know when you should reinitialize your stuff
         * after a restore use {@link Renderer#onContextChange}.
         *
         * @member {Signal}
         */
        this.onContextRestored = new Signal();

        /**
         * Dispatched when context has changed. This happens when the renderer
         * initializes and then again if the context is restored, after we initialize
         * the context again.
         *
         * @member {Signal}
         */
        this.onContextChange = new Signal();

        /**
         * Dispatched each frame before rendering the object.
         *
         * @member {Signal}
         */
        this.onBeforeRender = new Signal();

        /**
         * Dispatched each frame after rendering the object.
         *
         * @member {Signal}
         */
        this.onAfterRender = new Signal();

        /**
         * An empty renderer.
         *
         * @member {ObjectRenderer}
         */
        this.emptyRenderer = new ObjectRenderer(this);

        /**
         * The currently activer object renderer.
         *
         * @member {ObjectRenderer}
         */
        this.activeObjectRenderer = this.emptyRenderer;

        /**
         * The current state of the renderer.
         *
         * @member {WebGLState}
         */
        this.state = new RenderState(this);

        /**
         * The root render target, that represents the screen.
         *
         * @member {RenderTarget}
         */
        this.screen = null;

        this._boundOnContextLost = this._onContextLost.bind(this);
        this._boundOnContextRestored = this._onContextRestored.bind(this);

        this.gl.canvas.addEventListener('webglcontextlost', this._boundOnContextLost);
        this.gl.canvas.addEventListener('webglcontextrestored', this._boundOnContextRestored);

        // initialize for a new context
        this._initContext();

        // create and add the default systems
        for (let i = 0; i < defaultSystems.length; ++i)
        {
            const system = new defaultSystems[i](this);

            this.addSystem(system);
        }
    }

    /**
     * Adds a system that will be created automatically when a renderer instance is created.
     *
     * Note: Calling this function registers a system to be automatically added in renderers
     * that you create *after* calling this. If you call this after creating a renderer, the
     * already created renderer will *not* contain this system automatically.
     *
     * @param {System} System - The system class to add (**not** an instance, but the class
     * itself)
     */
    static addDefaultSystem(System)
    {
        defaultSystems.push(System);
    }

    /**
     * Removes a system so that it will no longer be created automatically when a renderer
     * instance is created.
     *
     * Note: Calling this function unregisters a system to be automatically added in renderers
     * that you create *after* calling this. If you call this after creating a renderer, the
     * already created renderer may contain this system automatically.
     *
     * @param {System} System - The system class to add (**not** an instance, but the class
     * itself)
     */
    static removeDefaultSystem(System)
    {
        const idx = defaultSystems.indexOf(System);

        if (idx !== -1)
        {
            removeElements(defaultSystems, idx, 1);
        }
    }

    /**
     * Add a system to the renderer.
     *
     * @param {System} system - The system to add.
     * @param {boolean} [skipSort=false] - If true, will not sort the systems automatically.
     *  Setting this to true requires you call {@link Renderer#sortSystems} manually. This
     *  can be useful if you are adding a large batch of systems in a single frame and want
     *  to delay the sorting until after they are all added.
     */
    addSystem(system, skipSort)
    {
        super.addSystem(system);

        if (!skipSort) this.sortSystems();
    }

    /**
     * Add an entity to the renderer.
     *
     * Note: Since adding an entity causes the entity list to be sorted (to ensure renderPriority
     * and grouping is correct), this method can be expensive when you have a large list. As such
     * it is recommended not to Add/Remove entities many times per frame.
     *
     * @param {Entity} entity - The entity to add.
     * @param {boolean} [skipSort=false] - If true, will not sort the entities automatically.
     *  Setting this to true requires you call {@link Renderer#sortEntities} manually. This
     *  can be useful if you are adding a large batch of entities in a single frame and want
     *  to delay the sorting until after they are all added.
     */
    addEntity(entity, skipSort)
    {
        super.addEntity(entity);

        if (!skipSort) this.sortEntities();
    }

    /**
     * Sorts the systems by priority. If you change a system's priority after adding
     * it to the renderer then you will need to call this for it to be properly sorted.
     *
     */
    sortSystems()
    {
        this.systems.sort(compareSystemsPriority);
    }

    /**
     * Sorts the entities by render priority and their group hint. If you change an
     * entity's priority after adding it to the renderer then you will need to call
     * this for it to take effect.
     *
     */
    sortEntities()
    {
        this.entities.sort(compareRenderPriority);
    }

    /**
     * Renders a drawable object to the render target.
     *
     * @param {RenderTarget} target - The target to render to, defaults to the screen.
     * @param {boolean} clear - Should we clear the screen before rendering?
     * @param {Matrix2d} transform - An optional matrix transform to apply for this render.
     */
    render(target = this.screen, clear = this.clearBeforeRender, transform = null)
    {
        // if no context, or context is lost, just bail.
        if (!this.gl || this.gl.isContextLost()) return;

        // tell everyone we are updating
        this.onBeforeRender.dispatch();

        // set the target
        target.transform = transform;
        this.state.setRenderTarget(target);

        // start the active object renderer
        this.activeObjectRenderer.start();

        // clear if we should
        if (clear) this.state.target.clear();

        // process all the entites and their systems
        this.update();

        // stop the active object renderer
        this.activeObjectRenderer.stop();

        // tell everyone we updated
        this.onAfterRender.dispatch();
    }

    /**
     * Sets the passed ObjectRenderer instance as the active object renderer.
     *
     * @param {ObjectRenderer} objectRenderer - The object renderer to use.
     */
    setActiveObjectRenderer(objectRenderer)
    {
        if (this.activeObjectRenderer !== objectRenderer)
        {
            this.activeObjectRenderer.stop();
            this.activeObjectRenderer = objectRenderer;
            this.activeObjectRenderer.start();
        }
    }

    /**
     * Destroys this renderer and the related objects.
     *
     */
    destroy()
    {
        // unbind canvas events
        this.gl.canvas.removeEventListener('webglcontextlost', this._boundOnContextLost);
        this.gl.canvas.removeEventListener('webglcontextrestored', this._boundOnContextRestored);

        this._boundOnContextLost = null;
        this._boundOnContextRestored = null;

        // destroy state
        this.state.destroy();

        // detach and lose signals
        this.onContextLost.detachAll();
        this.onContextLost = null;

        this.onContextRestored.detachAll();
        this.onContextRestored = null;

        this.onContextChange.detachAll();
        this.onContextChange = null;

        this.onBeforeRender.detachAll();
        this.onBeforeRender = null;

        this.onAfterRender.detachAll();
        this.onAfterRender = null;

        this.activeObjectRenderer = null;

        // finally lose context
        if (this.gl.getExtension('WEBGL_lose_context'))
        {
            this.gl.getExtension('WEBGL_lose_context').loseContext();
        }

        this.gl = null;
    }

    /**
     * Initializes the WebGL context.
     *
     * @private
     */
    _initContext()
    {
        const gl = this.gl;

        this.state.reset();

        if (this.screen)
        {
            this.screen.destroy();
        }

        this.screen = new RenderTarget(gl, gl.canvas.width, gl.canvas.height, RenderTarget.defaultScaleMode, true);

        this.state.setRenderTarget(this.screen);

        // this.resize(gl.canvas.width, gl.canvas.height);

        this.onContextChange.dispatch(gl);
    }

    /**
     * Called when the underlying context is lost.
     *
     * @private
     * @param {WebGLContextEvent} event - The DOM event about the context being lost.
     */
    _onContextLost(event)
    {
        event.preventDefault();
        this.onContextLost.dispatch();
    }

    /**
     * Called when the underlying context is restored.
     *
     * @private
     */
    _onContextRestored()
    {
        this._initContext();
        this.onContextRestored.dispatch();
    }
}

// lower is placed first
function compareSystemsPriority(a, b)
{
    return a.priority - b.priority;
}

// lower is placed first, and within renderPriority they are grouped
// by the objectRendererHint
function compareRenderPriority(a, b)
{
    if (a.renderPriority === b.renderPriority)
    {
        return a.renderGroupHint === b.renderGroupHint ? 0 : 1;
    }

    return a.renderPriority - b.renderPriority;
}
<commit_msg>fix typo in comment<commit_after>import Signal from 'mini-signals';
import ECS from '@fae/ecs';
import GLContext from '../gl/GLContext';
import RenderTarget from './RenderTarget';
import RenderState from './RenderState';
import ObjectRenderer from './ObjectRenderer';
import { uid, removeElements } from '../util';

const defaultSystems = [];

/**
 * The Renderer is just a container for the WebGLRenderingContext, the render state,
 * and the current object renderer that is doing the rendering.
 *
 * @class
 */
export default class Renderer extends ECS
{
    /**
     * Creates a new renderer.
     *
     * @param {!HTMLCanvasElement|WebGLRenderingContext} context - The canvas to create a context from,
     *  or the context to use to draw.
     * @param {object} [options] - Options for the renderer
     * @param {boolean} [options.clearBeforeRender=true] - Should we clear before each render?
     * @param {boolean} [options.preserveDrawingBuffer=false] - Enables drawing buffer preservation,
     *  enable this if you need to call toDataUrl on the webgl context.
     */
    constructor(context, options = {})
    {
        super();

        /**
         * The main rendering context used for drawing.
         *
         * @member {WebGLRenderingContext}
         */
        this.gl = (context.nodeName ? GLContext.create(context) : context);

        /**
         * A unique ID for this renderer, useful for keying maps by renderer
         *
         * @member {number}
         */
        this.uid = uid();

        /**
         * Should we clear before each frame?
         *
         * @member {boolean}
         */
        this.clearBeforeRender = typeof options.clearBeforeRender !== 'undefined' ? options.clearBeforeRender : true;

        /**
         * Should we preserve the drawing buffer each frame?
         *
         * @member {boolean}
         */
        this.preserveDrawingBuffer = options.preserveDrawingBuffer || false;

        /**
         * Dispatched when context has been lost.
         *
         * @member {Signal}
         */
        this.onContextLost = new Signal();

        /**
         * Dispatched when context has been restored, but before the renderer
         * has initialized for the new context.
         *
         * If you are wanting to know when you should reinitialize your stuff
         * after a restore use {@link Renderer#onContextChange}.
         *
         * @member {Signal}
         */
        this.onContextRestored = new Signal();

        /**
         * Dispatched when context has changed. This happens when the renderer
         * initializes and then again if the context is restored, after we initialize
         * the context again.
         *
         * @member {Signal}
         */
        this.onContextChange = new Signal();

        /**
         * Dispatched each frame before rendering the object.
         *
         * @member {Signal}
         */
        this.onBeforeRender = new Signal();

        /**
         * Dispatched each frame after rendering the object.
         *
         * @member {Signal}
         */
        this.onAfterRender = new Signal();

        /**
         * An empty renderer.
         *
         * @member {ObjectRenderer}
         */
        this.emptyRenderer = new ObjectRenderer(this);

        /**
         * The currently activer object renderer.
         *
         * @member {ObjectRenderer}
         */
        this.activeObjectRenderer = this.emptyRenderer;

        /**
         * The current state of the renderer.
         *
         * @member {WebGLState}
         */
        this.state = new RenderState(this);

        /**
         * The root render target, that represents the screen.
         *
         * @member {RenderTarget}
         */
        this.screen = null;

        this._boundOnContextLost = this._onContextLost.bind(this);
        this._boundOnContextRestored = this._onContextRestored.bind(this);

        this.gl.canvas.addEventListener('webglcontextlost', this._boundOnContextLost);
        this.gl.canvas.addEventListener('webglcontextrestored', this._boundOnContextRestored);

        // initialize for a new context
        this._initContext();

        // create and add the default systems
        for (let i = 0; i < defaultSystems.length; ++i)
        {
            const system = new defaultSystems[i](this);

            this.addSystem(system);
        }
    }

    /**
     * Adds a system that will be created automatically when a renderer instance is created.
     *
     * Note: Calling this function registers a system to be automatically added in renderers
     * that you create *after* calling this. If you call this after creating a renderer, the
     * already created renderer will *not* contain this system automatically.
     *
     * @param {System} System - The system class to add (**not** an instance, but the class
     * itself)
     */
    static addDefaultSystem(System)
    {
        defaultSystems.push(System);
    }

    /**
     * Removes a system so that it will no longer be created automatically when a renderer
     * instance is created.
     *
     * Note: Calling this function unregisters a system to be automatically added in renderers
     * that you create *after* calling this. If you call this after creating a renderer, the
     * already created renderer may contain this system automatically.
     *
     * @param {System} System - The system class to add (**not** an instance, but the class
     * itself)
     */
    static removeDefaultSystem(System)
    {
        const idx = defaultSystems.indexOf(System);

        if (idx !== -1)
        {
            removeElements(defaultSystems, idx, 1);
        }
    }

    /**
     * Add a system to the renderer.
     *
     * @param {System} system - The system to add.
     * @param {boolean} [skipSort=false] - If true, will not sort the systems automatically.
     *  Setting this to true requires you call {@link Renderer#sortSystems} manually. This
     *  can be useful if you are adding a large batch of systems in a single frame and want
     *  to delay the sorting until after they are all added.
     */
    addSystem(system, skipSort)
    {
        super.addSystem(system);

        if (!skipSort) this.sortSystems();
    }

    /**
     * Add an entity to the renderer.
     *
     * Note: Since adding an entity causes the entity list to be sorted (to ensure renderPriority
     * and grouping is correct), this method can be expensive when you have a large list. As such
     * it is recommended not to Add/Remove entities many times per frame.
     *
     * @param {Entity} entity - The entity to add.
     * @param {boolean} [skipSort=false] - If true, will not sort the entities automatically.
     *  Setting this to true requires you call {@link Renderer#sortEntities} manually. This
     *  can be useful if you are adding a large batch of entities in a single frame and want
     *  to delay the sorting until after they are all added.
     */
    addEntity(entity, skipSort)
    {
        super.addEntity(entity);

        if (!skipSort) this.sortEntities();
    }

    /**
     * Sorts the systems by priority. If you change a system's priority after adding
     * it to the renderer then you will need to call this for it to be properly sorted.
     *
     */
    sortSystems()
    {
        this.systems.sort(compareSystemsPriority);
    }

    /**
     * Sorts the entities by render priority and their group hint. If you change an
     * entity's priority after adding it to the renderer then you will need to call
     * this for it to take effect.
     *
     */
    sortEntities()
    {
        this.entities.sort(compareRenderPriority);
    }

    /**
     * Renders a drawable object to the render target.
     *
     * @param {RenderTarget} target - The target to render to, defaults to the screen.
     * @param {boolean} clear - Should we clear the screen before rendering?
     * @param {Matrix2d} transform - An optional matrix transform to apply for this render.
     */
    render(target = this.screen, clear = this.clearBeforeRender, transform = null)
    {
        // if no context, or context is lost, just bail.
        if (!this.gl || this.gl.isContextLost()) return;

        // tell everyone we are updating
        this.onBeforeRender.dispatch();

        // set the target
        target.transform = transform;
        this.state.setRenderTarget(target);

        // start the active object renderer
        this.activeObjectRenderer.start();

        // clear if we should
        if (clear) this.state.target.clear();

        // process all the entites and their systems
        this.update();

        // stop the active object renderer
        this.activeObjectRenderer.stop();

        // tell everyone we updated
        this.onAfterRender.dispatch();
    }

    /**
     * Sets the passed ObjectRenderer instance as the active object renderer.
     *
     * @param {ObjectRenderer} objectRenderer - The object renderer to use.
     */
    setActiveObjectRenderer(objectRenderer)
    {
        if (this.activeObjectRenderer !== objectRenderer)
        {
            this.activeObjectRenderer.stop();
            this.activeObjectRenderer = objectRenderer;
            this.activeObjectRenderer.start();
        }
    }

    /**
     * Destroys this renderer and the related objects.
     *
     */
    destroy()
    {
        // unbind canvas events
        this.gl.canvas.removeEventListener('webglcontextlost', this._boundOnContextLost);
        this.gl.canvas.removeEventListener('webglcontextrestored', this._boundOnContextRestored);

        this._boundOnContextLost = null;
        this._boundOnContextRestored = null;

        // destroy state
        this.state.destroy();

        // detach and lose signals
        this.onContextLost.detachAll();
        this.onContextLost = null;

        this.onContextRestored.detachAll();
        this.onContextRestored = null;

        this.onContextChange.detachAll();
        this.onContextChange = null;

        this.onBeforeRender.detachAll();
        this.onBeforeRender = null;

        this.onAfterRender.detachAll();
        this.onAfterRender = null;

        this.activeObjectRenderer = null;

        // finally lose context
        if (this.gl.getExtension('WEBGL_lose_context'))
        {
            this.gl.getExtension('WEBGL_lose_context').loseContext();
        }

        this.gl = null;
    }

    /**
     * Initializes the WebGL context.
     *
     * @private
     */
    _initContext()
    {
        const gl = this.gl;

        this.state.reset();

        if (this.screen)
        {
            this.screen.destroy();
        }

        this.screen = new RenderTarget(gl, gl.canvas.width, gl.canvas.height, RenderTarget.defaultScaleMode, true);

        this.state.setRenderTarget(this.screen);

        // this.resize(gl.canvas.width, gl.canvas.height);

        this.onContextChange.dispatch(gl);
    }

    /**
     * Called when the underlying context is lost.
     *
     * @private
     * @param {WebGLContextEvent} event - The DOM event about the context being lost.
     */
    _onContextLost(event)
    {
        event.preventDefault();
        this.onContextLost.dispatch();
    }

    /**
     * Called when the underlying context is restored.
     *
     * @private
     */
    _onContextRestored()
    {
        this._initContext();
        this.onContextRestored.dispatch();
    }
}

// lower is placed first
function compareSystemsPriority(a, b)
{
    return a.priority - b.priority;
}

// lower is placed first, and within renderPriority they are grouped
// by the renderGroupHint
function compareRenderPriority(a, b)
{
    if (a.renderPriority === b.renderPriority)
    {
        return a.renderGroupHint === b.renderGroupHint ? 0 : 1;
    }

    return a.renderPriority - b.renderPriority;
}
<|endoftext|>


<commit_before>import React from "react";
import { FormattedMessage, defineMessages, injectIntl, intlShape } from "react-intl";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import {
  Button,
  DataListItem,
  DataListItemRow,
  DataListCell,
  DataListToggle,
  DataListContent,
  DataListItemCells
} from "@patternfly/react-core";
import { BuilderImageIcon } from "@patternfly/react-icons";
import { deletingCompose, cancellingCompose } from "../../core/actions/composes";
import {
  setModalStopBuildVisible,
  setModalStopBuildState,
  setModalDeleteImageVisible,
  setModalDeleteImageState
} from "../../core/actions/modals";
import Logs from "../Logs/Logs";
import * as composer from "../../core/composer";
import ImagesDataList from "./ImagesDataList";
import ListItemUploads from "./ListItemUploads";

const messages = defineMessages({
  imageType: {
    defaultMessage: "Type",
    description: "A label for the type of image file was created"
  },
  imageCreated: {
    defaultMessage: "Created",
    description: "A label for the date that an image file was created"
  },
  imageSize: {
    defaultMessage: "Size",
    description: "A label for the size of an image file"
  },
  imageUploads: {
    defaultMessage: "Image uploads",
    description: "A label for the section that lists the upload actions initiated by the user"
  },
  imageActions: {
    defaultMessage: "Actions",
    description: "A label for the menu that displays the actions available"
  },
  imageLogs: {
    defaultMessage: "Logs",
    description: "Log content that gets generated as part of the image creation process"
  },
  imageStatusWaiting: {
    defaultMessage: "Image build pending",
    description: "Image build status when process is waiting"
  },
  imageStatusRunning: {
    defaultMessage: "Image build in progress",
    description: "Image build status when process is in progress"
  },
  imageStatusFinished: {
    defaultMessage: "Image build complete",
    description: "Image build status when process is finished"
  },
  imageStatusFailed: {
    defaultMessage: "Image build failed",
    description: "Image build status when process failed"
  },
  imageStatusStopping: {
    defaultMessage: "Stopping",
    description: "Image build status when user selected to end the process"
  }
});

class ListItemImages extends React.Component {
  constructor() {
    super();
    this.state = { logsExpanded: false, uploadsExpanded: false };
    this.handleDelete = this.handleDelete.bind(this);
    this.handleCancel = this.handleCancel.bind(this);
    this.handleShowModalStop = this.handleShowModalStop.bind(this);
    this.handleShowModalDeleteImage = this.handleShowModalDeleteImage.bind(this);
    this.handleLogsShow = this.handleLogsShow.bind(this);
    this.handleUploadsShow = this.handleUploadsShow.bind(this);
  }

  // maps to Remove button for FAILED
  handleDelete(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.deletingCompose(this.props.listItem.id);
  }

  // maps to Stop button for WAITING
  handleCancel(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.cancellingCompose(this.props.listItem.id);
  }

  // maps to Stop button for RUNNING
  handleShowModalStop(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.setModalStopBuildState(this.props.listItem.id, this.props.blueprint);
    this.props.setModalStopBuildVisible(true);
  }

  // maps to Delete button for FINISHED
  handleShowModalDeleteImage(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.setModalDeleteImageState(this.props.listItem.id, this.props.blueprint);
    this.props.setModalDeleteImageVisible(true);
  }

  handleLogsShow() {
    this.setState({ uploadsExpanded: false });
    this.setState(prevState => ({ logsExpanded: !prevState.logsExpanded, fetchingLogs: !prevState.logsExpanded }));
    composer.getComposeLog(this.props.listItem.id).then(
      logs => {
        this.setState({ logsContent: logs, fetchingLogs: false });
      },
      () => {
        this.setState({
          logsContent: <FormattedMessage defaultMessage="No log available" />,
          fetchingLogs: false
        });
      }
    );
  }
  // consider removing
  handleUploadsShow() {
    this.setState({ logsExpanded: false });
    this.setState(prevState => ({ uploadsExpanded: !prevState.uploadsExpanded }));
  }

  render() {
    const { listItem } = this.props;
    const { formatMessage } = this.props.intl;
    const timestamp = new Date(listItem.job_created * 1000);
    const formattedTime = timestamp.toDateString();
    let actions;
    switch (listItem.queue_status) {
      case "FINISHED":
        actions = (
          <>

                <FormattedMessage defaultMessage="Download" />

               this.handleShowModalDeleteImage(e)} data-delete>
                <FormattedMessage defaultMessage="Delete" />

          </>
        );
        break;
      case "RUNNING":
        actions = (
          <>

               this.handleShowModalStop(e)}>
                <FormattedMessage defaultMessage="Stop" />

          </>
        );
        break;
      case "WAITING":
        actions = (
          <>

               this.handleCancel(e)}>
                <FormattedMessage defaultMessage="Stop" />

          </>
        );
        break;
      case "FAILED":
        actions = (
          <>

               this.handleDelete(e)}>
                <FormattedMessage defaultMessage="Remove" />

          </>
        );
        break;
      default:
        actions = undefined;
        break;
    }
    const noLogs = listItem.queue_status === "WAITING" || listItem.queue_status === "STOPPING";
    const logsButton = (
      <div
        aria-hidden={noLogs}
        className={`pf-c-data-list__item-action ${noLogs ? "cc-u-not-visible" : ""}`}
      >
        <Button
          variant={`${this.state.logsExpanded ? "primary" : "secondary"}`}
          aria-expanded={this.state.logsExpanded}
          aria-controls={`${listItem.id}-logs`}
          onClick={this.handleLogsShow}
        >
          {formatMessage(messages.imageLogs)}
        </Button>

    );
    let uploadsToggle;
    if (listItem.uploads !== undefined) {
      uploadsToggle = (
        <DataListToggle
            onClick={this.handleUploadsShow}
            isExpanded={this.state.uploadsExpanded}
            id="uploads-toggle"
            aria-label={`${formatMessage(messages.imageUploads)} ${this.props.blueprint}-${listItem.version}-${listItem.compose_type}`}
            aria-controls={`${listItem.id}-uploads`}
            // ^ need to fix this attribute value
            aria-hidden={!listItem.uploads.length > 0}
            className={`${!listItem.uploads.length > 0 ? "cc-u-not-visible" : ""}`}
          />
      );
    }
    const composeStatus = () => {
      switch (listItem.queue_status) {
        case "WAITING":
          return (

              {formatMessage(messages.imageStatusWaiting)}

          );
        case "RUNNING":
          return (

              {formatMessage(messages.imageStatusRunning)}

          );
        case "FINISHED":
          return (

              {formatMessage(messages.imageStatusFinished)}

          );
        case "FAILED":
          return (

              {formatMessage(messages.imageStatusFailed)}

          );
        case "STOPPING":
          return (

                {formatMessage(messages.imageStatusStopping)}

          );
        default:
          return <></>;
      }
    };
    let logsSection;
    if (this.state.logsExpanded) {
      logsSection = <Logs logContent={this.state.logsContent} fetchingLog={this.state.fetchingLogs} />;
    }
    let uploadsSection;
    if (this.state.uploadsExpanded) {
      uploadsSection = (
        <ImagesDataList ariaLabel={formatMessage(messages.imageUploads)}>
          {listItem.uploads.map(upload => (
            <ListItemUploads upload={upload} key={upload.uuid} />
          ))}
        </ImagesDataList>
      );
    }
    const size = Math.round(listItem.image_size / 10000000) / 100;

    return (
      <DataListItem
        aria-labelledby={`${listItem.id}-compose-name`}
        isExpanded={this.state.uploadsExpanded}
        data-image={`${this.props.blueprint}-${listItem.version}-${listItem.compose_type}`}
      >
        <DataListItemRow className={`${this.state.logsExpanded ? "cc-m-sticky" : ""}`}>
          {uploadsToggle}

            <BuilderImageIcon />

          <DataListItemCells
            className="cc-m-stacked cc-m-split-on-lg"
            dataListCells={[
              <DataListCell key="primary" className="pf-l-flex pf-m-column pf-m-space-items-xs">

                  <strong id={`${listItem.id}-compose-name`} data-image-name>
                    {this.props.blueprint}-{listItem.version}-{listItem.compose_type}

                  {formatMessage(messages.imageType)}
                  {listItem.compose_type}

                  {formatMessage(messages.imageCreated)} {formattedTime}

                {listItem.queue_status === "FINISHED" && (

                  {formatMessage(messages.imageSize)} {size} GB

                )}
              </DataListCell>,
              <DataListCell key="status">{composeStatus()}</DataListCell>
            ]}
          />
          <div
            className={`pf-c-data-list__item-action ${actions === undefined ? "cc-u-not-visible" : ""}`}
            aria-hidden={actions === undefined}
          >

              <button
                aria-label={formatMessage(messages.imageActions)}
                className="btn btn-link dropdown-toggle"
                type="button"
                id={`${listItem.id}-actions`}
                data-toggle="dropdown"
                aria-haspopup="true"
                aria-expanded="false"
              >

              </button>
              <ul className="dropdown-menu dropdown-menu-right" aria-labelledby={`${listItem.id}-actions`}>
                {actions}

          {logsButton}
        </DataListItemRow>
        <DataListContent aria-label={formatMessage(messages.imageUploads)} id={`${listItem.id}-uploads`} isHidden={!this.state.uploadsExpanded} noPadding>
          {uploadsSection}
        </DataListContent>
        <DataListContent
          aria-label={formatMessage(messages.imageLogs)}
          id={`${listItem.id}-logs`}
          isHidden={!this.state.logsExpanded}
          noPadding
        >
          {logsSection}
        </DataListContent>
      </DataListItem>
    );
  }
}

ListItemImages.propTypes = {
  listItem: PropTypes.shape({
    blueprint: PropTypes.string,
    compose_type: PropTypes.string,
    id: PropTypes.string,
    image_size: PropTypes.number,
    job_created: PropTypes.number,
    job_finished: PropTypes.number,
    job_started: PropTypes.number,
    queue_status: PropTypes.string,
    version: PropTypes.string,
    uploads: PropTypes.arrayOf(PropTypes.object)
  }),
  blueprint: PropTypes.string,
  deletingCompose: PropTypes.func,
  cancellingCompose: PropTypes.func,
  setModalStopBuildState: PropTypes.func,
  setModalStopBuildVisible: PropTypes.func,
  setModalDeleteImageState: PropTypes.func,
  setModalDeleteImageVisible: PropTypes.func,
  downloadUrl: PropTypes.string,
  intl: intlShape.isRequired
};

ListItemImages.defaultProps = {
  listItem: {},
  blueprint: "",
  deletingCompose: function() {},
  cancellingCompose: function() {},
  setModalStopBuildState: function() {},
  setModalStopBuildVisible: function() {},
  setModalDeleteImageState: function() {},
  setModalDeleteImageVisible: function() {},
  downloadUrl: ""
};

const mapDispatchToProps = dispatch => ({
  deletingCompose: compose => {
    dispatch(deletingCompose(compose));
  },
  cancellingCompose: compose => {
    dispatch(cancellingCompose(compose));
  },
  setModalStopBuildState: (composeId, blueprintName) => {
    dispatch(setModalStopBuildState(composeId, blueprintName));
  },
  setModalStopBuildVisible: visible => {
    dispatch(setModalStopBuildVisible(visible));
  },
  setModalDeleteImageState: (composeId, blueprintName) => {
    dispatch(setModalDeleteImageState(composeId, blueprintName));
  },
  setModalDeleteImageVisible: visible => {
    dispatch(setModalDeleteImageVisible(visible));
  }
});

export default connect(null, mapDispatchToProps)(injectIntl(ListItemImages));
<commit_msg>components: remove stop option<commit_after>import React from "react";
import { FormattedMessage, defineMessages, injectIntl, intlShape } from "react-intl";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import {
  Button,
  DataListItem,
  DataListItemRow,
  DataListCell,
  DataListToggle,
  DataListContent,
  DataListItemCells
} from "@patternfly/react-core";
import { BuilderImageIcon } from "@patternfly/react-icons";
import { deletingCompose, cancellingCompose } from "../../core/actions/composes";
import {
  setModalStopBuildVisible,
  setModalStopBuildState,
  setModalDeleteImageVisible,
  setModalDeleteImageState
} from "../../core/actions/modals";
import Logs from "../Logs/Logs";
import * as composer from "../../core/composer";
import ImagesDataList from "./ImagesDataList";
import ListItemUploads from "./ListItemUploads";

const messages = defineMessages({
  imageType: {
    defaultMessage: "Type",
    description: "A label for the type of image file was created"
  },
  imageCreated: {
    defaultMessage: "Created",
    description: "A label for the date that an image file was created"
  },
  imageSize: {
    defaultMessage: "Size",
    description: "A label for the size of an image file"
  },
  imageUploads: {
    defaultMessage: "Image uploads",
    description: "A label for the section that lists the upload actions initiated by the user"
  },
  imageActions: {
    defaultMessage: "Actions",
    description: "A label for the menu that displays the actions available"
  },
  imageLogs: {
    defaultMessage: "Logs",
    description: "Log content that gets generated as part of the image creation process"
  },
  imageStatusWaiting: {
    defaultMessage: "Image build pending",
    description: "Image build status when process is waiting"
  },
  imageStatusRunning: {
    defaultMessage: "Image build in progress",
    description: "Image build status when process is in progress"
  },
  imageStatusFinished: {
    defaultMessage: "Image build complete",
    description: "Image build status when process is finished"
  },
  imageStatusFailed: {
    defaultMessage: "Image build failed",
    description: "Image build status when process failed"
  },
  imageStatusStopping: {
    defaultMessage: "Stopping",
    description: "Image build status when user selected to end the process"
  }
});

class ListItemImages extends React.Component {
  constructor() {
    super();
    this.state = { logsExpanded: false, uploadsExpanded: false };
    this.handleDelete = this.handleDelete.bind(this);
    this.handleCancel = this.handleCancel.bind(this);
    this.handleShowModalStop = this.handleShowModalStop.bind(this);
    this.handleShowModalDeleteImage = this.handleShowModalDeleteImage.bind(this);
    this.handleLogsShow = this.handleLogsShow.bind(this);
    this.handleUploadsShow = this.handleUploadsShow.bind(this);
  }

  // maps to Remove button for FAILED
  handleDelete(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.deletingCompose(this.props.listItem.id);
  }

  // maps to Stop button for WAITING
  handleCancel(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.cancellingCompose(this.props.listItem.id);
  }

  // maps to Stop button for RUNNING
  handleShowModalStop(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.setModalStopBuildState(this.props.listItem.id, this.props.blueprint);
    this.props.setModalStopBuildVisible(true);
  }

  // maps to Delete button for FINISHED
  handleShowModalDeleteImage(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.setModalDeleteImageState(this.props.listItem.id, this.props.blueprint);
    this.props.setModalDeleteImageVisible(true);
  }

  handleLogsShow() {
    this.setState({ uploadsExpanded: false });
    this.setState(prevState => ({ logsExpanded: !prevState.logsExpanded, fetchingLogs: !prevState.logsExpanded }));
    composer.getComposeLog(this.props.listItem.id).then(
      logs => {
        this.setState({ logsContent: logs, fetchingLogs: false });
      },
      () => {
        this.setState({
          logsContent: <FormattedMessage defaultMessage="No log available" />,
          fetchingLogs: false
        });
      }
    );
  }
  // consider removing
  handleUploadsShow() {
    this.setState({ logsExpanded: false });
    this.setState(prevState => ({ uploadsExpanded: !prevState.uploadsExpanded }));
  }

  render() {
    const { listItem } = this.props;
    const { formatMessage } = this.props.intl;
    const timestamp = new Date(listItem.job_created * 1000);
    const formattedTime = timestamp.toDateString();
    let actions;
    switch (listItem.queue_status) {
      case "FINISHED":
        actions = (
          <>

                <FormattedMessage defaultMessage="Download" />

               this.handleShowModalDeleteImage(e)} data-delete>
                <FormattedMessage defaultMessage="Delete" />

          </>
        );
        break;
      case "FAILED":
        actions = (
          <>

               this.handleDelete(e)}>
                <FormattedMessage defaultMessage="Remove" />

          </>
        );
        break;
      default:
        actions = undefined;
        break;
    }
    const noLogs = listItem.queue_status === "WAITING" || listItem.queue_status === "STOPPING";
    const logsButton = (
      <div
        aria-hidden={noLogs}
        className={`pf-c-data-list__item-action ${noLogs ? "cc-u-not-visible" : ""}`}
      >
        <Button
          variant={`${this.state.logsExpanded ? "primary" : "secondary"}`}
          aria-expanded={this.state.logsExpanded}
          aria-controls={`${listItem.id}-logs`}
          onClick={this.handleLogsShow}
        >
          {formatMessage(messages.imageLogs)}
        </Button>

    );
    let uploadsToggle;
    if (listItem.uploads !== undefined) {
      uploadsToggle = (
        <DataListToggle
            onClick={this.handleUploadsShow}
            isExpanded={this.state.uploadsExpanded}
            id="uploads-toggle"
            aria-label={`${formatMessage(messages.imageUploads)} ${this.props.blueprint}-${listItem.version}-${listItem.compose_type}`}
            aria-controls={`${listItem.id}-uploads`}
            // ^ need to fix this attribute value
            aria-hidden={!listItem.uploads.length > 0}
            className={`${!listItem.uploads.length > 0 ? "cc-u-not-visible" : ""}`}
          />
      );
    }
    const composeStatus = () => {
      switch (listItem.queue_status) {
        case "WAITING":
          return (

              {formatMessage(messages.imageStatusWaiting)}

          );
        case "RUNNING":
          return (

              {formatMessage(messages.imageStatusRunning)}

          );
        case "FINISHED":
          return (

              {formatMessage(messages.imageStatusFinished)}

          );
        case "FAILED":
          return (

              {formatMessage(messages.imageStatusFailed)}

          );
        case "STOPPING":
          return (

                {formatMessage(messages.imageStatusStopping)}

          );
        default:
          return <></>;
      }
    };
    let logsSection;
    if (this.state.logsExpanded) {
      logsSection = <Logs logContent={this.state.logsContent} fetchingLog={this.state.fetchingLogs} />;
    }
    let uploadsSection;
    if (this.state.uploadsExpanded) {
      uploadsSection = (
        <ImagesDataList ariaLabel={formatMessage(messages.imageUploads)}>
          {listItem.uploads.map(upload => (
            <ListItemUploads upload={upload} key={upload.uuid} />
          ))}
        </ImagesDataList>
      );
    }
    const size = Math.round(listItem.image_size / 10000000) / 100;

    return (
      <DataListItem
        aria-labelledby={`${listItem.id}-compose-name`}
        isExpanded={this.state.uploadsExpanded}
        data-image={`${this.props.blueprint}-${listItem.version}-${listItem.compose_type}`}
      >
        <DataListItemRow className={`${this.state.logsExpanded ? "cc-m-sticky" : ""}`}>
          {uploadsToggle}

            <BuilderImageIcon />

          <DataListItemCells
            className="cc-m-stacked cc-m-split-on-lg"
            dataListCells={[
              <DataListCell key="primary" className="pf-l-flex pf-m-column pf-m-space-items-xs">

                  <strong id={`${listItem.id}-compose-name`} data-image-name>
                    {this.props.blueprint}-{listItem.version}-{listItem.compose_type}

                  {formatMessage(messages.imageType)}
                  {listItem.compose_type}

                  {formatMessage(messages.imageCreated)} {formattedTime}

                {listItem.queue_status === "FINISHED" && (

                  {formatMessage(messages.imageSize)} {size} GB

                )}
              </DataListCell>,
              <DataListCell key="status">{composeStatus()}</DataListCell>
            ]}
          />
          <div
            className={`pf-c-data-list__item-action ${actions === undefined ? "cc-u-not-visible" : ""}`}
            aria-hidden={actions === undefined}
          >

              <button
                aria-label={formatMessage(messages.imageActions)}
                className="btn btn-link dropdown-toggle"
                type="button"
                id={`${listItem.id}-actions`}
                data-toggle="dropdown"
                aria-haspopup="true"
                aria-expanded="false"
              >

              </button>
              <ul className="dropdown-menu dropdown-menu-right" aria-labelledby={`${listItem.id}-actions`}>
                {actions}

          {logsButton}
        </DataListItemRow>
        <DataListContent aria-label={formatMessage(messages.imageUploads)} id={`${listItem.id}-uploads`} isHidden={!this.state.uploadsExpanded} noPadding>
          {uploadsSection}
        </DataListContent>
        <DataListContent
          aria-label={formatMessage(messages.imageLogs)}
          id={`${listItem.id}-logs`}
          isHidden={!this.state.logsExpanded}
          noPadding
        >
          {logsSection}
        </DataListContent>
      </DataListItem>
    );
  }
}

ListItemImages.propTypes = {
  listItem: PropTypes.shape({
    blueprint: PropTypes.string,
    compose_type: PropTypes.string,
    id: PropTypes.string,
    image_size: PropTypes.number,
    job_created: PropTypes.number,
    job_finished: PropTypes.number,
    job_started: PropTypes.number,
    queue_status: PropTypes.string,
    version: PropTypes.string,
    uploads: PropTypes.arrayOf(PropTypes.object)
  }),
  blueprint: PropTypes.string,
  deletingCompose: PropTypes.func,
  cancellingCompose: PropTypes.func,
  setModalStopBuildState: PropTypes.func,
  setModalStopBuildVisible: PropTypes.func,
  setModalDeleteImageState: PropTypes.func,
  setModalDeleteImageVisible: PropTypes.func,
  downloadUrl: PropTypes.string,
  intl: intlShape.isRequired
};

ListItemImages.defaultProps = {
  listItem: {},
  blueprint: "",
  deletingCompose: function() {},
  cancellingCompose: function() {},
  setModalStopBuildState: function() {},
  setModalStopBuildVisible: function() {},
  setModalDeleteImageState: function() {},
  setModalDeleteImageVisible: function() {},
  downloadUrl: ""
};

const mapDispatchToProps = dispatch => ({
  deletingCompose: compose => {
    dispatch(deletingCompose(compose));
  },
  cancellingCompose: compose => {
    dispatch(cancellingCompose(compose));
  },
  setModalStopBuildState: (composeId, blueprintName) => {
    dispatch(setModalStopBuildState(composeId, blueprintName));
  },
  setModalStopBuildVisible: visible => {
    dispatch(setModalStopBuildVisible(visible));
  },
  setModalDeleteImageState: (composeId, blueprintName) => {
    dispatch(setModalDeleteImageState(composeId, blueprintName));
  },
  setModalDeleteImageVisible: visible => {
    dispatch(setModalDeleteImageVisible(visible));
  }
});

export default connect(null, mapDispatchToProps)(injectIntl(ListItemImages));
<|endoftext|>


<commit_before>import Handorgel from '../src/js'

const accordion = new Handorgel(document.querySelector('.default'))

const accordion2 = new Handorgel(document.querySelector('.single-select'), {
  multiSelectable: false
})

const accordion3 = new Handorgel(document.querySelector('.single-select-not-collapsible'), {
  multiSelectable: false,
  collapsible: false
})
<commit_msg>Fix demo path<commit_after>import Handorgel from '../../src/js'

const accordion = new Handorgel(document.querySelector('.default'))

const accordion2 = new Handorgel(document.querySelector('.single-select'), {
  multiSelectable: false
})

const accordion3 = new Handorgel(document.querySelector('.single-select-not-collapsible'), {
  multiSelectable: false,
  collapsible: false
})
<|endoftext|>


<commit_before>import React from "react";
import { connect } from "react-redux";
import { Modal } from "patternfly-react";
import { FormattedMessage } from "react-intl";
import PropTypes from "prop-types";
import { fetchingBlueprintExportContents } from "../../core/actions/blueprints";

class ExportBlueprint extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showModal: false
    };
    this.open = this.open.bind(this);
    this.close = this.close.bind(this);
  }

  open(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.fetchingBlueprintExportContents(this.props.blueprint.name);
    this.setState({ showModal: true });
  }

  close() {
    this.setState({ showModal: false });
  }

  handleCopy() {
    this.blueprint_contents_text.select();
    document.execCommand("copy");
  }

  handleEnterKey(event) {
    if (event.which === 13 || event.keyCode === 13) {
      this.handleCopy();
    }
  }

  render() {
    return (
      <React.Fragment>

          <FormattedMessage defaultMessage="Export" />

        <Modal show={this.state.showModal} onHide={this.close} id="cmpsr-modal-export" aria-labelledby="title-export">
          <Modal.Header>
            <Modal.CloseButton onClick={this.close} />
            <Modal.Title id="title-export">
              <FormattedMessage defaultMessage="Export Blueprint" />
            </Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <form className="form-horizontal">

                  <FormattedMessage defaultMessage="Blueprint" />

                    {this.props.blueprint.name}

                  <FormattedMessage defaultMessage="Export as" />

                  <select className="form-control">
                    <FormattedMessage defaultMessage="Text" tagName="option" />
                  </select>

                  <FormattedMessage defaultMessage="Contents" />

                {(this.props.blueprint.exportContents && (

                    <textarea
                      readOnly
                      id="textInput2-modal-markup"
                      ref={c => {
                        this.blueprint_contents_text = c;
                      }}
                      className="form-control"
                      rows="10"
                      value={this.props.blueprint.exportContents
                        .map(comp => `${comp.name}-${comp.version}-${comp.release}`)
                        .join("\n")}
                      onKeyPress={e => this.handleEnterKey(e)}
                    />

                      <FormattedMessage
                        defaultMessage="{count} total components"
                        values={{
                          count: this.props.blueprint.exportContents.length
                        }}
                      />

                )) || (

                )}

            </form>
          </Modal.Body>
          <Modal.Footer>
            <button type="button" className="btn btn-default" onClick={this.close}>
              <FormattedMessage defaultMessage="Close" />
            </button>
            <button type="button" className="btn btn-primary" onClick={() => this.handleCopy()}>
              <FormattedMessage defaultMessage="Copy" />
            </button>
          </Modal.Footer>
        </Modal>
      </React.Fragment>
    );
  }
}

ExportBlueprint.propTypes = {
  fetchingBlueprintExportContents: PropTypes.func,
  blueprint: PropTypes.shape({
    name: PropTypes.string,
    exportContents: PropTypes.arrayOf(PropTypes.object),
    packages: PropTypes.arrayOf(PropTypes.object),
    modules: PropTypes.arrayOf(PropTypes.object)
  })
};

ExportBlueprint.defaultProps = {
  fetchingBlueprintExportContents: function() {},
  blueprint: {}
};

const mapStateToProps = () => ({});

const mapDispatchToProps = dispatch => ({
  fetchingBlueprintExportContents: blueprint => {
    dispatch(fetchingBlueprintExportContents(blueprint));
  }
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ExportBlueprint);
<commit_msg>Don't disable export blueprint button when there are no packages or modules<commit_after>import React from "react";
import { connect } from "react-redux";
import { Modal } from "patternfly-react";
import { FormattedMessage } from "react-intl";
import PropTypes from "prop-types";
import { fetchingBlueprintExportContents } from "../../core/actions/blueprints";

class ExportBlueprint extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showModal: false
    };
    this.open = this.open.bind(this);
    this.close = this.close.bind(this);
  }

  open(e) {
    e.preventDefault();
    e.stopPropagation();
    this.props.fetchingBlueprintExportContents(this.props.blueprint.name);
    this.setState({ showModal: true });
  }

  close() {
    this.setState({ showModal: false });
  }

  handleCopy() {
    this.blueprint_contents_text.select();
    document.execCommand("copy");
  }

  handleEnterKey(event) {
    if (event.which === 13 || event.keyCode === 13) {
      this.handleCopy();
    }
  }

  render() {
    return (
      <React.Fragment>

          <FormattedMessage defaultMessage="Export" />

        <Modal show={this.state.showModal} onHide={this.close} id="cmpsr-modal-export" aria-labelledby="title-export">
          <Modal.Header>
            <Modal.CloseButton onClick={this.close} />
            <Modal.Title id="title-export">
              <FormattedMessage defaultMessage="Export Blueprint" />
            </Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <form className="form-horizontal">

                  <FormattedMessage defaultMessage="Blueprint" />

                    {this.props.blueprint.name}

                  <FormattedMessage defaultMessage="Export as" />

                  <select className="form-control">
                    <FormattedMessage defaultMessage="Text" tagName="option" />
                  </select>

                  <FormattedMessage defaultMessage="Contents" />

                {(this.props.blueprint.exportContents && (

                    <textarea
                      readOnly
                      id="textInput2-modal-markup"
                      ref={c => {
                        this.blueprint_contents_text = c;
                      }}
                      className="form-control"
                      rows="10"
                      value={this.props.blueprint.exportContents
                        .map(comp => `${comp.name}-${comp.version}-${comp.release}`)
                        .join("\n")}
                      onKeyPress={e => this.handleEnterKey(e)}
                    />

                      <FormattedMessage
                        defaultMessage="{count} total components"
                        values={{
                          count: this.props.blueprint.exportContents.length
                        }}
                      />

                )) || (

                )}

            </form>
          </Modal.Body>
          <Modal.Footer>
            <button type="button" className="btn btn-default" onClick={this.close}>
              <FormattedMessage defaultMessage="Close" />
            </button>
            <button type="button" className="btn btn-primary" onClick={() => this.handleCopy()}>
              <FormattedMessage defaultMessage="Copy" />
            </button>
          </Modal.Footer>
        </Modal>
      </React.Fragment>
    );
  }
}

ExportBlueprint.propTypes = {
  fetchingBlueprintExportContents: PropTypes.func,
  blueprint: PropTypes.shape({
    name: PropTypes.string,
    exportContents: PropTypes.arrayOf(PropTypes.object)
  })
};

ExportBlueprint.defaultProps = {
  fetchingBlueprintExportContents: function() {},
  blueprint: {}
};

const mapStateToProps = () => ({});

const mapDispatchToProps = dispatch => ({
  fetchingBlueprintExportContents: blueprint => {
    dispatch(fetchingBlueprintExportContents(blueprint));
  }
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ExportBlueprint);
<|endoftext|>


<commit_before>describe("About Functions", function() {

  it("should declare functions", function() {

    function add(a, b) {
      return a + b;
    }

    expect(add(1, 2)).toBe(3);
  });

  it("should know internal variables override outer variables", function () {
    var message = "Outer";

    function getMessage() {
      return message;
    }

    function overrideMessage() {
      var message = "Inner";

      return message;
    }

    expect(getMessage()).toBe("Outer");
    expect(overrideMessage()).toBe("Inner");
    expect(message).toBe("Outer");
  });

  it("should have lexical scoping", function() {
    var variable = "top-level";

    function parentfunction() {
      var variable = "local";

      function childfunction() {
        return variable;
      }
      return childfunction();
    }
    expect(parentfunction()).toBe("local");
  });

  it("should use lexical scoping to synthesise functions", function() {

    function makeIncreaseByFunction(increaseByAmount) {
      return function(numberToIncrease) {
        return numberToIncrease + increaseByAmount;
      };
    }

    var increaseBy3 = makeIncreaseByFunction(3);
    var increaseBy5 = makeIncreaseByFunction(5);

    expect(increaseBy3(10) + increaseBy5(10)).toBe(28);
  });

  it("should allow extra function arguments", function() {

    function returnFirstArg(firstArg) {
      return firstArg;
    }

    expect(returnFirstArg("first", "second", "third")).toBe("first");

    function returnSecondArg(firstArg, secondArg) {
      return secondArg;
    }

    expect(returnSecondArg("only give first arg")).toBe(undefined);

    function returnAllArgs() {
      var argsArray = [];

      for (var i = 0; i < arguments.length; i += 1) {
        argsArray.push(arguments[i]);
      }
      return argsArray.join(",");
    }

    expect(returnAllArgs("first", "second", "third")).toBe("first,second,third");
  });

  it("should pass functions as values", function() {
    var appendRules = function(name) {
      return name + " rules!";
    };

    var appendDoubleRules = function(name) {
      return name + " totally rules!";
    };

    var praiseSinger = { givePraise: appendRules };
    expect(praiseSinger.givePraise("John")).toBe("John rules!");

    praiseSinger.givePraise = appendDoubleRules;
    expect(praiseSinger.givePraise("Mary")).toBe("Mary totally rules!");

  });

  it("should use function body as a string", function() {
    var add = new Function("a", "b", "return a + b;");
    expect(add(1, 2)).toBe(3);

    var multiply = function(a, b) {
      // An internal comment
      return a * b;
    };
    // expect(multiply.toString()).toBe("function(a, b) {\n// An internal comment\nreturn a * b;\n}");
    // Can't get the previous line to work. Commented it out to proceed.
  });
});
<commit_msg>Fixed the pesky toString<commit_after>describe("About Functions", function() {

  it("should declare functions", function() {

    function add(a, b) {
      return a + b;
    }

    expect(add(1, 2)).toBe(3);
  });

  it("should know internal variables override outer variables", function () {
    var message = "Outer";

    function getMessage() {
      return message;
    }

    function overrideMessage() {
      var message = "Inner";

      return message;
    }

    expect(getMessage()).toBe("Outer");
    expect(overrideMessage()).toBe("Inner");
    expect(message).toBe("Outer");
  });

  it("should have lexical scoping", function() {
    var variable = "top-level";

    function parentfunction() {
      var variable = "local";

      function childfunction() {
        return variable;
      }
      return childfunction();
    }
    expect(parentfunction()).toBe("local");
  });

  it("should use lexical scoping to synthesise functions", function() {

    function makeIncreaseByFunction(increaseByAmount) {
      return function(numberToIncrease) {
        return numberToIncrease + increaseByAmount;
      };
    }

    var increaseBy3 = makeIncreaseByFunction(3);
    var increaseBy5 = makeIncreaseByFunction(5);

    expect(increaseBy3(10) + increaseBy5(10)).toBe(28);
  });

  it("should allow extra function arguments", function() {

    function returnFirstArg(firstArg) {
      return firstArg;
    }

    expect(returnFirstArg("first", "second", "third")).toBe("first");

    function returnSecondArg(firstArg, secondArg) {
      return secondArg;
    }

    expect(returnSecondArg("only give first arg")).toBe(undefined);

    function returnAllArgs() {
      var argsArray = [];

      for (var i = 0; i < arguments.length; i += 1) {
        argsArray.push(arguments[i]);
      }
      return argsArray.join(",");
    }

    expect(returnAllArgs("first", "second", "third")).toBe("first,second,third");
  });

  it("should pass functions as values", function() {
    var appendRules = function(name) {
      return name + " rules!";
    };

    var appendDoubleRules = function(name) {
      return name + " totally rules!";
    };

    var praiseSinger = { givePraise: appendRules };
    expect(praiseSinger.givePraise("John")).toBe("John rules!");

    praiseSinger.givePraise = appendDoubleRules;
    expect(praiseSinger.givePraise("Mary")).toBe("Mary totally rules!");

  });

  it("should use function body as a string", function() {
    var add = new Function("a", "b", "return a + b;");
    expect(add(1, 2)).toBe(3);

    var multiply = function(a, b) {
      // An internal comment
      return a * b;
    };
    expect(multiply.toString()).toBe("function (a, b) {
      // An internal comment
      return a * b;
    }");
    // Can't get the previous line to work. Commented it out to proceed.
  });
});
<|endoftext|>


<commit_before>function motion(element) {
    var base = "https://res.cloudinary.com/demo/video/upload/so_0,du_3/vs_30,e_loop:10/w_260,h_105,c_fill/q_50,r_5,b_white/fl_lossy.animated/f_auto/";
    var suffix = ".gif";
    switchImage(element.getElementsByTagName('img')[0],element.id,base,suffix);
}
function still(element) {
	var base = "https://res.cloudinary.com/demo/video/upload/so_0,w_260,h_105,c_fill,r_5,b_white,q_auto,f_auto/";
	var suffix = ".jpg";
	switchImage(element.getElementsByTagName('img')[0],element.id,base,suffix);
}
function switchImage(elm,id,base,suffix) {
    switch (id) {
		case "sec01":
			elm.setAttribute('src', base+"rafting_short"+suffix);
			break;
		case "sec02":
			elm.setAttribute('src', base+"forest_bike"+suffix);
			break;
		case "sec03":
			elm.setAttribute('src', base+"snow_horses"+suffix);
			break;
		case "sec04":
			elm.setAttribute('src', base+"snow_deer"+suffix);
			break;
		default:
			console.log("switchImage id=",id);
		}
}
function copyURL() {
  var urlStr = window.location.href;
  copyStringToClipboard(urlStr);
}

function copyStringToClipboard (str) {
  const el = document.createElement('textarea');
  el.value = str;
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
}

window.addEventListener('scroll',checkPosition,false);
function checkPosition()
{
    var fixedHeader = document.getElementById("header");
    if(window.scrollY > 50)
    {
        fixedHeader.classList.add("fixed-position");
    } else {
        fixedHeader.classList.remove("fixed-position");
    }
}

function playerSizeChange(input) {
  var area = document.getElementById("video-area-adaptive");
  var border = document.getElementById("player-border");
  var val = input.value + "%";
  area.style.width = val;
  border.style.width = val;
  var pwidth = document.getElementById("player-width");
  pwidth.innerHTML = area.clientWidth;
}
function updateOnResize() {
  var width = demoplayer.videojs.videoWidth();
  var current = document.getElementById(width);
  var oldactive = document.getElementsByClassName("range-info active");
  for (var i = 0; i < oldactive.length; i++) {
    oldactive[i].setAttribute("class","range-info");
  }
  current.setAttribute("class","range-info active");
}
function requestResolution(btn) {
  if(!safari)
  {
    document.getElementById("checkbox").checked = false;
    document.getElementById("checkboxLabel").classList.add("disabled");
    for (var i = 0; i < qualityLevels.length; i++) {
      qualityLevels[i].enabled = (Number(btn.id) == qualityLevels[i].width);
    }
  }
}
function requestAuto() {
  var auto = document.getElementById("checkbox");
  console.log("requestAuto() ",auto.checked);
  if(auto.checked) {
    for (var i = 0; i < qualityLevels.length; i++) {
        qualityLevels[i].enabled = true;
    }
  }
  document.getElementById("checkboxLabel").classList.toggle("disabled");
}

function reportQuality() {
	for (var i = 0; i < qualityLevels.length; i++)
        	console.log("reportQuality",i,qualityLevels[i].width,qualityLevels[i].enabled);
}

function changeOfResolution() {
  var index = qualityLevels.selectedIndex;
  var res = document.getElementById(qualityLevels[index].width);
  var old = document.getElementsByClassName("range-info second-hover");
  for (var i = 0; i < old.length; i++) {
    old[i].setAttribute("class","range-info");
  }
  res.setAttribute("class","range-info second-hover");
}

function setProfile(profile) {
  updateResolutionRange(profile.value);
  demoplayer.source("kayak", { sourceTypes: ['hls'], transformation: {streaming_profile: profile.value } }).play();
}

function updateResolutionRange(profileVal) {
  var elements = document.getElementsByClassName('range-info');
  var i = elements.length;

    while(i--) {
        if(elements[i].getElementsByClassName(profileVal).length > 0)
          elements[i].setAttribute("class","range-info");
        else
          elements[i].setAttribute("class","range-info out-of-range");

    }
  document.getElementById("checkbox").checked = true;
  document.getElementById("checkboxLabel").classList.remove("disabled");
}

var chrome   = navigator.userAgent.indexOf('Chrome') > -1;
var safari   = navigator.userAgent.indexOf("Safari") > -1;
if ((chrome) && (safari)) safari = false;

if(safari)
  document.getElementById("checkbox").disabled = true;

playerSizeChange(document.getElementById("player-slider"));

addLi();

var cld = cloudinary.Cloudinary.new({ cloud_name: 'demo' });

var adaptive = document.getElementById("adaptive");
document.getElementById("demo-adaptive-player").addEventListener('resize',updateOnResize, false);

var demoplayer = cld.videoPlayer('demo-adaptive-player');

var qualityLevels = demoplayer.videojs.qualityLevels();
qualityLevels.on('change', changeOfResolution);
// qualityLevels.on('addqualitylevel', function(event) { console.log(event.qualityLevel.width); });

if(window.innerWidth < 960) {
	document.getElementById('streaming4').checked = true;
	updateResolutionRange("sd");
	demoplayer.source("kayak", { sourceTypes: ['hls'],
				    transformation: {streaming_profile: 'sd' },
			  poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }}
                          });
}
else {
	demoplayer.source('kayak',{ sourceTypes: ['hls'],
                            transformation: {streaming_profile: 'full_hd' },
                            poster: { transformation: { width: 1920, crop: 'limit', quality: 'auto', fetch_format: 'auto' }}
                          });
  document.getElementById('streaming2').checked = true;
}

function updateOnEvent(eventStr,automatic) {
  var list = document.getElementById('events-list');
  var entry = document.createElement('li');
  if(automatic)
      entry.className = "orange";
  entry.appendChild(document.createTextNode(eventStr));
  list.appendChild(entry);
  list.scrollTop = list.scrollHeight;
}

function checkTime(i) {
        return (i < 10) ? "0" + i : i;
    }

function startTime() {
        var today = new Date(),
            h = checkTime(today.getHours()),
            m = checkTime(today.getMinutes()),
            s = checkTime(today.getSeconds());
        return (h + ":" + m + ":" + s);
}

function addLi() {
  var resolutions = ['3840ul', '2560ul', '1920ul', '1280ul', '960ul', '640ul', '480ul', '320ul'];
  var li = null;
  for (var i = 0; i < resolutions.length; i++) {
      var res = resolutions[i];
      var ul = document.getElementById(res);
      for (var j = 0; j<11; j++) {
        li = document.createElement('li');
        if(j == 5 )
          li.className = "long";
        ul.appendChild(li);
      }
  }
}

var eventplayer = cld.videoPlayer('demo-events-player',
  { playedEventTimes: [3, 10],
    analytics: { // Enable player analytics
    events: [
    'play',
    'pause',
    'percentsplayed',
    'start',
    'ended',
    'fullscreenchange']}});

var autoEventTypes = ['sourcechanged', 'timeplayed', 'percentsplayed', 'ended'];

var manualEventTypes = ['play', 'pause', 'volumechange', 'mute', 'unmute', 'fullscreenchange',
      'seek'];

autoEventTypes.forEach(function(eventType) {
      eventplayer.on(eventType, function(event) {
        var eventStr = startTime() + " " + eventType;
        if (event.eventData) {
          eventStr = eventStr + ": " + JSON.stringify(event.eventData)
        }
        updateOnEvent(eventStr,true);
      })
    });

manualEventTypes.forEach(function(eventType) {
      eventplayer.on(eventType, function(event) {
        var eventStr = startTime() + " " + eventType;
        if (event.eventData) {
          eventStr = eventStr + ": " + JSON.stringify(event.eventData)
        }
        updateOnEvent(eventStr,false);
      })
    });

 eventplayer.source('forest_bike',{ sourceTypes: ['hls'],
                                    transformation: {streaming_profile: 'full_hd' },
                                    poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }}
                                  });

var plistplayer = cld.videoPlayer('demo-playlist-player',{
  playlistWidget: {
    direction: "horizontal",
    total: 4
  }});

var psource1 = { publicId: 'snow_horses', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Horses', subtitle: 'Snow Horses Movie' } };
var psource2 = { publicId: 'snow_deer', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Deer', subtitle: 'Snow Deer Movie' } };
var psource3 = { publicId: 'sea_turtle', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Sea Turtle', subtitle: 'Sea Turtle Movie' } };
var psource4 = { publicId: 'elephants', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
	       poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Elephants', subtitle: 'Elephants' } };

plistplayer.playlist([psource1, psource2, psource3, psource4], { autoAdvance: 0, repeat: true, presentUpcoming: 5 });

var recplayer = cld.videoPlayer('demo-recommendation-player',{ autoShowRecommendations: true });

var source1 = { publicId: 'snow_deer_short', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Deer', subtitle: 'Snow Deer Movie' } };
var source2 = { publicId: 'snow_horses', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Horses', subtitle: 'Snow Horses Movie' } };
var source3 = { publicId: 'sea_turtle', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Sea Turtle', subtitle: 'Sea Turtle Movie' } };
var source4 = { publicId: 'elephants', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
	       poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Elephants', subtitle: 'Elephants' } };
var source5 = { publicId: 'marmots', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Marmots', subtitle: 'Marmots' } };

source1.recommendations = [source2];
source2.recommendations = [source3];
source3.recommendations = [source4, source5, source1, source2];
source4.recommendations = [source5];
source5.recommendations = [source2, source3, source4, source1];
var first = true;
recplayer.on('sourcechanged', function(event) {if (first) {first = false;} else {recplayer.play();}});
recplayer.source(source3);
var adTagUrl = ["https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dskippablelinear&correlator=6",
"https://pubads.g.doubleclick.net/gampad/ads?sz=480x70&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dnonlinear&correlator=",
"https://cloudinary-demo.global.ssl.fastly.net/generic_vast/vastdemo_preroll.xml"];
var adsplayer = cld.videoPlayer('demo-ads-player', {ads: {adTagUrl: adTagUrl[0], adsInPlaylist: 'every-video'}});
var adsplayer1 = cld.videoPlayer('demo-ads-player-banner', {ads: {adTagUrl: adTagUrl[1], adsInPlaylist: 'every-video'}});
var adsplayer2 = cld.videoPlayer('demo-ads-player-vast', {ads: {adTagUrl: adTagUrl[2], adsInPlaylist: 'every-video'}});
var adsPlaylistSources = [source1, source2, source3, source4, source5];
var adsPlaylistOptions = {
  autoAdvance: true,
  repeat: true
};

  adsplayer.playlist(adsPlaylistSources, adsPlaylistOptions);
  adsplayer1.playlist(adsPlaylistSources, adsPlaylistOptions);
  adsplayer2.playlist(adsPlaylistSources, adsPlaylistOptions);

function setVAST(vastOption) {
  var option = Number(vastOption.value)
  if(option < adTagUrl.length)
  {
    var adElement = document.getElementById('demo-ads-player');
    var adElement1 = document.getElementById('demo-ads-player-banner');
    var adElement2 = document.getElementById('demo-ads-player-vast');
    switch(option) {
      case 0:
        adsplayer.playNext();
        adsplayer1.stop();
        adsplayer2.stop();
        adElement.classList.remove('hidden');
        adElement1.classList.add('hidden');
        adElement2.classList.add('hidden');
        break;
      case 1:
        adsplayer.stop();
        adsplayer1.playNext();
        adsplayer2.stop();
        adElement.classList.add('hidden');
        adElement1.classList.remove('hidden');
        adElement2.classList.add('hidden');
        break;
      case 2:
        adsplayer.stop();
        adsplayer1.stop();
        adsplayer2.playNext();
        adElement.classList.add('hidden');
        adElement1.classList.add('hidden');
        adElement2.classList.remove('hidden');
        break;
      default:
        // code block
    }
  }
}
<commit_msg>Update main.js<commit_after>function motion(element) {
    var base = "https://res.cloudinary.com/demo/video/upload/so_0,du_3/vs_30,e_loop:100/w_260,h_105,c_fill/q_50,r_5,b_white/fl_lossy.animated/f_auto/";
    var suffix = ".gif";
    switchImage(element.getElementsByTagName('img')[0],element.id,base,suffix);
}
function still(element) {
	var base = "https://res.cloudinary.com/demo/video/upload/so_0,w_260,h_105,c_fill,r_5,b_white,q_auto,f_auto/";
	var suffix = ".jpg";
	switchImage(element.getElementsByTagName('img')[0],element.id,base,suffix);
}
function switchImage(elm,id,base,suffix) {
    switch (id) {
		case "sec01":
			elm.setAttribute('src', base+"rafting_short"+suffix);
			break;
		case "sec02":
			elm.setAttribute('src', base+"forest_bike"+suffix);
			break;
		case "sec03":
			elm.setAttribute('src', base+"snow_horses"+suffix);
			break;
		case "sec04":
			elm.setAttribute('src', base+"snow_deer"+suffix);
			break;
		default:
			console.log("switchImage id=",id);
		}
}
function copyURL() {
  var urlStr = window.location.href;
  copyStringToClipboard(urlStr);
}

function copyStringToClipboard (str) {
  const el = document.createElement('textarea');
  el.value = str;
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
}

window.addEventListener('scroll',checkPosition,false);
function checkPosition()
{
    var fixedHeader = document.getElementById("header");
    if(window.scrollY > 50)
    {
        fixedHeader.classList.add("fixed-position");
    } else {
        fixedHeader.classList.remove("fixed-position");
    }
}

function playerSizeChange(input) {
  var area = document.getElementById("video-area-adaptive");
  var border = document.getElementById("player-border");
  var val = input.value + "%";
  area.style.width = val;
  border.style.width = val;
  var pwidth = document.getElementById("player-width");
  pwidth.innerHTML = area.clientWidth;
}
function updateOnResize() {
  var width = demoplayer.videojs.videoWidth();
  var current = document.getElementById(width);
  var oldactive = document.getElementsByClassName("range-info active");
  for (var i = 0; i < oldactive.length; i++) {
    oldactive[i].setAttribute("class","range-info");
  }
  current.setAttribute("class","range-info active");
}
function requestResolution(btn) {
  if(!safari)
  {
    document.getElementById("checkbox").checked = false;
    document.getElementById("checkboxLabel").classList.add("disabled");
    for (var i = 0; i < qualityLevels.length; i++) {
      qualityLevels[i].enabled = (Number(btn.id) == qualityLevels[i].width);
    }
  }
}
function requestAuto() {
  var auto = document.getElementById("checkbox");
  console.log("requestAuto() ",auto.checked);
  if(auto.checked) {
    for (var i = 0; i < qualityLevels.length; i++) {
        qualityLevels[i].enabled = true;
    }
  }
  document.getElementById("checkboxLabel").classList.toggle("disabled");
}

function reportQuality() {
	for (var i = 0; i < qualityLevels.length; i++)
        	console.log("reportQuality",i,qualityLevels[i].width,qualityLevels[i].enabled);
}

function changeOfResolution() {
  var index = qualityLevels.selectedIndex;
  var res = document.getElementById(qualityLevels[index].width);
  var old = document.getElementsByClassName("range-info second-hover");
  for (var i = 0; i < old.length; i++) {
    old[i].setAttribute("class","range-info");
  }
  res.setAttribute("class","range-info second-hover");
}

function setProfile(profile) {
  updateResolutionRange(profile.value);
  demoplayer.source("kayak", { sourceTypes: ['hls'], transformation: {streaming_profile: profile.value } }).play();
}

function updateResolutionRange(profileVal) {
  var elements = document.getElementsByClassName('range-info');
  var i = elements.length;

    while(i--) {
        if(elements[i].getElementsByClassName(profileVal).length > 0)
          elements[i].setAttribute("class","range-info");
        else
          elements[i].setAttribute("class","range-info out-of-range");

    }
  document.getElementById("checkbox").checked = true;
  document.getElementById("checkboxLabel").classList.remove("disabled");
}

var chrome   = navigator.userAgent.indexOf('Chrome') > -1;
var safari   = navigator.userAgent.indexOf("Safari") > -1;
if ((chrome) && (safari)) safari = false;

if(safari)
  document.getElementById("checkbox").disabled = true;

playerSizeChange(document.getElementById("player-slider"));

addLi();

var cld = cloudinary.Cloudinary.new({ cloud_name: 'demo' });

var adaptive = document.getElementById("adaptive");
document.getElementById("demo-adaptive-player").addEventListener('resize',updateOnResize, false);

var demoplayer = cld.videoPlayer('demo-adaptive-player');

var qualityLevels = demoplayer.videojs.qualityLevels();
qualityLevels.on('change', changeOfResolution);
// qualityLevels.on('addqualitylevel', function(event) { console.log(event.qualityLevel.width); });

if(window.innerWidth < 960) {
	document.getElementById('streaming4').checked = true;
	updateResolutionRange("sd");
	demoplayer.source("kayak", { sourceTypes: ['hls'],
				    transformation: {streaming_profile: 'sd' },
			  poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }}
                          });
}
else {
	demoplayer.source('kayak',{ sourceTypes: ['hls'],
                            transformation: {streaming_profile: 'full_hd' },
                            poster: { transformation: { width: 1920, crop: 'limit', quality: 'auto', fetch_format: 'auto' }}
                          });
  document.getElementById('streaming2').checked = true;
}

function updateOnEvent(eventStr,automatic) {
  var list = document.getElementById('events-list');
  var entry = document.createElement('li');
  if(automatic)
      entry.className = "orange";
  entry.appendChild(document.createTextNode(eventStr));
  list.appendChild(entry);
  list.scrollTop = list.scrollHeight;
}

function checkTime(i) {
        return (i < 10) ? "0" + i : i;
    }

function startTime() {
        var today = new Date(),
            h = checkTime(today.getHours()),
            m = checkTime(today.getMinutes()),
            s = checkTime(today.getSeconds());
        return (h + ":" + m + ":" + s);
}

function addLi() {
  var resolutions = ['3840ul', '2560ul', '1920ul', '1280ul', '960ul', '640ul', '480ul', '320ul'];
  var li = null;
  for (var i = 0; i < resolutions.length; i++) {
      var res = resolutions[i];
      var ul = document.getElementById(res);
      for (var j = 0; j<11; j++) {
        li = document.createElement('li');
        if(j == 5 )
          li.className = "long";
        ul.appendChild(li);
      }
  }
}

var eventplayer = cld.videoPlayer('demo-events-player',
  { playedEventTimes: [3, 10],
    analytics: { // Enable player analytics
    events: [
    'play',
    'pause',
    'percentsplayed',
    'start',
    'ended',
    'fullscreenchange']}});

var autoEventTypes = ['sourcechanged', 'timeplayed', 'percentsplayed', 'ended'];

var manualEventTypes = ['play', 'pause', 'volumechange', 'mute', 'unmute', 'fullscreenchange',
      'seek'];

autoEventTypes.forEach(function(eventType) {
      eventplayer.on(eventType, function(event) {
        var eventStr = startTime() + " " + eventType;
        if (event.eventData) {
          eventStr = eventStr + ": " + JSON.stringify(event.eventData)
        }
        updateOnEvent(eventStr,true);
      })
    });

manualEventTypes.forEach(function(eventType) {
      eventplayer.on(eventType, function(event) {
        var eventStr = startTime() + " " + eventType;
        if (event.eventData) {
          eventStr = eventStr + ": " + JSON.stringify(event.eventData)
        }
        updateOnEvent(eventStr,false);
      })
    });

 eventplayer.source('forest_bike',{ sourceTypes: ['hls'],
                                    transformation: {streaming_profile: 'full_hd' },
                                    poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }}
                                  });

var plistplayer = cld.videoPlayer('demo-playlist-player',{
  playlistWidget: {
    direction: "horizontal",
    total: 4
  }});

var psource1 = { publicId: 'snow_horses', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Horses', subtitle: 'Snow Horses Movie' } };
var psource2 = { publicId: 'snow_deer', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Deer', subtitle: 'Snow Deer Movie' } };
var psource3 = { publicId: 'sea_turtle', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Sea Turtle', subtitle: 'Sea Turtle Movie' } };
var psource4 = { publicId: 'elephants', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
	       poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Elephants', subtitle: 'Elephants' } };

plistplayer.playlist([psource1, psource2, psource3, psource4], { autoAdvance: 0, repeat: true, presentUpcoming: 5 });

var recplayer = cld.videoPlayer('demo-recommendation-player',{ autoShowRecommendations: true });

var source1 = { publicId: 'snow_deer_short', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Deer', subtitle: 'Snow Deer Movie' } };
var source2 = { publicId: 'snow_horses', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Snow Horses', subtitle: 'Snow Horses Movie' } };
var source3 = { publicId: 'sea_turtle', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Sea Turtle', subtitle: 'Sea Turtle Movie' } };
var source4 = { publicId: 'elephants', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
	       poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Elephants', subtitle: 'Elephants' } };
var source5 = { publicId: 'marmots', sourceTypes: ['hls'], transformation: {streaming_profile: 'full_hd'},
               poster: { transformation: { width: 960, crop: 'limit', quality: 'auto', fetch_format: 'auto' }},
               info: { title: 'Marmots', subtitle: 'Marmots' } };

source1.recommendations = [source2];
source2.recommendations = [source3];
source3.recommendations = [source4, source5, source1, source2];
source4.recommendations = [source5];
source5.recommendations = [source2, source3, source4, source1];
var first = true;
recplayer.on('sourcechanged', function(event) {if (first) {first = false;} else {recplayer.play();}});
recplayer.source(source3);
var adTagUrl = ["https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dskippablelinear&correlator=6",
"https://pubads.g.doubleclick.net/gampad/ads?sz=480x70&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dnonlinear&correlator=",
"https://cloudinary-demo.global.ssl.fastly.net/generic_vast/vastdemo_preroll.xml"];
var adsplayer = cld.videoPlayer('demo-ads-player', {ads: {adTagUrl: adTagUrl[0], adsInPlaylist: 'every-video'}});
var adsplayer1 = cld.videoPlayer('demo-ads-player-banner', {ads: {adTagUrl: adTagUrl[1], adsInPlaylist: 'every-video'}});
var adsplayer2 = cld.videoPlayer('demo-ads-player-vast', {ads: {adTagUrl: adTagUrl[2], adsInPlaylist: 'every-video'}});
var adsPlaylistSources = [source1, source2, source3, source4, source5];
var adsPlaylistOptions = {
  autoAdvance: true,
  repeat: true
};

  adsplayer.playlist(adsPlaylistSources, adsPlaylistOptions);
  adsplayer1.playlist(adsPlaylistSources, adsPlaylistOptions);
  adsplayer2.playlist(adsPlaylistSources, adsPlaylistOptions);

function setVAST(vastOption) {
  var option = Number(vastOption.value)
  if(option < adTagUrl.length)
  {
    var adElement = document.getElementById('demo-ads-player');
    var adElement1 = document.getElementById('demo-ads-player-banner');
    var adElement2 = document.getElementById('demo-ads-player-vast');
    switch(option) {
      case 0:
        adsplayer.playNext();
        adsplayer1.stop();
        adsplayer2.stop();
        adElement.classList.remove('hidden');
        adElement1.classList.add('hidden');
        adElement2.classList.add('hidden');
        break;
      case 1:
        adsplayer.stop();
        adsplayer1.playNext();
        adsplayer2.stop();
        adElement.classList.add('hidden');
        adElement1.classList.remove('hidden');
        adElement2.classList.add('hidden');
        break;
      case 2:
        adsplayer.stop();
        adsplayer1.stop();
        adsplayer2.playNext();
        adElement.classList.add('hidden');
        adElement1.classList.add('hidden');
        adElement2.classList.remove('hidden');
        break;
      default:
        // code block
    }
  }
}
<|endoftext|>


<commit_before>describe("About Functions", function() {

  it("should declare functions", function() {

    function add(a, b) {
      return a + b;
    }

    expect(add(1, 2)).toBe(FILL_ME_IN);
  });

  it("should know internal variables override outer variables", function () {
    var message = "Outer";

    function getMessage() {
      return message;
    }

    function overrideMessage() {
      var message = "Inner";
      return message;
    }

    expect(getMessage()).toBe(FILL_ME_IN);
    expect(overrideMessage()).toBe(FILL_ME_IN);
    expect(message).toBe(FILL_ME_IN);
  });

  it("should have lexical scoping", function () {
    var variable = "top-level";
    function parentfunction() {
        var variable = "local";
      function childfunction() {
          return variable;
      }
      return childfunction();
    }
    expect(parentfunction()).toBe(FILL_ME_IN);
  });

  it("should use lexical scoping to synthesise functions", function () {

    function makeIncreaseByFunction(increaseByAmount) {
      return function (numberToIncrease) {
        return numberToIncrease + increaseByAmount;
      };
    }

    var increaseBy3 = makeIncreaseByFunction(3);
    var increaseBy5 = makeIncreaseByFunction(5);

    expect(increaseBy3(10) + increaseBy5(10)).toBe(FILL_ME_IN);
  });

  it("should allow extra function arguments", function () {

    function returnFirstArg(firstArg) {
      return firstArg;
    }

    expect(returnFirstArg("first", "second", "third")).toBe(FILL_ME_IN);

    function returnSecondArg(firstArg, secondArg) {
      return secondArg;
    }

    expect(returnSecondArg("only give first arg")).toBe(FILL_ME_IN);

    function returnAllArgs() {
      var argsArray = [];
      for (var i = 0; i < arguments.length; i += 1) {
        argsArray.push(arguments[i]);
      }
      return argsArray.join(",");
    }

    expect(returnAllArgs("first", "second", "third")).toBe(FILL_ME_IN);
  });

  it("should pass functions as values", function () {

    var appendRules = function (name) {
      return name + " rules!";
    };

    var appendDoubleRules = function (name) {
      return name + " totally rules!";
    };

    var praiseSinger = { givePraise: appendRules };
    expect(praiseSinger.givePraise("John")).toBe(FILL_ME_IN);

    praiseSinger.givePraise = appendDoubleRules;
    expect(praiseSinger.givePraise("Mary")).toBe(FILL_ME_IN);

  });

  it("should use function body as a string", function () {
    var add = new Function("a", "b", "return a + b;");
    expect(add(1, 2)).toBe(FILL_ME_IN);

    var multiply = function (a, b) {
      //An internal comment
      return a * b;
    };
    expect(multiply.toString()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Finished "About Functions" koans<commit_after>describe("About Functions", function() {

  it("should declare functions", function() {

    function add(a, b) {
      return a + b;
    }

    expect(add(1, 2)).toBe(3);
  });

  it("should know internal variables override outer variables", function () {
    var message = "Outer";

    function getMessage() {
      return message;
    }

    function overrideMessage() {
      var message = "Inner";
      return message;
    }

    expect(getMessage()).toBe("Outer");
    expect(overrideMessage()).toBe("Inner");
    expect(message).toBe("Outer");
  });

  it("should have lexical scoping", function () {
    var variable = "top-level";
    function parentfunction() {
        var variable = "local";
      function childfunction() {
          return variable;
      }
      return childfunction();
    }
    expect(parentfunction()).toBe("local");
  });

  it("should use lexical scoping to synthesise functions", function () {

    function makeIncreaseByFunction(increaseByAmount) {
      return function (numberToIncrease) {
        return numberToIncrease + increaseByAmount;
      };
    }

    var increaseBy3 = makeIncreaseByFunction(3);
    var increaseBy5 = makeIncreaseByFunction(5);

    expect(increaseBy3(10) + increaseBy5(10)).toBe(28);
  });

  it("should allow extra function arguments", function () {

    function returnFirstArg(firstArg) {
      return firstArg;
    }

    expect(returnFirstArg("first", "second", "third")).toBe("first");

    function returnSecondArg(firstArg, secondArg) {
      return secondArg;
    }

    expect(returnSecondArg("only give first arg")).toBe(undefined);

    function returnAllArgs() {
      var argsArray = [];
      for (var i = 0; i < arguments.length; i += 1) {
        argsArray.push(arguments[i]);
      }
      return argsArray.join(",");
    }

    expect(returnAllArgs("first", "second", "third")).toBe("first,second,third");
  });

  it("should pass functions as values", function () {

    var appendRules = function (name) {
      return name + " rules!";
    };

    var appendDoubleRules = function (name) {
      return name + " totally rules!";
    };

    var praiseSinger = { givePraise: appendRules };
    expect(praiseSinger.givePraise("John")).toBe("John rules!");

    praiseSinger.givePraise = appendDoubleRules;
    expect(praiseSinger.givePraise("Mary")).toBe("Mary totally rules!");

  });

  it("should use function body as a string", function () {
    var add = new Function("a", "b", "return a + b;");
    expect(add(1, 2)).toBe(3);

    var multiply = function (a, b) {
      //An internal comment
      return a * b;
    };
    expect(multiply.toString()).toBe("function (a, b) {\n"
    + "      //An internal comment\n"
    + "      return a * b;\n"
    + "    }");
  });
});
<|endoftext|>