<commit_before>// Dependencies
// ------------
var util = require('util');
var express = require('express');
var mongoose = require('mongoose');
var lingo = require('lingo');
var url = require('url');

var middleware = {
  configure: require('./middleware/configure'),
  documents: require('./middleware/documents'),
  exec: require('./middleware/exec'),
  headers: require('./middleware/headers'),
  query: require('./middleware/query')
};

// Private Static Members
// ----------------------

// Create a data structure to store user-defined middleware
function createEmptyMiddlewareHash () {
  var o = {};

  ['request', 'query', 'documents'].forEach(function (stage) {
    o[stage] = {};
    ['instance', 'collection'].forEach(function (howMany) {
      o[stage][howMany] = {};
      ['head', 'get', 'post', 'put', 'del'].forEach(function (verb) {
        o[stage][howMany][verb] = [];
      });
    });
  });

  return o;
}

// Cascade optional paramaters into a single hash
function cascadeArguments (stage, howMany, verbs, middleware) {
  if (!stage) throw new Error('Must supply stage.');
  if (!middleware && !verbs && !howMany) throw new Error('Too few arguments.');

  if (!middleware && !verbs) {
    middleware = howMany;
    verbs = undefined;
    howMany = undefined;
  }

  if (!middleware) {
    middleware = verbs;
    verbs = howMany;
    howMany = undefined;
  }

  if (middleware.verbs) middleware.verbs = middleware.verbs.toLowerCase();

  return { stage: stage, howMany: howMany, verbs: verbs, middleware: middleware };
}

// Module Definition
var Controller = module.exports = function (options) {
  // Marshal string into a hash
  if (typeof options === 'string') options = { singular: options };

  // Validate singular & basePath
  if (!options.singular) throw new Error('Must provide the Mongoose schema name');
  if (options.basePath) {
    if (options.basePath.indexOf('/') !== 0) throw new Error('basePath must start with a "/"');
    if (options.basePath.lastIndexOf('/') === options.basePath.length - 1) throw new Error('basePath must not end with a "/"');
  }

  // *Private Instance Members*
  var controller = express();
  var initialized = false;
  var model = mongoose.model(options.singular);
  var userMiddlewareFor = createEmptyMiddlewareHash();
  var basePath = options.basePath ? options.basePath : '/';
  var separator = (basePath === '/' ? '' : '/');
  var basePathWithId = basePath + separator + ':id';
  var basePathWithOptionalId = basePath + separator + ':id?';

  // Validate findBy
  if (options.findBy && !model.schema.path(options.findBy).options.unique) {
    throw new Error('findBy path for ' + options.singular + ' not unique');
  }

  // *Private Instance Methods*
  // Parse the options hash and recurse `f` with parsed paramaters.  Execute `g`
  // for each verb.
  function traverseMiddleware (options, f, g) {
    if (!options.stage) throw new Error('Must supply stage.');
    if (!options.middleware) throw new Error('Must supply middleware.');

    var verbs = options.verbs || 'head get post put del';

    if (!Array.isArray(options.middleware) && typeof options.middleware !== 'function') {
      Object.keys(options.middleware).forEach(function (howManyKey) {
        Object.keys(options.middleware[howManyKey]).forEach(function (verb) {
          f({
            stage: options.stage,
            howMany: howManyKey,
            verbs: verb,
            middleware: options.middleware[howManyKey][verb]
          });
        });
      });
      return;
    }

    verbs.split(' ').forEach(g);
  }

  // Register user middleware to be activated later
  function registerMiddleware (options) {
    if (initialized) {
      throw new Error("Can't add middleware after the controller has been initialized.");
    }

    if (options.verbs && options.verbs.indexOf('post') !== -1) {
      throw new Error('Query stage not executed for POST.');
    }

    traverseMiddleware(options, registerMiddleware, function (verb) {
      if (controller.get(verb) === false) return;

      if (options.howMany !== 'collection') {
        userMiddlewareFor[options.stage]['instance'][verb] = userMiddlewareFor[options.stage]['instance'][verb].concat(options.middleware);
      }
      if (options.howMany !== 'instance') {
        userMiddlewareFor[options.stage]['collection'][verb] = userMiddlewareFor[options.stage]['collection'][verb].concat(options.middleware);
      }
    });
  }

  // Activate user middleware that was registered previously
  function activateMiddleware (options) {
    if (initialized) throw new Error("Can't activate middleware after the controller has been initialized.");

    traverseMiddleware(options, activateMiddleware, function (verb) {
      if (controller.get(verb) === false) return;

      var path;

      if (!options.howMany) path = controller.get('basePathWithOptionalId');
      else if (options.howMany === 'instance') path = controller.get('basePathWithId');
      else if (options.howMany === 'collection') path = controller.get('basePath');
      else throw new Error('Unrecognized howMany.');

      controller[verb](path, options.middleware);
    });
  }

  // Public Methods
  // --------------
  controller.request = function (howMany, verbs, middleware) {
    var cascaded = cascadeArguments('request', howMany, verbs, middleware);
    registerMiddleware(cascaded);
    return controller;
  };

  controller.query = function (howMany, verbs, middleware) {
    var cascaded = cascadeArguments('query', howMany, verbs, middleware);
    // Prevent explicitly setting query:post middleware.  Implicitly adding
    // query:post middleware is ignored.
    if (cascaded.verbs && cascaded.verbs.indexOf('post') !== -1) {
      throw new Error('POST cannot have query middleware');
    }
    registerMiddleware(cascaded);
    return controller;
  };

  controller.documents = function (howMany, verbs, middleware) {
    var cascaded = cascadeArguments('documents', howMany, verbs, middleware);
    registerMiddleware(cascaded);
    return controller;
  };

  controller.initialize = function () {
    if (initialized) return controller;

    // Allow/Accept headers
    activateMiddleware({
      stage: 'request',
      middleware: [ middleware.headers.allow, middleware.headers.accept ]
    });

    // Process the request before building the query.
    activateMiddleware({
      stage: 'request',
      howMany: 'collection',
      verbs: 'head get del',
      middleware: middleware.configure.conditions
    });
    activateMiddleware({
       stage: 'request',
       middleware: userMiddlewareFor['request']
    });
    activateMiddleware({
      stage: 'request',
      middleware: middleware.query
    });

    // Query has been created (except for POST)
    activateMiddleware({
      stage: 'query',
      middleware: [ middleware.configure.controller, middleware.configure.query ]
    });

    // Delete any POST-stage query middleware that was added implicitly
    delete userMiddlewareFor['query']['instance']['post'];
    delete userMiddlewareFor['query']['collection']['post'];

    activateMiddleware({
      stage: 'query',
      verbs: 'head get put del',
      middleware: userMiddlewareFor['query']
    });
    activateMiddleware({
      stage: 'query',
      verbs: 'head',
      middleware: middleware.exec.count
    });
    activateMiddleware({
      stage: 'query',
      verbs: 'get del',
      middleware: middleware.exec.exec
    });
    activateMiddleware({
      stage: 'query',
      howMany: 'collection',
      verbs: 'post',
      middleware: middleware.exec.create
    });
    activateMiddleware({
      stage: 'query',
      howMany: 'instance',
      verbs: 'put',
      middleware: middleware.exec.update
    });

    // Set Link header if desired (must come after exec or else query gets count)
    if (this.get('relations') === true) {
      activateMiddleware({
        stage: 'query',
        howMany: 'instance',
        middleware: middleware.headers.link
      });
      activateMiddleware({
        stage: 'query',
        howMany: 'collection',
        middleware: middleware.headers.linkCollection
      });
    }

    // Documents/count have/has been created
    activateMiddleware({
      stage: 'documents',
      middleware: middleware.documents.lastModified
    });
    activateMiddleware({
      stage: 'documents',
      middleware: userMiddlewareFor['documents']
    });
    activateMiddleware({
      stage: 'documents',
      middleware: middleware.documents.send
    });

    // The controller is initialized and we don't need the intermiediate data
    // structure any more.
    delete userMiddlewareFor;
    initialized = true;

    return controller;
  };

  // Configuration
  // -------------
  Object.keys(options).forEach(function (key) {
    controller.set(key, options[key]);
  });

  controller.set('model', model);
  controller.set('plural', options.plural || lingo.en.pluralize(options.singular));
  controller.set('findBy', options.findBy || '_id');

  controller.set('basePath', basePath);
  controller.set('basePathWithId', basePathWithId);
  controller.set('basePathWithOptionalId', basePathWithOptionalId);

  // Basic middleware
  // Middleware for parsing JSON requests
  controller.use(express.json());

  // Initialize baucis state
  controller.use(function (request, response, next) {
    request.baucis = {};
    next();
  });

  return controller;
};

util.inherits(Controller, express);
<commit_msg>Fixes #43 Check stage when preventing POST middleware registration for query stage<commit_after>// Dependencies
// ------------
var util = require('util');
var express = require('express');
var mongoose = require('mongoose');
var lingo = require('lingo');
var url = require('url');

var middleware = {
  configure: require('./middleware/configure'),
  documents: require('./middleware/documents'),
  exec: require('./middleware/exec'),
  headers: require('./middleware/headers'),
  query: require('./middleware/query')
};

// Private Static Members
// ----------------------

// Create a data structure to store user-defined middleware
function createEmptyMiddlewareHash () {
  var o = {};

  ['request', 'query', 'documents'].forEach(function (stage) {
    o[stage] = {};
    ['instance', 'collection'].forEach(function (howMany) {
      o[stage][howMany] = {};
      ['head', 'get', 'post', 'put', 'del'].forEach(function (verb) {
        o[stage][howMany][verb] = [];
      });
    });
  });

  return o;
}

// Cascade optional paramaters into a single hash
function cascadeArguments (stage, howMany, verbs, middleware) {
  if (!stage) throw new Error('Must supply stage.');
  if (!middleware && !verbs && !howMany) throw new Error('Too few arguments.');

  if (!middleware && !verbs) {
    middleware = howMany;
    verbs = undefined;
    howMany = undefined;
  }

  if (!middleware) {
    middleware = verbs;
    verbs = howMany;
    howMany = undefined;
  }

  if (middleware.verbs) middleware.verbs = middleware.verbs.toLowerCase();

  return { stage: stage, howMany: howMany, verbs: verbs, middleware: middleware };
}

// Module Definition
var Controller = module.exports = function (options) {
  // Marshal string into a hash
  if (typeof options === 'string') options = { singular: options };

  // Validate singular & basePath
  if (!options.singular) throw new Error('Must provide the Mongoose schema name');
  if (options.basePath) {
    if (options.basePath.indexOf('/') !== 0) throw new Error('basePath must start with a "/"');
    if (options.basePath.lastIndexOf('/') === options.basePath.length - 1) throw new Error('basePath must not end with a "/"');
  }

  // *Private Instance Members*
  var controller = express();
  var initialized = false;
  var model = mongoose.model(options.singular);
  var userMiddlewareFor = createEmptyMiddlewareHash();
  var basePath = options.basePath ? options.basePath : '/';
  var separator = (basePath === '/' ? '' : '/');
  var basePathWithId = basePath + separator + ':id';
  var basePathWithOptionalId = basePath + separator + ':id?';

  // Validate findBy
  if (options.findBy && !model.schema.path(options.findBy).options.unique) {
    throw new Error('findBy path for ' + options.singular + ' not unique');
  }

  // *Private Instance Methods*
  // Parse the options hash and recurse `f` with parsed paramaters.  Execute `g`
  // for each verb.
  function traverseMiddleware (options, f, g) {
    if (!options.stage) throw new Error('Must supply stage.');
    if (!options.middleware) throw new Error('Must supply middleware.');

    var verbs = options.verbs || 'head get post put del';

    if (!Array.isArray(options.middleware) && typeof options.middleware !== 'function') {
      Object.keys(options.middleware).forEach(function (howManyKey) {
        Object.keys(options.middleware[howManyKey]).forEach(function (verb) {
          f({
            stage: options.stage,
            howMany: howManyKey,
            verbs: verb,
            middleware: options.middleware[howManyKey][verb]
          });
        });
      });
      return;
    }

    verbs.split(' ').forEach(g);
  }

  // Register user middleware to be activated later
  function registerMiddleware (options) {
    if (initialized) {
      throw new Error("Can't add middleware after the controller has been initialized.");
    }

    if (options.stage === 'query' && options.verbs && options.verbs.indexOf('post') !== -1) {
      throw new Error('Query stage not executed for POST.');
    }

    traverseMiddleware(options, registerMiddleware, function (verb) {
      if (controller.get(verb) === false) return;

      if (options.howMany !== 'collection') {
        userMiddlewareFor[options.stage]['instance'][verb] = userMiddlewareFor[options.stage]['instance'][verb].concat(options.middleware);
      }
      if (options.howMany !== 'instance') {
        userMiddlewareFor[options.stage]['collection'][verb] = userMiddlewareFor[options.stage]['collection'][verb].concat(options.middleware);
      }
    });
  }

  // Activate user middleware that was registered previously
  function activateMiddleware (options) {
    if (initialized) throw new Error("Can't activate middleware after the controller has been initialized.");

    traverseMiddleware(options, activateMiddleware, function (verb) {
      if (controller.get(verb) === false) return;

      var path;

      if (!options.howMany) path = controller.get('basePathWithOptionalId');
      else if (options.howMany === 'instance') path = controller.get('basePathWithId');
      else if (options.howMany === 'collection') path = controller.get('basePath');
      else throw new Error('Unrecognized howMany.');

      controller[verb](path, options.middleware);
    });
  }

  // Public Methods
  // --------------
  controller.request = function (howMany, verbs, middleware) {
    var cascaded = cascadeArguments('request', howMany, verbs, middleware);
    registerMiddleware(cascaded);
    return controller;
  };

  controller.query = function (howMany, verbs, middleware) {
    var cascaded = cascadeArguments('query', howMany, verbs, middleware);
    // Prevent explicitly setting query:post middleware.  Implicitly adding
    // query:post middleware is ignored.
    if (cascaded.verbs && cascaded.verbs.indexOf('post') !== -1) {
      throw new Error('POST cannot have query middleware');
    }
    registerMiddleware(cascaded);
    return controller;
  };

  controller.documents = function (howMany, verbs, middleware) {
    var cascaded = cascadeArguments('documents', howMany, verbs, middleware);
    registerMiddleware(cascaded);
    return controller;
  };

  controller.initialize = function () {
    if (initialized) return controller;

    // Allow/Accept headers
    activateMiddleware({
      stage: 'request',
      middleware: [ middleware.headers.allow, middleware.headers.accept ]
    });

    // Process the request before building the query.
    activateMiddleware({
      stage: 'request',
      howMany: 'collection',
      verbs: 'head get del',
      middleware: middleware.configure.conditions
    });
    activateMiddleware({
       stage: 'request',
       middleware: userMiddlewareFor['request']
    });
    activateMiddleware({
      stage: 'request',
      middleware: middleware.query
    });

    // Query has been created (except for POST)
    activateMiddleware({
      stage: 'query',
      middleware: [ middleware.configure.controller, middleware.configure.query ]
    });

    // Delete any POST-stage query middleware that was added implicitly
    delete userMiddlewareFor['query']['instance']['post'];
    delete userMiddlewareFor['query']['collection']['post'];

    activateMiddleware({
      stage: 'query',
      verbs: 'head get put del',
      middleware: userMiddlewareFor['query']
    });
    activateMiddleware({
      stage: 'query',
      verbs: 'head',
      middleware: middleware.exec.count
    });
    activateMiddleware({
      stage: 'query',
      verbs: 'get del',
      middleware: middleware.exec.exec
    });
    activateMiddleware({
      stage: 'query',
      howMany: 'collection',
      verbs: 'post',
      middleware: middleware.exec.create
    });
    activateMiddleware({
      stage: 'query',
      howMany: 'instance',
      verbs: 'put',
      middleware: middleware.exec.update
    });

    // Set Link header if desired (must come after exec or else query gets count)
    if (this.get('relations') === true) {
      activateMiddleware({
        stage: 'query',
        howMany: 'instance',
        middleware: middleware.headers.link
      });
      activateMiddleware({
        stage: 'query',
        howMany: 'collection',
        middleware: middleware.headers.linkCollection
      });
    }

    // Documents/count have/has been created
    activateMiddleware({
      stage: 'documents',
      middleware: middleware.documents.lastModified
    });
    activateMiddleware({
      stage: 'documents',
      middleware: userMiddlewareFor['documents']
    });
    activateMiddleware({
      stage: 'documents',
      middleware: middleware.documents.send
    });

    // The controller is initialized and we don't need the intermiediate data
    // structure any more.
    delete userMiddlewareFor;
    initialized = true;

    return controller;
  };

  // Configuration
  // -------------
  Object.keys(options).forEach(function (key) {
    controller.set(key, options[key]);
  });

  controller.set('model', model);
  controller.set('plural', options.plural || lingo.en.pluralize(options.singular));
  controller.set('findBy', options.findBy || '_id');

  controller.set('basePath', basePath);
  controller.set('basePathWithId', basePathWithId);
  controller.set('basePathWithOptionalId', basePathWithOptionalId);

  // Basic middleware
  // Middleware for parsing JSON requests
  controller.use(express.json());

  // Initialize baucis state
  controller.use(function (request, response, next) {
    request.baucis = {};
    next();
  });

  return controller;
};

util.inherits(Controller, express);
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var filesize = require('filesize');

import MFileBody from './MFileBody';

var MatrixClientPeg = require('../../../MatrixClientPeg');
var ImageUtils = require('../../../ImageUtils');
var Modal = require('../../../Modal');
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
var DecryptFile = require('../../../utils/DecryptFile');

module.exports = React.createClass({
    displayName: 'MImageBody',

    propTypes: {
        /* the MatrixEvent to show */
        mxEvent: React.PropTypes.object.isRequired,
    },

    getInitialState: function() {
        return {
            decryptedUrl: null,
        };
    },

    onClick: function onClick(ev) {
        if (ev.button == 0 && !ev.metaKey) {
            ev.preventDefault();
            var content = this.props.mxEvent.getContent();
            var httpUrl = this._getContentUrl();
            var ImageView = sdk.getComponent("elements.ImageView");
            var params = {
                src: httpUrl,
                mxEvent: this.props.mxEvent
            };

            if (content.info) {
                params.width = content.info.w;
                params.height = content.info.h;
                params.fileSize = content.info.size;
            }

            Modal.createDialog(ImageView, params, "mx_Dialog_lightbox");
        }
    },

    _isGif: function() {
        var content = this.props.mxEvent.getContent();
        return (content && content.info && content.info.mimetype === "image/gif");
    },

    onImageEnter: function(e) {
        if (!this._isGif()) {
            return;
        }
        var imgElement = e.target;
        imgElement.src = MatrixClientPeg.get().mxcUrlToHttp(
            this.props.mxEvent.getContent().url
        );
    },

    onImageLeave: function(e) {
        if (!this._isGif()) {
            return;
        }
        var imgElement = e.target;
        imgElement.src = this._getThumbUrl();
    },

    _getContentUrl: function() {
        var content = this.props.mxEvent.getContent();
        if (content.file !== undefined) {
            return this.state.decryptedUrl;
        } else {
            return MatrixClientPeg.get().mxcUrlToHttp(content.url);
        }
    },

    _getThumbUrl: function() {
        var content = this.props.mxEvent.getContent();
        if (content.file !== undefined) {
            // TODO: Decrypt and use the thumbnail file if one is present.
            return this.state.decryptedUrl;
        } else {
            return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600);
        }
    },

    componentDidMount: function() {
        this.dispatcherRef = dis.register(this.onAction);
        this.fixupHeight();
        var content = this.props.mxEvent.getContent();
        var self = this;
        if (content.file !== undefined && this.state.decryptedUrl === null) {
            DecryptFile.decryptFile(content.file).then(function(url) {
                self.setState({
                    decryptedUrl: url,
                });
            }).catch(function (err) {
                console.warn("Unable to decrypt attachment: ", err)
                // Set a placeholder image when we can't decrypt the image.
                self.refs.image.src = "img/warning.svg";
            });
        }
    },

    componentWillUnmount: function() {
        dis.unregister(this.dispatcherRef);
    },

    onAction: function(payload) {
        if (payload.action === "timeline_resize") {
            this.fixupHeight();
        }
    },

    fixupHeight: function() {
        if (!this.refs.image) {
            console.warn("Refusing to fix up height on MImageBody with no image element");
            return;
        }

        var content = this.props.mxEvent.getContent();

        var thumbHeight = null;
        var timelineWidth = this.refs.body.offsetWidth;
        var maxHeight = 600; // let images take up as much width as they can so long as the height doesn't exceed 600px.
        // the alternative here would be 600*timelineWidth/800; to scale them down to fit inside a 4:3 bounding box

        //console.log("trying to fit image into timelineWidth of " + this.refs.body.offsetWidth + " or " + this.refs.body.clientWidth);
        if (content.info) {
            thumbHeight = ImageUtils.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight);
        }
        this.refs.image.style.height = thumbHeight + "px";
        // console.log("Image height now", thumbHeight);
    },

    render: function() {
        var TintableSvg = sdk.getComponent("elements.TintableSvg");
        var content = this.props.mxEvent.getContent();

        if (content.file !== undefined && this.state.decryptedUrl === null) {

            // Need to decrypt the attachment
            // The attachment is decrypted in componentDidMount.
            // For now add an img tag with a spinner.
            return (

            );
        }

        var contentUrl = this._getContentUrl();
        var thumbUrl = this._getThumbUrl();

        if (thumbUrl) {
            return (

                    <MFileBody {...this.props} decryptedUrl={this.state.decryptedUrl} />

            );
        } else if (content.body) {
            return (

                    Image '{content.body}' cannot be displayed.

            );
        } else {
            return (

                    This image cannot be displayed.

            );
        }
    },
});
<commit_msg>Fix gif hoverover<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var filesize = require('filesize');

import MFileBody from './MFileBody';

var MatrixClientPeg = require('../../../MatrixClientPeg');
var ImageUtils = require('../../../ImageUtils');
var Modal = require('../../../Modal');
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
var DecryptFile = require('../../../utils/DecryptFile');

module.exports = React.createClass({
    displayName: 'MImageBody',

    propTypes: {
        /* the MatrixEvent to show */
        mxEvent: React.PropTypes.object.isRequired,
    },

    getInitialState: function() {
        return {
            decryptedUrl: null,
        };
    },

    onClick: function onClick(ev) {
        if (ev.button == 0 && !ev.metaKey) {
            ev.preventDefault();
            var content = this.props.mxEvent.getContent();
            var httpUrl = this._getContentUrl();
            var ImageView = sdk.getComponent("elements.ImageView");
            var params = {
                src: httpUrl,
                mxEvent: this.props.mxEvent
            };

            if (content.info) {
                params.width = content.info.w;
                params.height = content.info.h;
                params.fileSize = content.info.size;
            }

            Modal.createDialog(ImageView, params, "mx_Dialog_lightbox");
        }
    },

    _isGif: function() {
        var content = this.props.mxEvent.getContent();
        return (content && content.info && content.info.mimetype === "image/gif");
    },

    onImageEnter: function(e) {
        if (!this._isGif()) {
            return;
        }
        var imgElement = e.target;
        imgElement.src = this._getContentUrl();
    },

    onImageLeave: function(e) {
        if (!this._isGif()) {
            return;
        }
        var imgElement = e.target;
        imgElement.src = this._getThumbUrl();
    },

    _getContentUrl: function() {
        var content = this.props.mxEvent.getContent();
        if (content.file !== undefined) {
            return this.state.decryptedUrl;
        } else {
            return MatrixClientPeg.get().mxcUrlToHttp(content.url);
        }
    },

    _getThumbUrl: function() {
        var content = this.props.mxEvent.getContent();
        if (content.file !== undefined) {
            // TODO: Decrypt and use the thumbnail file if one is present.
            return this.state.decryptedUrl;
        } else {
            return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600);
        }
    },

    componentDidMount: function() {
        this.dispatcherRef = dis.register(this.onAction);
        this.fixupHeight();
        var content = this.props.mxEvent.getContent();
        var self = this;
        if (content.file !== undefined && this.state.decryptedUrl === null) {
            DecryptFile.decryptFile(content.file).then(function(url) {
                self.setState({
                    decryptedUrl: url,
                });
            }).catch(function (err) {
                console.warn("Unable to decrypt attachment: ", err)
                // Set a placeholder image when we can't decrypt the image.
                self.refs.image.src = "img/warning.svg";
            });
        }
    },

    componentWillUnmount: function() {
        dis.unregister(this.dispatcherRef);
    },

    onAction: function(payload) {
        if (payload.action === "timeline_resize") {
            this.fixupHeight();
        }
    },

    fixupHeight: function() {
        if (!this.refs.image) {
            console.warn("Refusing to fix up height on MImageBody with no image element");
            return;
        }

        var content = this.props.mxEvent.getContent();

        var thumbHeight = null;
        var timelineWidth = this.refs.body.offsetWidth;
        var maxHeight = 600; // let images take up as much width as they can so long as the height doesn't exceed 600px.
        // the alternative here would be 600*timelineWidth/800; to scale them down to fit inside a 4:3 bounding box

        //console.log("trying to fit image into timelineWidth of " + this.refs.body.offsetWidth + " or " + this.refs.body.clientWidth);
        if (content.info) {
            thumbHeight = ImageUtils.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight);
        }
        this.refs.image.style.height = thumbHeight + "px";
        // console.log("Image height now", thumbHeight);
    },

    render: function() {
        var TintableSvg = sdk.getComponent("elements.TintableSvg");
        var content = this.props.mxEvent.getContent();

        if (content.file !== undefined && this.state.decryptedUrl === null) {

            // Need to decrypt the attachment
            // The attachment is decrypted in componentDidMount.
            // For now add an img tag with a spinner.
            return (

            );
        }

        var contentUrl = this._getContentUrl();
        var thumbUrl = this._getThumbUrl();

        if (thumbUrl) {
            return (

                    <MFileBody {...this.props} decryptedUrl={this.state.decryptedUrl} />

            );
        } else if (content.body) {
            return (

                    Image '{content.body}' cannot be displayed.

            );
        } else {
            return (

                    This image cannot be displayed.

            );
        }
    },
});
<|endoftext|>


<commit_before>/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var _ = require('underscore');
var fs = require('fs');
var util = require('util');

var sinon = require('sinon');

var log = require('../../lib/util/logging');
var profile = require('../../lib/util/profile');
var utils = require('../../lib/util/utils');
var CLITest = require('./cli-test');

function CSMCLITest(testPrefix, forceMocked) {
  CSMCLITest['super_'].call(this, testPrefix, forceMocked);
}

util.inherits(CSMCLITest, CLITest);

_.extend(CSMCLITest.prototype, {
  setupSuite: function (callback) {
    if (this.isMocked) {
      process.env.AZURE_ENABLE_STRICT_SSL = false;

      CLITest.wrap(sinon, profile, 'load', function(originalLoad) {
        return function (filenameOrData) {
          if (!fileNameOrData || fileNameOrData == profile.defaultProfileFile) {
            return originalProfileLoad(JSON.parse(createMockedSubscriptionFile()));
          }
          return originalLoad(filenameOrData);
        };
      });

      CLITest.wrap(sinon, utils, 'readConfig', function (originalReadConfig) {
        return function () {
          var config = originalReadConfig();
          config.mode = 'csm';
          return config;
        };
      });
    }

    if (this.isRecording) {
      fs.writeFileSync(this.recordingsFile,
        '// This file has been autogenerated.\n\n' +
        'exports.scopes = [');
    }

    this.removeCacheFiles();
    profile.current = profile.load();
    this.doLogin(callback);
  },

  teardownSuite: function (callback) {
    this.currentTest = 0;
    if (this.isMocked) {
      if (this.isRecording) {
        fs.appendFIleSync(this.recordingsFile, '];');
      }

      if (profile.load.restore) {
        profile.load.restore();
      }

      if (utils.readConfig.restore) {
        utils.readConfig.restore();
      }

      delete process.env.AZURE_ENABLE_STRICT_SSL;
    }
    callback();
  },

  doLogin: function (callback) {
    var requiredVars = [
      'AZURE_CSM_TEST_ENVIRONMENT',
      'AZURE_CSM_TEST_USERNAME',
      'AZURE_CSM_TEST_PASSWORD',
      'AZURE_CSM_TEST_SUBSCRIPTIONID'
    ];

    var missingVars = requiredVars.filter(function (v) { return !process.env[v]; });
    if (missingVars.length !== 0) {
      var error = 'Missing environment variables: ' + missingVars.join(', ');
      log.error(error);
      throw new Error(error);
    }

    var env = profile.current.getEnvironment(process.env['AZURE_CSM_TEST_ENVIRONMENT']);
    env.addAccount(
      process.env['AZURE_CSM_TEST_USERNAME'],
      process.env['AZURE_CSM_TEST_PASSWORD'],
      null,
      function (err, newSubscription) {
        if (err) { return callback(err); }

        newSubscription.id = process.env['AZURE_CSM_TEST_SUBSCRIPTIONID'];
        newSubscription.name = 'xplat-test-subscription';
        newSubscription.isDefault = true;
        profile.current.addSubscription(newSubscription);
        profile.current.save();

        callback();
      });
  }
});

function createMockedSubscriptionFile () {
  return {
    environments: [
      {
        "name": "next",
        "publishingProfileUrl": "https://auxnext.windows.azure-test.net/publishsettings/index",
        "portalUrl": "https://auxnext.windows.azure-test.net",
        "managementEndpointUrl": "https://managementnext.rdfetest.dnsdemo4.com",
        "resourceManagementEndpointUrl": "https://api-next.resources.windows-int.net",
        "activeDirectoryEndpointUrl": "https://login.windows-ppe.net",
        "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
        "hostNameSuffix": "azurewebsites.net",
        "commonTenantName": "common"
      }
    ],

    subscriptions: [
    ],
  };
}

module.exports = CSMCLITest;
<commit_msg>Fixed issue in tests due to removal of explicit subscription id<commit_after>/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var _ = require('underscore');
var fs = require('fs');
var util = require('util');

var sinon = require('sinon');

var log = require('../../lib/util/logging');
var profile = require('../../lib/util/profile');
var utils = require('../../lib/util/utils');
var CLITest = require('./cli-test');

function CSMCLITest(testPrefix, forceMocked) {
  CSMCLITest['super_'].call(this, testPrefix, forceMocked);
}

util.inherits(CSMCLITest, CLITest);

_.extend(CSMCLITest.prototype, {
  setupSuite: function (callback) {
    if (this.isMocked) {
      process.env.AZURE_ENABLE_STRICT_SSL = false;

      CLITest.wrap(sinon, profile, 'load', function(originalLoad) {
        return function (filenameOrData) {
          if (!fileNameOrData || fileNameOrData == profile.defaultProfileFile) {
            return originalProfileLoad(JSON.parse(createMockedSubscriptionFile()));
          }
          return originalLoad(filenameOrData);
        };
      });

      CLITest.wrap(sinon, utils, 'readConfig', function (originalReadConfig) {
        return function () {
          var config = originalReadConfig();
          config.mode = 'csm';
          return config;
        };
      });
    }

    if (this.isRecording) {
      fs.writeFileSync(this.recordingsFile,
        '// This file has been autogenerated.\n\n' +
        'exports.scopes = [');
    }

    this.removeCacheFiles();
    profile.current = profile.load();
    this.doLogin(callback);
  },

  teardownSuite: function (callback) {
    this.currentTest = 0;
    if (this.isMocked) {
      if (this.isRecording) {
        fs.appendFIleSync(this.recordingsFile, '];');
      }

      if (profile.load.restore) {
        profile.load.restore();
      }

      if (utils.readConfig.restore) {
        utils.readConfig.restore();
      }

      delete process.env.AZURE_ENABLE_STRICT_SSL;
    }
    callback();
  },

  doLogin: function (callback) {
    var requiredVars = [
      'AZURE_CSM_TEST_ENVIRONMENT',
      'AZURE_CSM_TEST_USERNAME',
      'AZURE_CSM_TEST_PASSWORD'
    ];

    var missingVars = requiredVars.filter(function (v) { return !process.env[v]; });
    if (missingVars.length !== 0) {
      var error = 'Missing environment variables: ' + missingVars.join(', ');
      log.error(error);
      throw new Error(error);
    }

    var env = profile.current.getEnvironment(process.env['AZURE_CSM_TEST_ENVIRONMENT']);
    env.addAccount(
      process.env['AZURE_CSM_TEST_USERNAME'],
      process.env['AZURE_CSM_TEST_PASSWORD'],
      function (err, newSubscriptions) {
        if (err) { return callback(err); }

        newSubscriptions[0].isDefault = true;
        newSubscriptions.forEach(function (s) { profile.current.addSubscription(s); });
        profile.current.save();

        callback();
      });
  }
});

function createMockedSubscriptionFile () {
  return {
    environments: [
      {
        "name": "next",
        "publishingProfileUrl": "https://auxnext.windows.azure-test.net/publishsettings/index",
        "portalUrl": "https://auxnext.windows.azure-test.net",
        "managementEndpointUrl": "https://managementnext.rdfetest.dnsdemo4.com",
        "resourceManagementEndpointUrl": "https://api-next.resources.windows-int.net",
        "activeDirectoryEndpointUrl": "https://login.windows-ppe.net",
        "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
        "hostNameSuffix": "azurewebsites.net",
        "commonTenantName": "common"
      }
    ],

    subscriptions: [
    ],
  };
}

module.exports = CSMCLITest;
<|endoftext|>


<commit_before>import KBlock from './KBlock.vue'
import KDialog from './KDialog.vue'
import KModal from './KModal.vue'
import KScreen from './KScreen.vue'

export {
  KBlock,
  KDialog,
  KModal,
  KScreen
}
<commit_msg>Cleaned index.js<commit_after>import KBlock from './KBlock.vue'
import KModal from './KModal.vue'
import KScreen from './KScreen.vue'

export {
  KBlock,
  KModal,
  KScreen
}
<|endoftext|>


<commit_before>var Cookies = require('cookies');
var groupArray = require('group-array');
var User = require('../model/user');
var record = require('./record');

var divisions = ['Non Mortal','Gold','Silver','Bronze','Unranked'];
var badges = ['ten','ace','admin','top','par','bottom','record','god','bomb','noscore','blocked','thumbdown','flame','anchor','refresh'];

function authenticate(req, res, next) {
  if(req.path == '/login') return next();
  var cookies = new Cookies(req, res);
  var cookie = cookies.get('discgolfleague');

  try{
    user = JSON.parse(cookie);
  }catch(err){
    return res.render('pages/login');
  }
  if(user.name === undefined || user.secret === undefined) return res.render('pages/login');

  User.findOne({name: user.name, secret: user.secret}, 'name division position score hasPosted isAdmin history badges viewedNotice', function(err, user) {
    if(err) return next({status: 500, message: 'Unable to access database.'});
    if(user === null){
      return res.render('pages/login');
    }else{
      record.getRecords(function(err, records) {
        if(err) return next(err);
        if(user.viewedNotice) records['notice'] = null;
        calculateBadges(user, records['courseRecord']);
        user.lastLogin = new Date();
        user.viewedNotice = true;
        user.save(function(err) {
          if(err) return next({status: 500, message: 'Unable to access database.'});
          req.records = records;
          req.user = user;
          return next();
        });
      });
    }
  });
}

function calculateBadges(user, courseRecord) {
  if(user.isAdmin) user.badges.admin = 1;
  user.badges.record = (courseRecord!==undefined && Math.min.apply(null, user.history)<=courseRecord) ? 1 : 0;
  user.badges.ten = Math.floor(user.history.length/10);
}

function create(name, secret, callback) {
  var user = new User({
    name: name,
    secret: secret
  });
  user.save(function(err) {
    if(err) return callback({status: 500, message: 'Unable to access database.'});
    callback(null);
  });
}

function post(user, score, competitive, ace, callback) {
  score = Number(score);
  user.history.push(score);
  if(competitive && !user.hasPosted){
    user.score = score;
    user.hasPosted = true;
  }
  if(ace){
    user.badges.ace++;
  }
  if(score <= 0){
    user.badges.par++;
  }
  user.save(function(err) {
    if(err) return callback({status: 500, message: 'Unable to save score.'});
    record.setCourseRecord(score, function(err) {
      if(err) return callback(err);
      callback(null);
    });
  });
}

function resetViewedNotice(callback) {
  User.update({}, {viewedNotice: false}, {multi: true}, function(err) {
    if(err) return callback({status: 500, message: 'Unable to save score.'});
    callback(null);
  });
}

function playersByDivision(sort, courseRecord, callback) {
  if(sort!=='position' && sort!=='score') return callback({status: 400, message: 'Must sort by position or score.'});
  User.find({}, 'name division position score badges isAdmin history', function(err, users) {
    if(err) return callback({status: 500, message: 'Unable to access database.'});
    users.sort(function(a, b) {
      if(a[sort]===null && b[sort]===null) return a.position - b.position;
      else if(a[sort]===null) return 1;
      else if(b[sort]===null) return -1;
      else return a[sort] - b[sort];
    });
    users.forEach(function(user) {
      calculateBadges(user, courseRecord);
    });
    var players = groupArray(users, 'division');
    callback(null, players);
  });
}

function place(date, courseRecord, callback) {
  playersByDivision('score', courseRecord, function(err, players) {
    if(err) return callback(err);

    // Calculate new standings
    var worstScore = null;
    Object.keys(players).forEach(function(division) {
      var divisionIndex = Number(division);
      var nextDivision = String(divisionIndex+1);
      var player = players[division][players[division].length-1];
      if(player.score!==null && (worstScore===null || player.score>worstScore)) worstScore = player.score;
      if(players[nextDivision] === undefined) return;
      var challenger = players[nextDivision][0];

      if((challenger.score!==null && player.score===null) || challenger.score==player.score) player.badges.blocked++;

      if((challenger.score!==null && player.score===null) || challenger.score<player.score){
        players[division].pop();
        players[nextDivision].splice(0, 1);
        players[division].push(challenger);
        players[nextDivision].unshift(player);
      }

    });

    // Reset scores, save players
    var divisionBasePosition = 0;
    Object.keys(players).forEach(function(division) {
      var divisionIndex = Number(division);
      players[division].forEach(function(player, playerIndex) {
        player.division = divisionIndex;
        user.divHistory.push(divisionIndex);
        player.position = divisionBasePosition+playerIndex;
        if(player.score!==null && player.score===worstScore) player.badges.bomb++;
        if(player.score==null) player.badges.noscore++;
        if(divisionIndex === 0){
          player.badges.god++;
        }else if(divisionIndex===1 && playerIndex===0){
          player.badges.top++;
        }else if(divisionIndex===divisions.length-1 && playerIndex===players[division].length-1){
          player.badges.bottom++;
        }

        var divLength = divHistory.length;
        if(divLength < 3){
          return;
        }else if(user.divHistory[divLength-3] == user.divHistory[divLength-2] && user.divHistory[divLength-2] == user.divHistory[divLength.length-1]){
          player.badges.anchor++;
        }else if(user.divHistory[divLength-3] > user.divHistory[divLength-2] && user.divHistory[divLength-2] > user.divHistory[divLength.length-1]){
          player.badges.flame++;
        }else if(user.divHistory[divLength-3] < user.divHistory[divLength-2] && user.divHistory[divLength-2] < user.divHistory[divLength.length-1]){
          player.badges.thumbdown++;
        }else if(user.divHistory[divLength-3] == user.divHistory[divLength-1]){
          player.badges.refresh++;
        }

        player.score = null;
        player.hasPosted = false;
        player.save(function(err) {
          if(err) return callback({status: 500, message: 'Unable to save score.'});
        });
      });
      divisionBasePosition += players[division].length;
    });

    record.setEndDate(date, function(err) {
      if(err) return callback(err);
      return callback(null);
    });
  });
}

module.exports = {
  create,
  authenticate,
  divisions,
  badges,
  playersByDivision,
  post,
  place,
  resetViewedNotice
}
<commit_msg>Add Movement Badges<commit_after>var Cookies = require('cookies');
var groupArray = require('group-array');
var User = require('../model/user');
var record = require('./record');

var divisions = ['Non Mortal','Gold','Silver','Bronze','Unranked'];
var badges = ['ten','ace','admin','top','par','bottom','record','god','bomb','noscore','blocked','thumbdown','flame','anchor','refresh'];

function authenticate(req, res, next) {
  if(req.path == '/login') return next();
  var cookies = new Cookies(req, res);
  var cookie = cookies.get('discgolfleague');

  try{
    user = JSON.parse(cookie);
  }catch(err){
    return res.render('pages/login');
  }
  if(user.name === undefined || user.secret === undefined) return res.render('pages/login');

  User.findOne({name: user.name, secret: user.secret}, 'name division position score hasPosted isAdmin history badges viewedNotice', function(err, user) {
    if(err) return next({status: 500, message: 'Unable to access database.'});
    if(user === null){
      return res.render('pages/login');
    }else{
      record.getRecords(function(err, records) {
        if(err) return next(err);
        if(user.viewedNotice) records['notice'] = null;
        calculateBadges(user, records['courseRecord']);
        user.lastLogin = new Date();
        user.viewedNotice = true;
        user.save(function(err) {
          if(err) return next({status: 500, message: 'Unable to access database.'});
          req.records = records;
          req.user = user;
          return next();
        });
      });
    }
  });
}

function calculateBadges(user, courseRecord) {
  if(user.isAdmin) user.badges.admin = 1;
  user.badges.record = (courseRecord!==undefined && Math.min.apply(null, user.history)<=courseRecord) ? 1 : 0;
  user.badges.ten = Math.floor(user.history.length/10);
}

function create(name, secret, callback) {
  var user = new User({
    name: name,
    secret: secret
  });
  user.save(function(err) {
    if(err) return callback({status: 500, message: 'Unable to access database.'});
    callback(null);
  });
}

function post(user, score, competitive, ace, callback) {
  score = Number(score);
  user.history.push(score);
  if(competitive && !user.hasPosted){
    user.score = score;
    user.hasPosted = true;
  }
  if(ace){
    user.badges.ace++;
  }
  if(score <= 0){
    user.badges.par++;
  }
  user.save(function(err) {
    if(err) return callback({status: 500, message: 'Unable to save score.'});
    record.setCourseRecord(score, function(err) {
      if(err) return callback(err);
      callback(null);
    });
  });
}

function resetViewedNotice(callback) {
  User.update({}, {viewedNotice: false}, {multi: true}, function(err) {
    if(err) return callback({status: 500, message: 'Unable to save score.'});
    callback(null);
  });
}

function playersByDivision(sort, courseRecord, callback) {
  if(sort!=='position' && sort!=='score') return callback({status: 400, message: 'Must sort by position or score.'});
  User.find({}, 'name division position score badges isAdmin history', function(err, users) {
    if(err) return callback({status: 500, message: 'Unable to access database.'});
    users.sort(function(a, b) {
      if(a[sort]===null && b[sort]===null) return a.position - b.position;
      else if(a[sort]===null) return 1;
      else if(b[sort]===null) return -1;
      else return a[sort] - b[sort];
    });
    users.forEach(function(user) {
      calculateBadges(user, courseRecord);
    });
    var players = groupArray(users, 'division');
    callback(null, players);
  });
}

function place(date, courseRecord, callback) {
  playersByDivision('score', courseRecord, function(err, players) {
    if(err) return callback(err);

    // Calculate new standings
    var worstScore = null;
    Object.keys(players).forEach(function(division) {
      var divisionIndex = Number(division);
      var nextDivision = String(divisionIndex+1);
      var player = players[division][players[division].length-1];
      if(player.score!==null && (worstScore===null || player.score>worstScore)) worstScore = player.score;
      if(players[nextDivision] === undefined) return;
      var challenger = players[nextDivision][0];

      if(challenger.score==player.score) player.badges.blocked++;

      if((challenger.score!==null && player.score===null) || challenger.score<player.score){
        players[division].pop();
        players[nextDivision].splice(0, 1);
        players[division].push(challenger);
        players[nextDivision].unshift(player);
      }

    });

    // Reset scores, save players
    var divisionBasePosition = 0;
    Object.keys(players).forEach(function(division) {
      var divisionIndex = Number(division);
      players[division].forEach(function(player, playerIndex) {
        player.division = divisionIndex;
        user.divHistory.push(divisionIndex);
        player.position = divisionBasePosition+playerIndex;
        if(player.score!==null && player.score===worstScore) player.badges.bomb++;
        if(player.score==null) player.badges.noscore++;
        if(divisionIndex === 0){
          player.badges.god++;
        }else if(divisionIndex===1 && playerIndex===0){
          player.badges.top++;
        }else if(divisionIndex===divisions.length-1 && playerIndex===players[division].length-1){
          player.badges.bottom++;
        }

        var divLength = divHistory.length;
        if(divLength < 3){
          return;
        }else if(user.divHistory[divLength-3] == user.divHistory[divLength-2] && user.divHistory[divLength-2] == user.divHistory[divLength.length-1]){
          player.badges.anchor++;
        }else if(user.divHistory[divLength-3] > user.divHistory[divLength-2] && user.divHistory[divLength-2] > user.divHistory[divLength.length-1]){
          player.badges.flame++;
        }else if(user.divHistory[divLength-3] < user.divHistory[divLength-2] && user.divHistory[divLength-2] < user.divHistory[divLength.length-1]){
          player.badges.thumbdown++;
        }else if(user.divHistory[divLength-3] == user.divHistory[divLength-1]){
          player.badges.refresh++;
        }

        player.score = null;
        player.hasPosted = false;
        player.save(function(err) {
          if(err) return callback({status: 500, message: 'Unable to save score.'});
        });
      });
      divisionBasePosition += players[division].length;
    });

    record.setEndDate(date, function(err) {
      if(err) return callback(err);
      return callback(null);
    });
  });
}

module.exports = {
  create,
  authenticate,
  divisions,
  badges,
  playersByDivision,
  post,
  place,
  resetViewedNotice
}
<|endoftext|>


<commit_before>( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'logo', mw.KBaseComponent.extend({

		defaultConfig: {
			parent: "controlsContainer",
		 	order: 41,
		 	displayImportance: 'low',
		 	align: "right",
		 	cssClass: "kaltura-logo",
			href: 'http://www.kaltura.com',
			title: 'Kaltura',
			img: null
		},
		getComponent: function() {
			if( !this.$el ) {
				var $img = [];
				if( this.getConfig('img') ){
					$img = $( '<img />' )
								.attr({
									alt: this.getConfig('title'),
									src: this.getConfig('img')
								});
				}
				this.$el = $('<div />')
								.addClass ( this.getCssClass() )
								.append(
								$( '<a />' )
								.attr({
									'title': this.getConfig('title'),
									'target': '_blank',
									'href': this.getConfig('href')
								}).append( $img )
							);
			}
			return this.$el;
		}
	}));

} )( window.mw, window.jQuery );<commit_msg>fixed wp on logo.js<commit_after>( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'logo', mw.KBaseComponent.extend({

		defaultConfig: {
			parent: "controlsContainer",
			order: 41,
			displayImportance: 'low',
			align: "right",
			cssClass: "kaltura-logo",
			href: 'http://www.kaltura.com',
			title: 'Kaltura',
			img: null
		},
		getComponent: function() {
			if( !this.$el ) {
				var $img = [];
				if( this.getConfig('img') ){
					$img = $( '<img />' )
								.attr({
									alt: this.getConfig('title'),
									src: this.getConfig('img')
								});
				}
				this.$el = $('<div />')
								.addClass ( this.getCssClass() )
								.append(
								$( '<a />' )
								.attr({
									'title': this.getConfig('title'),
									'target': '_blank',
									'href': this.getConfig('href')
								}).append( $img )
							);
			}
			return this.$el;
		}
	}));

} )( window.mw, window.jQuery );<|endoftext|>


<commit_before>import Morph from 'src/components/widgets/lively-morph.js';
import ohm from "https://unpkg.com/ohm-js@15.2.1/dist/ohm.js";
import {Author, Paper, MicrosoftAcademicEntities} from "src/client/literature.js";

var g = ohm.grammar(
  `Academic {
    Exp =
      AcademicQuery

    AcademicQuery = Attribute Comparator Value -- simple
      | ("And" | "Or") "(" AcademicQuery "," AcademicQuery ")" -- complex
      | "Composite(" CompositeQuery ")" -- composite
    CompositeQuery = Attribute "." Attribute Comparator Value -- simple
      | ("And" | "Or") "(" CompositeQuery "," CompositeQuery ")" -- complex

    Comparator =
      PartialComparator "="?
    PartialComparator =
      "=" | "<" | ">"

    Attribute (an attribute) =
      letter letter? letter? letter?

    Value (a value) =
      "\'" alnum* "\'" -- string
      | Number
      | Date
      | ( "[" | "(" ) Number "," Number ( "]" | ")" ) -- numberRange
      | ( "[" | "(" ) Date "," Date ( "]" | ")" ) -- dateRange

    Number =
      digit+
      Date =
      "\'" Number "-" Number "-" Number "\'"
  }`
);

var s = g.createSemantics();

s.addOperation(
  'interpret', {
    Exp: function(e) {
      return e.interpret();
    },

    AcademicQuery_simple: function(attribute, comparator, value) {
      return {
        "attribute" : attribute.interpret(),
        "comparator" : comparator.interpret(),
        "value" : value.interpret(),
        "type" : "simple"
      }
    },
    AcademicQuery_complex: function(conjunction, _1, left, _2, right, _3) {
      return {
        "conjunction" : conjunction.sourceString,
        "left" : left.interpret(),
        "right" : right.interpret(),
        "type" : "conjunction"
       }
    },
    AcademicQuery_composite: function(_1, query, _2) {
      return query.interpret();
    },

    CompositeQuery_simple: function(mainAttribute, _, secondaryAttribute, comparator, value) {
      // would it make sense to split main and secondary attribute?
      var main = mainAttribute.interpret();
      var secondary = secondaryAttribute.interpret();
      return {
        "attribute" : main + "." + secondary,
        "comparator" : comparator.interpret(),
        "value" : value.interpret(),
        "type" : "composite"
      }
    },
    CompositeQuery_complex: function(conjunction, _1, left, _2, right, _3) {
      return {
        "conjunction" : conjunction.sourceString,
        "left" : left.interpret(),
        "right" : right.interpret(),
        "type" : "conjunction"
      }
    },

    Comparator: function(main, secondary) {
      return [main.interpret(), secondary.sourceString].join('');
    },
    PartialComparator: function(comparator) {
      return comparator.sourceString;
    },

    Attribute: function(a, b, c, d) {
      return [a.interpret(), b.interpret(), c.interpret(), d.interpret()].join('');
    },

    Value: function(value) {
      return value.interpret();
    },
    Value_string: function(_1, string, _2) {
      return string.sourceString;
    },
    Value_numberRange: function(leftBracket, nLeft, _, nRight, rightBracket) {
      return "TODO";//arguments.map(a => {a.sourceString}).join('');
    },
    Value_dateRange: function(leftBracket, dLeft, _, dRight, rightBracket) {
      return "TODO";//arguments.map(a => {a.sourceString}).join('');
    },

    Number: function(n) {
      //return parseFloat(n.sourceString);
      return n.sourceString;
    },
    Date: function(_1, year, _2, month, _3, day, _4) {
      return new Date(year.interpret(),
                      month.interpret(),
                      day.interpret())
    },

    letter: function(a) {
      return a.sourceString;
    }
  }
)

var observer;
var timeout;

export default class AcademicSubquery extends Morph {
  constructor() {
    super();
  }

  async initialize() {
    this.updateView()

    observer = new MutationObserver((mutations) => {
      clearTimeout(timeout);
      timeout = setTimeout(async () => {
        mutations.forEach(async mutation => {
          if (mutation.type == "characterData") {
            this.textContent = await this.viewToQuery();
          }
          if (mutation.type == "childList") {
            // TODO: better propagation to super elements
            var div =

;
            this.appendChild(div);
            this.removeChild(div);

          }
        })
      }, 300);
    });

    const config = {
      attributes: true,
      childList: true,
      subtree: true,
      attributeOldValue: true,
      characterDataOldValue: true,
    };

    // TODO: Why are we switching focus after editing
    // once we start observing?
    observer.observe(this.get('#pane'), config);

    // TODO: falls ich das umbaue, sodass eine subquery einfach als
    // html Element in updateView erstellt wird, muss das hier auch da rein
//     this.addEventListener('dragstart', (evt) => this.onDragStart(evt))
//     this.addEventListener('dragend', (evt) => this.onDragEnd(evt))
//     this.addEventListener('dragover', (evt) => this.onDragOver(evt))
//     this.addEventListener('drop', (evt) => this.onDrop(evt))

    this.style.draggable = 'true';
  //   "drag",
  // "dragend",
  // "dragenter",
  // "dragleave",
  // "dragover",
  // "dragstart",
  // "drop",
  }

  onDragStart(event) {
    //event.dataTransfer.setData("element", event.target.id);
    this.style.opacity = '0.4';
    this.style.color = "black";

    // var id = lively.ensureID(this)
    // this.id = id

    event.dataTransfer.effectAllowed = 'move';
    event.dataTransfer.setData('text/html', this.innerHTML);
    //event.dataTransfer.setData("application/lively4id", id);
  }

  onDragEnd(event) {
    //event.dataTransfer.setData("element", event.target.id);
    this.style.opacity = '1.0';
  }

  onDragOver(event) {
    //event.dataTransfer.setData("element", event.target.id);
    // the next line should not be neccessary with onDragEnter()...
    this.classList.add('over');
    //this.style.border = '3px dotted #666';
  }

  onDrop(event) {
    //if (this.dragStart !== this) {
      //var id = event.dataTransfer.getData("application/lively4id")
      //var el = lively.query(this, "#"+id);
      //lively.notify("ELEMENT", el);
    this.innerHTML = event.dataTransfer.getData("text/html");
    this.classList.remove('over');
    //}
  }

  onDragEnter(event) {
    event.preventDefault();
    //if (!this.complexQuery) this.style.border = '3px dotted #666';
    //lively.notify("ENTERED THIS", this.classList)
    this.classList.add('over');
  }

  onDragLeave(event) {
    event.preventDefault();
    this.classList.remove('over');

    //if (!this.isComplex) this.style.border = '3px dotted #FFF';
  }

  async updateView() {
    var pane = this.get("#pane")
    pane.innerHTML = ""

    if(this.ui) {
      this.ui.style.draggable = 'true'
      this.ui.style.userSelect = 'none'
      if (!this.isComplex) {
        this.ui.addEventListener('dragstart', this.onDragStart)
        this.ui.addEventListener('dragend', this.onDragEnd)
        this.ui.addEventListener('dragover', this.onDragOver)
        this.ui.addEventListener('dragenter', this.onDragEnter)
        this.ui.addEventListener('dragleave', this.onDragLeave)
        this.ui.addEventListener('drop', this.onDrop)
      }
      pane.appendChild(this.ui)
    }
  }

  async setQuery(q) {
    this.textContent = q;

    var match = g.match(q);
    this.ast = s(match).interpret();
    this.ui = await this.queryToView(this.ast);

    this.updateView()
  }

  getQuery() {
    // dasselbe wie viewToQuery?
    return this.textContent;
  }

  async setQueryObject(o) {
    this.ast = o
    this.ui = await this.queryToView(o);

    this.updateView();

    // when only setting the query object, the query might not be set yet
    this.textContent = await this.viewToQuery();
  }

  async viewToQuery() {
    var query = this.textContent;

    if (this.isComplex) {
      // TODO: Why is this neccessary?
      if (await this.leftSubquery && await this.rightSubquery) {
        var left = await this.leftSubquery.viewToQuery();
        var right = await this.rightSubquery.viewToQuery();
        var conjunction = this.get('#conjunction').textContent;
        query = conjunction + "(" + left + ", " + right + ")";
      }
    } else {
      var innerSpan = this.get('#inner');
      if (innerSpan) {
        //lively.notify("INNERSPAN", innerSpan)
        var [attr, comp, val] = innerSpan
                    .querySelectorAll("span[name='queryPart']")
                    .map(e => e.textContent);
        if (val)
          val = val.slice(0, val.length - 1); // remove last whitespace

        // TODO check if attribute has string value
        var stringAttributes = {
          "A": "Author",
          "AA.AuN": "Author Name",
        }
        if (attr.slice(0, attr.length - 1) in stringAttributes) {
          val = "'" + val + "'"
        }
        //query = attr + comp + "'" + val + "'";
        if (innerSpan.getAttribute("type") == "composite")
          query = "Composite(" + attr + comp + val + ")";
        else
          query = attr + comp + val;
      }
    }

    return query
  }

  async toggleEditing() {
    var queries = this.get("#inner").querySelectorAll("[name='sub']");
    var edit = this.get('#edit');
    //edit.innerHTML = "";

    // TODO: Hier this.editing = !this.editing und dann updateView()
    this.editing = !this.editing;
    this.ui = await this.queryToView(this.ast); // TODO: sollte das hier in updateView passieren?
    this.updateView();
    // TODO: Edit Zeichen in buildEditable ändern

    /*
    edit.appendChild();
    edit.appendChild();
    */
  }

  // builds the UI in edit mode
  async buildEditable(object) {
    var inner = ;
    var query = ;
    var schema = await MicrosoftAcademicEntities.generateSchema("paper"); // TODO: in der Klasse speichern?

    // attribute
    var attribute = <select name='attribute' id='attribute'></select>;
    var selectedAttribute;
    schema.filter(attr => attr.operations != "None").forEach(option => {
      var selected = (option.name == object.attribute);
      if (selected) { selectedAttribute = option; }
      attribute.options.add(new Option(option.name, option.name, selected, selected))
    })
    query.appendChild(attribute);

    // comparator
    var mapOperationToSymbol = op => {switch(op) {
        case "Equals":
          return ["==", "="];
        case "StartsWith":
          return ["="];
        case "IsBetween":
          return [">", ">=", "<", "<=", "="];
        default:
          return op;
      } // TODO: in der Klasse speichern?
    };
    var comparator = <select name='comparator' id='comparator'></select>;
    selectedAttribute.operations.split(", ")
      .map(operation => mapOperationToSymbol(operation)) // map words to arrays of symbols
      .flat() // flatten array of arrays
      .filter((item, pos, self) => self.indexOf(item) == pos) // deduplicate
      .forEach(option => {
        var selected = (option == object.comparator);
        comparator.options.add(new Option(option, option, selected, selected))
      });
    query.appendChild(comparator);

    // value
    var value = <input id="value" name="value" value={object.value}></input>;
    // TODO: fit input type to attribute type
    query.appendChild(value);

    inner.appendChild(query);
    var edit =  this.toggleEditing()}>;
    edit.style.cursor = "pointer";
    inner.appendChild(edit);
    return inner;
  }

  async buildConjunctionQuery(object) {
    var inner = ;
    var conjunction = {object.conjunction};
    var left = await (<academic-subquery style="font-size: smaller;"></academic-subquery>);
    await left.setQueryObject(object.left);
    this.leftSubquery = left; // for viewToQuery
    var right = await (<academic-subquery style="font-size: smaller;"></academic-subquery>);
    await right.setQueryObject(object.right);
    this.rightSubquery = right; // for viewToQuery
    inner.appendChild(

          {conjunction}

{left}

{right}

    )
    return inner;
  }

  onMouseOver(event) {
    this.style.color = "orange"
  }

  onMouseOut(event) {
    this.style.color = "black"
  }

  buildSimpleQuery(object) {
    var inner =

          <button
            class="button"
            click={() => {
              this.setQuery(
                "And(" + this.textContent + ", " + this.textContent + ")")
            }}>AND</button>
          <button
            class="button"
            click={() => {
              this.setQuery(
                "Or(" + this.textContent + ", " + this.textContent + ")")
            }}>OR</button>

      ;
    var query = ;
    [object.attribute, object.comparator, object.value].forEach(value => {
      query.appendChild({value} )
      query.addEventListener('mouseover', (evt) => this.onMouseOver(evt));
      query.addEventListener('mouseout', (evt) => this.onMouseOut(evt));
      query.style.cursor = "grab" // on drag: grabbing
    });
    inner.appendChild(query);
    var edit =  this.toggleEditing()}>;
    edit.style.cursor = "pointer";
    inner.appendChild(edit);
    return inner;
  }

  async queryToView(object) {
    var inner = ;
    if (object.type == "conjunction") {
      this.isComplex = true;
      inner = await this.buildConjunctionQuery(object);
    } else { // "composite" or "simple"
      this.isComplex = false;
      if (this.editing) { // edit mode
        inner = await this.buildEditable(object);
      } else { // drag&drop / read mode
        inner = this.buildSimpleQuery(object);
      }
    }
    inner.setAttribute("type", object.type);

    var queryElement =
{inner}
;

    return queryElement;
  }

  async livelyExample() {
    this.setQuery("Composite(AA.AuN=='susan t dumais')");
    //this.setQuery("Composite(AA.AuId=2055148755)")
    //this.setQuery("And(Or(Y=1985, Y=2008), Ti='disordered electronic systems')")
    //this.setQuery("And(O='abc', Y=1000)")
    //this.setQuery("Y='1000'")
  }

}<commit_msg>[academic_query] refactor<commit_after>import Morph from 'src/components/widgets/lively-morph.js';
import ohm from "https://unpkg.com/ohm-js@15.2.1/dist/ohm.js";
import {Author, Paper, MicrosoftAcademicEntities} from "src/client/literature.js";

var g = ohm.grammar(
  `Academic {
    Exp =
      AcademicQuery

    AcademicQuery = Attribute Comparator Value -- simple
      | ("And" | "Or") "(" AcademicQuery "," AcademicQuery ")" -- complex
      | "Composite(" CompositeQuery ")" -- composite
    CompositeQuery = Attribute "." Attribute Comparator Value -- simple
      | ("And" | "Or") "(" CompositeQuery "," CompositeQuery ")" -- complex

    Comparator =
      PartialComparator "="?
    PartialComparator =
      "=" | "<" | ">"

    Attribute (an attribute) =
      letter letter? letter? letter?

    Value (a value) =
      "\'" alnum* "\'" -- string
      | Number
      | Date
      | ( "[" | "(" ) Number "," Number ( "]" | ")" ) -- numberRange
      | ( "[" | "(" ) Date "," Date ( "]" | ")" ) -- dateRange

    Number =
      digit+
      Date =
      "\'" Number "-" Number "-" Number "\'"
  }`
);

var s = g.createSemantics();

s.addOperation(
  'interpret', {
    Exp: function(e) {
      return e.interpret();
    },

    AcademicQuery_simple: function(attribute, comparator, value) {
      return {
        "attribute" : attribute.interpret(),
        "comparator" : comparator.interpret(),
        "value" : value.interpret(),
        "type" : "simple"
      }
    },
    AcademicQuery_complex: function(conjunction, _1, left, _2, right, _3) {
      return {
        "conjunction" : conjunction.sourceString,
        "left" : left.interpret(),
        "right" : right.interpret(),
        "type" : "conjunction"
       }
    },
    AcademicQuery_composite: function(_1, query, _2) {
      return query.interpret();
    },

    CompositeQuery_simple: function(mainAttribute, _, secondaryAttribute, comparator, value) {
      // would it make sense to split main and secondary attribute?
      var main = mainAttribute.interpret();
      var secondary = secondaryAttribute.interpret();
      return {
        "attribute" : main + "." + secondary,
        "comparator" : comparator.interpret(),
        "value" : value.interpret(),
        "type" : "composite"
      }
    },
    CompositeQuery_complex: function(conjunction, _1, left, _2, right, _3) {
      return {
        "conjunction" : conjunction.sourceString,
        "left" : left.interpret(),
        "right" : right.interpret(),
        "type" : "conjunction"
      }
    },

    Comparator: function(main, secondary) {
      return [main.interpret(), secondary.sourceString].join('');
    },
    PartialComparator: function(comparator) {
      return comparator.sourceString;
    },

    Attribute: function(a, b, c, d) {
      return [a.interpret(), b.interpret(), c.interpret(), d.interpret()].join('');
    },

    Value: function(value) {
      return value.interpret();
    },
    Value_string: function(_1, string, _2) {
      return string.sourceString;
    },
    Value_numberRange: function(leftBracket, nLeft, _, nRight, rightBracket) {
      return "TODO";//arguments.map(a => {a.sourceString}).join('');
    },
    Value_dateRange: function(leftBracket, dLeft, _, dRight, rightBracket) {
      return "TODO";//arguments.map(a => {a.sourceString}).join('');
    },

    Number: function(n) {
      //return parseFloat(n.sourceString);
      return n.sourceString;
    },
    Date: function(_1, year, _2, month, _3, day, _4) {
      return new Date(year.interpret(),
                      month.interpret(),
                      day.interpret())
    },

    letter: function(a) {
      return a.sourceString;
    }
  }
)

var observer;
var timeout;

export default class AcademicSubquery extends Morph {
  constructor() {
    super();
  }

  async initialize() {
    this.updateView()

    observer = new MutationObserver((mutations) => {
      clearTimeout(timeout);
      timeout = setTimeout(async () => {
        mutations.forEach(async mutation => {
          if (mutation.type == "characterData") {
            this.textContent = await this.viewToQuery();
          }
          if (mutation.type == "childList") {
            // TODO: better propagation to super elements
            var div =

;
            this.appendChild(div);
            this.removeChild(div);

          }
        })
      }, 300);
    });

    const config = {
      attributes: true,
      childList: true,
      subtree: true,
      attributeOldValue: true,
      characterDataOldValue: true,
    };

    // TODO: Why are we switching focus after editing
    // once we start observing?
    observer.observe(this.get('#pane'), config);

    // TODO: falls ich das umbaue, sodass eine subquery einfach als
    // html Element in updateView erstellt wird, muss das hier auch da rein
//     this.addEventListener('dragstart', (evt) => this.onDragStart(evt))
//     this.addEventListener('dragend', (evt) => this.onDragEnd(evt))
//     this.addEventListener('dragover', (evt) => this.onDragOver(evt))
//     this.addEventListener('drop', (evt) => this.onDrop(evt))

    this.style.draggable = 'true';
  //   "drag",
  // "dragend",
  // "dragenter",
  // "dragleave",
  // "dragover",
  // "dragstart",
  // "drop",
  }

  onDragStart(event) {
    //event.dataTransfer.setData("element", event.target.id);
    this.style.opacity = '0.4';
    this.style.color = "black";

    // var id = lively.ensureID(this)
    // this.id = id

    event.dataTransfer.effectAllowed = 'move';
    event.dataTransfer.setData('text/html', this.innerHTML);
    //event.dataTransfer.setData("application/lively4id", id);
  }

  onDragEnd(event) {
    //event.dataTransfer.setData("element", event.target.id);
    this.style.opacity = '1.0';
  }

  onDragOver(event) {
    //event.dataTransfer.setData("element", event.target.id);
    // the next line should not be neccessary with onDragEnter()...
    this.classList.add('over');
    //this.style.border = '3px dotted #666';
  }

  onDrop(event) {
    //if (this.dragStart !== this) {
      //var id = event.dataTransfer.getData("application/lively4id")
      //var el = lively.query(this, "#"+id);
      //lively.notify("ELEMENT", el);
    this.innerHTML = event.dataTransfer.getData("text/html");
    this.classList.remove('over');
    //}
  }

  onDragEnter(event) {
    event.preventDefault();
    //if (!this.complexQuery) this.style.border = '3px dotted #666';
    //lively.notify("ENTERED THIS", this.classList)
    this.classList.add('over');
  }

  onDragLeave(event) {
    event.preventDefault();
    this.classList.remove('over');

    //if (!this.isComplex) this.style.border = '3px dotted #FFF';
  }

  async updateView() {
    if(!this.ui) { return }
    var pane = this.get("#pane")
    pane.innerHTML = ""

    this.ui.style.draggable = 'true'
    this.ui.style.userSelect = 'none'
    if (!this.isComplex) {
      this.ui.addEventListener('dragstart', this.onDragStart)
      this.ui.addEventListener('dragend', this.onDragEnd)
      this.ui.addEventListener('dragover', this.onDragOver)
      this.ui.addEventListener('dragenter', this.onDragEnter)
      this.ui.addEventListener('dragleave', this.onDragLeave)
      this.ui.addEventListener('drop', this.onDrop)
    }
    pane.appendChild(this.ui)
  }

  async setQuery(q) {
    this.textContent = q;

    var match = g.match(q);
    this.ast = s(match).interpret();
    this.ui = await this.queryToView(this.ast);

    this.updateView()
  }

  getQuery() {
    return this.textContent;
  }

  async setQueryObject(o) {
    this.ast = o
    this.ui = await this.queryToView();

    this.updateView();

    // when only setting the query object, the query might not be set yet
    this.textContent = await this.viewToQuery();
  }

  async viewToQuery() {
    // TODO!
    var query = this.textContent;

    if (this.isComplex) {
      // TODO: Why is this neccessary?
      if (await this.leftSubquery && await this.rightSubquery) {
        var left = await this.leftSubquery.viewToQuery();
        var right = await this.rightSubquery.viewToQuery();
        var conjunction = this.get('#conjunction').textContent;
        query = conjunction + "(" + left + ", " + right + ")";
      }
    } else {
      var innerSpan = this.get('#inner');
      if (innerSpan) {
        //lively.notify("INNERSPAN", innerSpan)
        var [attr, comp, val] = innerSpan
                    .querySelectorAll("span[name='queryPart']")
                    .map(e => e.textContent);
        if (val)
          val = val.slice(0, val.length - 1); // remove last whitespace

        // TODO check if attribute has string value
        var stringAttributes = {
          "A": "Author",
          "AA.AuN": "Author Name",
        }
        if (attr.slice(0, attr.length - 1) in stringAttributes) {
          val = "'" + val + "'"
        }
        //query = attr + comp + "'" + val + "'";
        if (innerSpan.getAttribute("type") == "composite")
          query = "Composite(" + attr + comp + val + ")";
        else
          query = attr + comp + val;
      }
    }

    return query
  }

  async toggleEditing() {
    this.editing = !this.editing;
    this.ui = await this.queryToView();
    this.updateView();
  }

  // builds the UI in edit mode
  async buildEditable(ast) {
    var inner = ;
    var query = ;
    var schema = await MicrosoftAcademicEntities.generateSchema("paper"); // TODO: in der Klasse speichern?

    // attribute
    var attribute = <select name='attribute' id='attribute'></select>;
    var selectedAttribute; // TODO: Klassenvariable?
    schema.filter(attr => attr.operations != "None").forEach(option => {
      var selected = (option.name == ast.attribute);
      if (selected) { selectedAttribute = option; }
      attribute.options.add(new Option(option.name, option.name, selected, selected))
    })
    query.appendChild(attribute);

    // comparator
    var mapOperationToSymbol = op => {switch(op) {
        case "Equals":
          return ["==", "="];
        case "StartsWith":
          return ["="];
        case "IsBetween":
          return [">", ">=", "<", "<=", "="];
        default:
          return op;
      } // TODO: in der Klasse speichern?
    };
    var comparator = <select name='comparator' id='comparator'></select>;
    selectedAttribute.operations.split(", ")
      .map(operation => mapOperationToSymbol(operation)) // map words to arrays of symbols
      .flat()
      .filter((item, pos, self) => self.indexOf(item) == pos) // deduplicate
      .forEach(option => {
        var selected = (option == ast.comparator);
        comparator.options.add(new Option(option, option, selected, selected))
      });
    query.appendChild(comparator);

    // value
    var value = <input id="value" name="value" value={ast.value}></input>;
    // TODO: fit input type to attribute type
    query.appendChild(value);

    inner.appendChild(query);

    var edit =  this.toggleEditing()}>;
    edit.style.cursor = "pointer";
    inner.appendChild(edit);

    return inner;
  }

  async buildConjunctionQuery(ast) {
    var inner = ;
    var conjunction = {ast.conjunction};
    var left = await (<academic-subquery style="font-size: smaller;"></academic-subquery>);
    await left.setQueryObject(ast.left);
    this.leftSubquery = left; // for viewToQuery
    var right = await (<academic-subquery style="font-size: smaller;"></academic-subquery>);
    await right.setQueryObject(ast.right);
    this.rightSubquery = right; // for viewToQuery
    inner.appendChild(

          {conjunction}

{left}

{right}

    )
    return inner;
  }

  onMouseOver(event) {
    this.style.color = "orange"
  }

  onMouseOut(event) {
    this.style.color = "black"
  }

  buildSimpleQuery(ast) {
    var inner =

          <button
            class="button"
            click={() => {
              this.setQuery(
                "And(" + this.textContent + ", " + this.textContent + ")")
            }}>AND</button>
          <button
            class="button"
            click={() => {
              this.setQuery(
                "Or(" + this.textContent + ", " + this.textContent + ")")
            }}>OR</button>

      ;
    var query = ;
    [ast.attribute, ast.comparator, ast.value].forEach(value => {
      query.appendChild({value} )
      query.addEventListener('mouseover', (evt) => this.onMouseOver(evt));
      query.addEventListener('mouseout', (evt) => this.onMouseOut(evt));
      query.style.cursor = "grab"
    });
    inner.appendChild(query);
    var edit =  this.toggleEditing()}>;
    edit.style.cursor = "pointer";
    inner.appendChild(edit);
    return inner;
  }

  async queryToView() {
    const ast = this.ast;
    var inner = ;
    if (ast.type == "conjunction") {
      this.isComplex = true;
      inner = await this.buildConjunctionQuery(ast);
    } else { // "composite" or "simple"
      this.isComplex = false;
      if (this.editing) { // edit mode
        inner = await this.buildEditable(ast);
      } else { // read mode
        inner = this.buildSimpleQuery(ast);
      }
    }
    inner.setAttribute("type", ast.type);

    var queryElement =
{inner}
;

    return queryElement;
  }

  async livelyExample() {
    this.setQuery("Composite(AA.AuN=='susan t dumais')");
    //this.setQuery("Composite(AA.AuId=2055148755)")
    //this.setQuery("And(Or(Y=1985, Y=2008), Ti='disordered electronic systems')")
    //this.setQuery("And(O='abc', Y=1000)")
    //this.setQuery("Y='1000'")
  }

}<|endoftext|>


<commit_before>const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const local = require('feathers-authentication-local');
const oauth2 = require('feathers-authentication-oauth2');
const GoogleStrategy = require('passport-google-oauth20');
const FacebookStrategy = require('passport-facebook');

module.exports = function () {
  const app = this;
  const config = app.get('authentication');
  console.log('LOGGING***', config.strategies);

  // Set up authentication with the secret
  app.configure(authentication(config));
  app.configure(jwt());
  app.configure(local());

  app.configure(oauth2(Object.assign({
    name: 'google',
    Strategy: GoogleStrategy
  }, config.google)));

  app.configure(oauth2(Object.assign({
    name: 'facebook',
    Strategy: FacebookStrategy
  }, config.facebook)));

  // The `authentication` service is used to create a JWT.
  // The before `create` hook registers strategies that can be used
  // to create a new valid JWT (e.g. local or oauth2)
  app.service('authentication').hooks({
    before: {
      create: [
        authentication.hooks.authenticate(config.strategies)
      ],
      remove: [
        authentication.hooks.authenticate('jwt')
      ]
    }
  });
};
<commit_msg>removed logs from auth file<commit_after>const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const local = require('feathers-authentication-local');
const oauth2 = require('feathers-authentication-oauth2');
const GoogleStrategy = require('passport-google-oauth20');
const FacebookStrategy = require('passport-facebook');

module.exports = function () {
  const app = this;
  const config = app.get('authentication');

  // Set up authentication with the secret
  app.configure(authentication(config));
  app.configure(jwt());
  app.configure(local());

  app.configure(oauth2(Object.assign({
    name: 'google',
    Strategy: GoogleStrategy
  }, config.google)));

  app.configure(oauth2(Object.assign({
    name: 'facebook',
    Strategy: FacebookStrategy
  }, config.facebook)));

  // The `authentication` service is used to create a JWT.
  // The before `create` hook registers strategies that can be used
  // to create a new valid JWT (e.g. local or oauth2)
  app.service('authentication').hooks({
    before: {
      create: [
        authentication.hooks.authenticate(config.strategies)
      ],
      remove: [
        authentication.hooks.authenticate('jwt')
      ]
    }
  });
};
<|endoftext|>