<commit_before>'use strict';

var Q = require('q');
var UserFactory = require('./UserFactoryService.js');

module.exports = function(session) {
	var self = this;

	this.session = session;

	this.login = function(name) {
    	return UserFactory.findByName(name);
	};

	this.logout = function(id) {
		var deferred = Q.defer();

		// Take care of cases where the client becomes de-synchronized with the server.
		if(!self.session || !self.session.user) {
			deferred.resolve();
		}
		else if(id === self.session.user.id) {
		  UserFactory.removeByUser(self.session.user).then(function() {
			self.session.destroy();
			deferred.resolve();
		  }, function() {
			deferred.reject('We had trouble logging you out. Please try again in a few minutes!');
		  });
		}
		else {
		  deferred.reject('You can\'t log out as another user.');
		}

    	return deferred.promise;
	};
};
<commit_msg>Removed the unnecessary require statement from the beginning of SessionService.<commit_after>'use strict';

var Q = require('q');

module.exports = function(session) {
	var self = this;

	this.session = session;

	this.login = function(name) {
    	return UserFactoryService.findByName(name);
	};

	this.logout = function(id) {
		var deferred = Q.defer();

		// Take care of cases where the client becomes de-synchronized with the server.
		if(!self.session || !self.session.user) {
			deferred.resolve();
		}
		else if(id === self.session.user.id) {
		  UserFactoryService.removeByUser(self.session.user).then(function() {
			self.session.destroy();
			deferred.resolve();
		  }, function() {
			deferred.reject('We had trouble logging you out. Please try again in a few minutes!');
		  });
		}
		else {
		  deferred.reject('You can\'t log out as another user.');
		}

    	return deferred.promise;
	};
};
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2021 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import I18n from 'i18n!discussion_posts'
import React, {useRef, useState, useEffect} from 'react'
import {Flex} from '@instructure/ui-flex'
import {Button} from '@instructure/ui-buttons'
import {View} from '@instructure/ui-view'
import {nanoid} from 'nanoid'
import PropTypes from 'prop-types'
import CanvasRce from '@canvas/rce/react/CanvasRce'
import {name as mentionsPluginName} from '@canvas/rce/plugins/canvas_mentions/plugin'

export const DiscussionEdit = props => {
  const rceRef = useRef()
  const [rceContent, setRceContent] = useState(false)
  const textAreaId = useRef(`message-body-${nanoid()}`)

  const rceMentionsIsEnabled = () => {
    return !!ENV.rce_mentions_in_discussions
  }

  const getPlugins = () => {
    const plugins = []

    // Non-Editable
    plugins.push('noneditable')

    // Mentions
    if (rceMentionsIsEnabled()) {
      plugins.push(mentionsPluginName)
    }

    return plugins
  }

  useEffect(() => {
    setRceContent(props.value)
  }, [props.value, setRceContent])

  return (

      <View display="block">

          <CanvasRce
            textareaId={textAreaId.current}
            onFocus={() => {}}
            onBlur={() => {}}
            onInit={() => {
              setTimeout(() => {
                rceRef?.current?.focus()
              }, 1500)
            }}
            ref={rceRef}
            onContentChange={content => {
              setRceContent(content)
            }}
            editorOptions={{
              focus: true,
              plugins: getPlugins()
            }}
            height={300}
            defaultContent={props.replyPreview + props.value}
            mirroredAttrs={{'data-testid': 'message-body'}}
          />

      </View>
      <Flex margin="small none none none">
        <Flex.Item shouldGrow shouldShrink textAlign="end">
          <Button
            onClick={() => {
              if (props.onCancel) {
                props.onCancel()
              }
            }}
            display="inline-block"
            color="secondary"
            data-testid="DiscussionEdit-cancel"
          >
            {I18n.t('Cancel')}
          </Button>
          <Button
            onClick={() => {
              if (props.onSubmit) {
                props.onSubmit(rceContent)
              }
            }}
            display="inline-block"
            color="primary"
            margin="none none none small"
            data-testid="DiscussionEdit-submit"
          >
            {props.isEdit ? I18n.t('Save') : I18n.t('Reply')}
          </Button>
        </Flex.Item>
      </Flex>

  )
}

DiscussionEdit.propTypes = {
  show: PropTypes.bool,
  value: PropTypes.string,
  onCancel: PropTypes.func.isRequired,
  onSubmit: PropTypes.func.isRequired,
  isEdit: PropTypes.bool,
  replyPreview: PropTypes.string
}

DiscussionEdit.defaultProps = {
  show: true,
  isEdit: false,
  replyPreview: '',
  value: ''
}

export default DiscussionEdit
<commit_msg>make reply/cancel buttons responsive in discussions rce<commit_after>/*
 * Copyright (C) 2021 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import I18n from 'i18n!discussion_posts'
import React, {useRef, useState, useEffect} from 'react'
import {Flex} from '@instructure/ui-flex'
import {Button} from '@instructure/ui-buttons'
import {Responsive} from '@instructure/ui-responsive'
import {Text} from '@instructure/ui-text'
import {responsiveQuerySizes} from '../../utils'
import {View} from '@instructure/ui-view'
import {nanoid} from 'nanoid'
import PropTypes from 'prop-types'
import CanvasRce from '@canvas/rce/react/CanvasRce'
import {name as mentionsPluginName} from '@canvas/rce/plugins/canvas_mentions/plugin'

export const DiscussionEdit = props => {
  const rceRef = useRef()
  const [rceContent, setRceContent] = useState(false)
  const textAreaId = useRef(`message-body-${nanoid()}`)

  const rceMentionsIsEnabled = () => {
    return !!ENV.rce_mentions_in_discussions
  }

  const getPlugins = () => {
    const plugins = []

    // Non-Editable
    plugins.push('noneditable')

    // Mentions
    if (rceMentionsIsEnabled()) {
      plugins.push(mentionsPluginName)
    }

    return plugins
  }

  useEffect(() => {
    setRceContent(props.value)
  }, [props.value, setRceContent])

  return (

      <View display="block">

          <CanvasRce
            textareaId={textAreaId.current}
            onFocus={() => {}}
            onBlur={() => {}}
            onInit={() => {
              setTimeout(() => {
                rceRef?.current?.focus()
              }, 1500)
            }}
            ref={rceRef}
            onContentChange={content => {
              setRceContent(content)
            }}
            editorOptions={{
              focus: true,
              plugins: getPlugins()
            }}
            height={300}
            defaultContent={props.replyPreview + props.value}
            mirroredAttrs={{'data-testid': 'message-body'}}
          />

      </View>
      <Responsive
        match="media"
        query={responsiveQuerySizes({mobile: true, desktop: true})}
        props={{
          mobile: {
            direction: 'column',
            display: 'block',
            margin: 'small 0 0 0'
          },
          desktop: {
            direction: 'row',
            display: 'inline-block',
            margin: '0 0 0 small'
          }
        }}
        render={responsiveProps => (
          <Flex margin="small none none none" direction={responsiveProps.direction}>
            <Flex.Item
              shouldGrow
              shouldShrink
              textAlign="end"
              overflowY="hidden"
              overflowX="hidden"
            >
              <Button
                onClick={() => {
                  if (props.onCancel) {
                    props.onCancel()
                  }
                }}
                display={responsiveProps.display}
                color="secondary"
                data-testid="DiscussionEdit-cancel"
              >
                <Text size="medium">{I18n.t('Cancel')}</Text>
              </Button>
              <Button
                onClick={() => {
                  if (props.onSubmit) {
                    props.onSubmit(rceContent)
                  }
                }}
                display={responsiveProps.display}
                color="primary"
                margin={responsiveProps.margin}
                data-testid="DiscussionEdit-submit"
              >
                <Text size="medium">{props.isEdit ? I18n.t('Save') : I18n.t('Reply')} </Text>
              </Button>
            </Flex.Item>
          </Flex>
        )}
      />

  )
}

DiscussionEdit.propTypes = {
  show: PropTypes.bool,
  value: PropTypes.string,
  onCancel: PropTypes.func.isRequired,
  onSubmit: PropTypes.func.isRequired,
  isEdit: PropTypes.bool,
  replyPreview: PropTypes.string
}

DiscussionEdit.defaultProps = {
  show: true,
  isEdit: false,
  replyPreview: '',
  value: ''
}

export default DiscussionEdit
<|endoftext|>


<commit_before>var net = require('net');
var tls = require('tls');
var url = require('url');
var path = require('path');
var PipeStream = require('pipestream');
var util = require('../../util');
var WhistleTransform = util.WhistleTransform;
var rules = require('../rules');
var parseReq = require('../proxy/parse-req');
var cert = require('./cert');
var DEFAULT_CERT = cert.getDefault();
var LOCALHOST = '127.0.0.1';

function handleWebsocket(socket, wss, callback, app) {
	var headers = socket.headers;
	var host = headers.host;
	var fullUrl = socket.fullUrl = (wss ? 'wss://' : 'ws://') + headers.host + socket.url;
	var options = url.parse(fullUrl);
	/**
	 * 1. proxy
	 * 2. wss?://
	 * 3. req: delay, speed, headers
	 * 4. res: delay, speed, headers
	 */
	var _rules = socket.rules = rules.resolveRules(fullUrl);

	rules.resolveHost(fullUrl, function(err, ip) {
		if (err || !ip) {
			return callback(new Error(err || new Error('unsupported non websocket the url: ' + fullUrl)));
		}

		var reqSocket = (wss ? tls : net).connect({
			rejectUnauthorized: false,
			host: ip,
			port: options.port || (wss ? 443 : 80)
		}, function () {
			reqSocket.write(socket.getBuffer());
			socket.pipe(reqSocket);
			parseReq(reqSocket, function(err, reqSocket) {
				if (err) {
					return destroy();
				}

				socket.write(reqSocket.getBuffer());
				reqSocket.pipe(socket);
			}, true);
		});

		callback(null, reqSocket);
	}, true);
}

exports.dispatch = function dispatch(socket, app) {
	var config = app.config;
	var reqSocket, buffer;
	var content = '';

	function destroy() {
		socket.destroy();
		reqSocket && reqSocket.destroy();
	}

	function abortIfUnavailable(socket) {
		return socket.on('error', destroy)
			.on('close', destroy);
	}

	abortIfUnavailable(socket);
	socket.on('data', request);
	socket.on('end', request);

	function request(chunk) {
		socket.removeListener('data', request);
		socket.removeListener('end', request);
		if (!chunk) {//没有数据
			return destroy();
		}

		buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
		if (/upgrade\s*:\s*websocket/i.test(buffer && buffer.toString())) { //ws
			parseReq(socket, function(err, socket) {
				if (err) {
					return destroy();
				}
				handleWebsocket(socket, false, function(err, req) {
					if (err) {
						return destroy();
					}
					reqSocket = req;
					abortIfUnavailable(reqSocket);
				});
			}, buffer, true);
			buffer = null;
		} else {
			reqSocket = net.connect(config.httpsport, LOCALHOST, function() {
				reqSocket.write(buffer);
	            reqSocket.pipe(socket).pipe(reqSocket);
	            buffer = null;
	        });
			abortIfUnavailable(reqSocket);
		}
	}

};

exports.createServer = function createServer(app) {
	var config = app.config;
	var server = tls.createServer({
		SNICallback: function(hostname, callback) {
			if (typeof callback != 'function') {
				return cert.getCert();
			}

			callback(null, cert.getCert());
		},
		key: DEFAULT_CERT[0],
		cert: DEFAULT_CERT[1]
	},function(socket) {
		var reqSocket;
		function destroy() {
			socket.destroy();
			reqSocket && reqSocket.destroy();
		}

		function abortIfUnavailable(socket) {
			return socket.on('error', destroy)
				.on('close', destroy);
		}

		abortIfUnavailable(socket);
		parseReq(socket, function(err, socket) {
			if (err) {
				return destroy();
			}
			//wss

			var headers = socket.headers;
			if (headers.upgrade && headers.upgrade.toLowerCase() == 'websocket') {
				handleWebsocket(socket, true, function(err, req) {
					if (err) {
						return destroy();
					}
					reqSocket = req;
					abortIfUnavailable(reqSocket);
				}, app);
			} else {
				//https
				reqSocket = net.connect(config.port, LOCALHOST, function() {
					headers[util.HTTPS_FIELD] = 1;
					reqSocket.write(socket.getBuffer(headers));
					socket.pipe(reqSocket);
					reqSocket.pipe(socket);
		        });
				abortIfUnavailable(reqSocket);
			}
		}, true);

	}).listen(config.httpsport, 'localhost')
		.on('error', util.noop);
};
<commit_msg>proxy map<commit_after>var net = require('net');
var tls = require('tls');
var url = require('url');
var path = require('path');
var util = require('../../util');
var rules = require('../rules');
var parseReq = require('../proxy/parse-req');
var cert = require('./cert');
var DEFAULT_CERT = cert.getDefault();
var LOCALHOST = '127.0.0.1';

function handleWebsocket(socket, wss, callback, app) {
	var headers = socket.headers;
	var host = headers.host;
	var fullUrl = socket.fullUrl = (wss ? 'wss://' : 'ws://') + headers.host + socket.url;
	var options = url.parse(fullUrl);
	/**
	 * 1. proxy
	 * 2. wss?://
	 */
	var _rules = socket.rules = rules.resolveRules(fullUrl);

	rules.resolveHost(fullUrl, function(err, ip) {
		if (err || !ip) {
			return callback(new Error(err || new Error('unsupported non websocket the url: ' + fullUrl)));
		}

		var reqSocket = (wss ? tls : net).connect({
			rejectUnauthorized: false,
			host: ip,
			port: options.port || (wss ? 443 : 80)
		}, function () {
			reqSocket.write(socket.getBuffer());
			socket.pipe(reqSocket);
			parseReq(reqSocket, function(err, reqSocket) {
				if (err) {
					return destroy();
				}

				socket.write(reqSocket.getBuffer());
				reqSocket.pipe(socket);
			}, true);
		});

		callback(null, reqSocket);
	}, true);
}

exports.dispatch = function dispatch(socket, app) {
	var config = app.config;
	var reqSocket, buffer;
	var content = '';

	function destroy() {
		socket.destroy();
		reqSocket && reqSocket.destroy();
	}

	function abortIfUnavailable(socket) {
		return socket.on('error', destroy)
			.on('close', destroy);
	}

	abortIfUnavailable(socket);
	socket.on('data', request);
	socket.on('end', request);

	function request(chunk) {
		socket.removeListener('data', request);
		socket.removeListener('end', request);
		if (!chunk) {//没有数据
			return destroy();
		}

		buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
		if (/upgrade\s*:\s*websocket/i.test(buffer && buffer.toString())) { //ws
			parseReq(socket, function(err, socket) {
				if (err) {
					return destroy();
				}
				handleWebsocket(socket, false, function(err, req) {
					if (err) {
						return destroy();
					}
					reqSocket = req;
					abortIfUnavailable(reqSocket);
				});
			}, buffer, true);
			buffer = null;
		} else {
			reqSocket = net.connect(config.httpsport, LOCALHOST, function() {
				reqSocket.write(buffer);
	            reqSocket.pipe(socket).pipe(reqSocket);
	            buffer = null;
	        });
			abortIfUnavailable(reqSocket);
		}
	}

};

exports.createServer = function createServer(app) {
	var config = app.config;
	var server = tls.createServer({
		SNICallback: function(hostname, callback) {
			if (typeof callback != 'function') {
				return cert.getCert();
			}

			callback(null, cert.getCert());
		},
		key: DEFAULT_CERT[0],
		cert: DEFAULT_CERT[1]
	},function(socket) {
		var reqSocket;
		function destroy() {
			socket.destroy();
			reqSocket && reqSocket.destroy();
		}

		function abortIfUnavailable(socket) {
			return socket.on('error', destroy)
				.on('close', destroy);
		}

		abortIfUnavailable(socket);
		parseReq(socket, function(err, socket) {
			if (err) {
				return destroy();
			}
			//wss

			var headers = socket.headers;
			if (headers.upgrade && headers.upgrade.toLowerCase() == 'websocket') {
				handleWebsocket(socket, true, function(err, req) {
					if (err) {
						return destroy();
					}
					reqSocket = req;
					abortIfUnavailable(reqSocket);
				}, app);
			} else {
				//https
				reqSocket = net.connect(config.port, LOCALHOST, function() {
					headers[util.HTTPS_FIELD] = 1;
					reqSocket.write(socket.getBuffer(headers));
					socket.pipe(reqSocket);
					reqSocket.pipe(socket);
		        });
				abortIfUnavailable(reqSocket);
			}
		}, true);

	}).listen(config.httpsport, 'localhost')
		.on('error', util.noop);
};
<|endoftext|>


<commit_before>/*
 * Geddy JavaScript Web development framework
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * 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.
 *
*/

var fs = require('fs')
  , ServerResponse = require('http').OutgoingMessage
  , utils = require('utilities')
  , errors = require('./errors')
  , format = require('./format')
  , mime = require('mime')
  , Response;

var response = new function () {
  // From Paperboy, http://github.com/felixge/node-paperboy
  this.charsets = {
    'application/json': 'UTF-8',
    'text/javascript': 'UTF-8',
    'text/html': 'UTF-8'
  };

  this.getContentTypeForFormat = function (f) {
    var formatObj = format.formats[f];
    if (formatObj) {
      return formatObj.preferredContentType;
    }
  };

  this.matchAcceptHeaderContentType = function (accepts, type) {
    var formatObj = format.formats[type]
      , pat = formatObj && formatObj.acceptsContentTypePattern
      , match;
    if (pat) {
      for (var j = 0, jj = accepts.length; j < jj; j++) {
        match = accepts[j].match(pat);
        if (match) {
          return match;
        }
      }
    }
  };

  this.formatContent = function (controller, content, opts, callback) {
    var formatObj = format.formats[opts.format];
    return formatObj.handler.call(controller, content, opts, callback);
  };

}();

Response = function (resp) {
  this.resp = resp;
  // Copy has-own props over from original
  utils.mixin(this, resp);
};

// Inherit from actual ServerResponse
Response.prototype = new ServerResponse();
Response.prototype.constructor = Response;

utils.mixin(Response.prototype, new (function () {

  // Override, delegate
  this.setHeaders = function (statusCode, headers) {
    var contentType = headers['Content-Type'];
    var charset = response.charsets[contentType];
    if (charset) {
      contentType += '; charset='+charset;
      headers['Content-Type'] = contentType;
    }
    this.resp.statusCode = statusCode;
    for (var p in headers) {
      this.resp.setHeader(p, headers[p]);
    }
  };

  // Custom methods
  this.send = function (content, statusCode, headers) {
    //var success = !errors.errorTypes[statusCode];
    var s = statusCode || 200;
    var h = headers || {};
    this.setHeaders(s, h);
    this.finalize(content);
  };

  this.finalize = function (content) {
    this.writeBody(content);
    this.finish();
  };

  this.sendFile = function (filepath, opts) {
    var self = this
      , opts = opts || {}
      , contentType = mime.lookup(filepath)
      , now = new Date()
      , expireTime = geddy.config.cacheControl.expires[contentType] ||
          geddy.config.cacheControl.expires.default || 0
      , expireDate = new Date(now.getTime() + (expireTime * 1000));

    var encoding = 'binary';

    fs.stat(filepath, function(err, stat) {
      if(err) {
        throw err;
      }
      else {
        // include additional headers
        var headers = utils.mixin({ }, opts.headers || {});
        headers['Content-Type'] = contentType;
        headers['Content-Length'] = stat.size || (stat.blksize * stat.blocks);
        headers['Last-Modified'] = stat.mtime.toUTCString();
        headers['Expires'] = expireDate.toUTCString();
        headers['Cache-Control'] = 'max-age=' + expireTime;

        self.setHeaders(200, headers);

        // From Paperboy, http://github.com/felixge/node-paperboy
        fs.open(filepath, 'r', 0666, function (err, fd) {
          var pos = 0
            , len = 0;
          var streamChunk = function () {
            fs.read(fd, 16 * 1024, pos, encoding,
                function (err, chunk, bytesRead) {
              if (!chunk) {
                fs.close(fd);
                self.resp._length = len;
                self.resp.end();
                return;
              }
              len += chunk.length;
              self.resp.write(chunk, encoding);
              pos += bytesRead;

              streamChunk();
            });
          }
          streamChunk();
        });
      }
    });
  };

  this.writeBody = function (c) {
    var content = c || ''
      , resp = this.resp;
    resp._length = resp._length || 0;
    resp._length += content.length;
    resp.write(content);
  };

  this.finish = function (success) {
    this.resp.end();
  };

  // Methods for so-called Connect-style middleware
  this.redirect = function () {
    var stat, url;
    // Express API, optional param comes first, WTF
    if (arguments.length == 2) {
      stat = arguments[0];
      url = arguments[1];
    }
    else {
      url = arguments[0];
    }
    this.controller.redirect(url);
  };

})());

response.Response = Response;

module.exports = response;
<commit_msg>repsonse.sendFile(): using responses own headers as default<commit_after>/*
 * Geddy JavaScript Web development framework
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * 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.
 *
*/

var fs = require('fs')
  , ServerResponse = require('http').OutgoingMessage
  , utils = require('utilities')
  , errors = require('./errors')
  , format = require('./format')
  , mime = require('mime')
  , Response;

var response = new function () {
  // From Paperboy, http://github.com/felixge/node-paperboy
  this.charsets = {
    'application/json': 'UTF-8',
    'text/javascript': 'UTF-8',
    'text/html': 'UTF-8'
  };

  this.getContentTypeForFormat = function (f) {
    var formatObj = format.formats[f];
    if (formatObj) {
      return formatObj.preferredContentType;
    }
  };

  this.matchAcceptHeaderContentType = function (accepts, type) {
    var formatObj = format.formats[type]
      , pat = formatObj && formatObj.acceptsContentTypePattern
      , match;
    if (pat) {
      for (var j = 0, jj = accepts.length; j < jj; j++) {
        match = accepts[j].match(pat);
        if (match) {
          return match;
        }
      }
    }
  };

  this.formatContent = function (controller, content, opts, callback) {
    var formatObj = format.formats[opts.format];
    return formatObj.handler.call(controller, content, opts, callback);
  };

}();

Response = function (resp) {
  this.resp = resp;
  // Copy has-own props over from original
  utils.mixin(this, resp);
};

// Inherit from actual ServerResponse
Response.prototype = new ServerResponse();
Response.prototype.constructor = Response;

utils.mixin(Response.prototype, new (function () {

  // Override, delegate
  this.setHeaders = function (statusCode, headers) {
    var contentType = headers['Content-Type'];
    var charset = response.charsets[contentType];
    if (charset) {
      contentType += '; charset='+charset;
      headers['Content-Type'] = contentType;
    }
    this.resp.statusCode = statusCode;
    for (var p in headers) {
      this.resp.setHeader(p, headers[p]);
    }
  };

  // Custom methods
  this.send = function (content, statusCode, headers) {
    //var success = !errors.errorTypes[statusCode];
    var s = statusCode || 200;
    var h = headers || {};
    this.setHeaders(s, h);
    this.finalize(content);
  };

  this.finalize = function (content) {
    this.writeBody(content);
    this.finish();
  };

  this.sendFile = function (filepath, opts) {
    var self = this
      , opts = opts || {}
      , contentType = mime.lookup(filepath)
      , now = new Date()
      , expireTime = geddy.config.cacheControl.expires[contentType] ||
          geddy.config.cacheControl.expires.default || 0
      , expireDate = new Date(now.getTime() + (expireTime * 1000));

    var encoding = 'binary';

    fs.stat(filepath, function(err, stat) {
      if(err) {
        throw err;
      }
      else {
        // include additional headers
        var headers = utils.mixin(self.headers, opts.headers || {});
        headers['Content-Type'] = contentType;
        headers['Content-Length'] = stat.size || (stat.blksize * stat.blocks);
        headers['Last-Modified'] = stat.mtime.toUTCString();
        headers['Expires'] = expireDate.toUTCString();
        headers['Cache-Control'] = 'max-age=' + expireTime;

        self.setHeaders(200, headers);

        // From Paperboy, http://github.com/felixge/node-paperboy
        fs.open(filepath, 'r', 0666, function (err, fd) {
          var pos = 0
            , len = 0;
          var streamChunk = function () {
            fs.read(fd, 16 * 1024, pos, encoding,
                function (err, chunk, bytesRead) {
              if (!chunk) {
                fs.close(fd);
                self.resp._length = len;
                self.resp.end();
                return;
              }
              len += chunk.length;
              self.resp.write(chunk, encoding);
              pos += bytesRead;

              streamChunk();
            });
          }
          streamChunk();
        });
      }
    });
  };

  this.writeBody = function (c) {
    var content = c || ''
      , resp = this.resp;
    resp._length = resp._length || 0;
    resp._length += content.length;
    resp.write(content);
  };

  this.finish = function (success) {
    this.resp.end();
  };

  // Methods for so-called Connect-style middleware
  this.redirect = function () {
    var stat, url;
    // Express API, optional param comes first, WTF
    if (arguments.length == 2) {
      stat = arguments[0];
      url = arguments[1];
    }
    else {
      url = arguments[0];
    }
    this.controller.redirect(url);
  };

})());

response.Response = Response;

module.exports = response;
<|endoftext|>


<commit_before>//Use this file to implement Part One of your project

console.log("test")
<commit_msg>basic solution<commit_after>//Use this file to implement Part One of your project

// console.log("test")

var animal = {}

animal.username = "Daffy";

// console.log(animal['username']);

animal["tagline"] = "Ducks Rule!";

var empty = [];
animal.noises = empty;

console.log(animal);

var i = 0
for(var key in animal){
	i += 1;
	console.log(i);
	// console.log(animal[key]);
	if (key == "username")
		console.log(animal.username);
	else if (key == "tagline")
		console.log(animal.tagline);
}<|endoftext|>


<commit_before>if (!phantom.casperLoaded) {
    console.log('This script must be invoked using the casperjs executable');
    phantom.exit(1);
}

var fs = require('fs');
var utils = require('utils');
var f = utils.format;
var includes = [];
var tests = [];
var casper = require('casper').create({
    exitOnError: false
});

// local utils
function checkIncludeFile(include) {
    var absInclude = fs.absolute(include.trim());
    if (!fs.exists(absInclude)) {
        casper.warn("%s file not found, can't be included", absInclude);
        return;
    }
    if (!utils.isJsFile(absInclude)) {
        casper.warn("%s is not a supported file type, can't be included", absInclude);
        return;
    }
    if (fs.isDirectory(absInclude)) {
        casper.warn("%s is a directory, can't be included", absInclude);
        return;
    }
    if (tests.indexOf(include) > -1 || tests.indexOf(absInclude) > -1) {
        casper.warn("%s is a test file, can't be included", absInclude);
        return;
    }
    return absInclude;
}

// parse some options from cli
casper.options.verbose = casper.cli.get('direct') || false;
casper.options.logLevel = casper.cli.get('log-level') || "error";

// overriding Casper.open to prefix all test urls
casper.setFilter('open.location', function(location) {
    if (!/^http/.test(location)) {
        return f('file://%s/%s', phantom.casperPath, location);
    }
    return location;
});

// test paths are passed as args
if (casper.cli.args.length) {
    tests = casper.cli.args.filter(function(path) {
        return fs.isFile(path) || fs.isDirectory(path);
    });
} else {
    casper.echo('No test path passed, exiting.', 'RED_BAR', 80);
    casper.exit(1);
}

// includes handling
if (casper.cli.has('includes')) {
    includes = casper.cli.get('includes').split(',').map(function(include) {
        // we can't use filter() directly because of abspath transformation
        return checkIncludeFile(include);
    }).filter(function(include) {
        return utils.isString(include);
    });
    casper.test.includes = utils.unique(includes);
}

// test suites completion listener
casper.test.on('tests.complete', function() {
    this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
});

// run all the suites
casper.test.runSuites.apply(casper.test, tests);
<commit_msg>fixes #140 - 'casper test' now resolves local paths urls<commit_after>if (!phantom.casperLoaded) {
    console.log('This script must be invoked using the casperjs executable');
    phantom.exit(1);
}

var fs = require('fs');
var utils = require('utils');
var f = utils.format;
var includes = [];
var tests = [];
var casper = require('casper').create({
    exitOnError: false
});

// local utils
function checkIncludeFile(include) {
    var absInclude = fs.absolute(include.trim());
    if (!fs.exists(absInclude)) {
        casper.warn("%s file not found, can't be included", absInclude);
        return;
    }
    if (!utils.isJsFile(absInclude)) {
        casper.warn("%s is not a supported file type, can't be included", absInclude);
        return;
    }
    if (fs.isDirectory(absInclude)) {
        casper.warn("%s is a directory, can't be included", absInclude);
        return;
    }
    if (tests.indexOf(include) > -1 || tests.indexOf(absInclude) > -1) {
        casper.warn("%s is a test file, can't be included", absInclude);
        return;
    }
    return absInclude;
}

// parse some options from cli
casper.options.verbose = casper.cli.get('direct') || false;
casper.options.logLevel = casper.cli.get('log-level') || "error";

// overriding Casper.open to prefix all test urls
casper.setFilter('open.location', function(location) {
    if (!/^http/.test(location)) {
        return f('file://%s/%s', fs.workingDirectory, location);
    }
    return location;
});

// test paths are passed as args
if (casper.cli.args.length) {
    tests = casper.cli.args.filter(function(path) {
        return fs.isFile(path) || fs.isDirectory(path);
    });
} else {
    casper.echo('No test path passed, exiting.', 'RED_BAR', 80);
    casper.exit(1);
}

// includes handling
if (casper.cli.has('includes')) {
    includes = casper.cli.get('includes').split(',').map(function(include) {
        // we can't use filter() directly because of abspath transformation
        return checkIncludeFile(include);
    }).filter(function(include) {
        return utils.isString(include);
    });
    casper.test.includes = utils.unique(includes);
}

// test suites completion listener
casper.test.on('tests.complete', function() {
    this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
});

// run all the suites
casper.test.runSuites.apply(casper.test, tests);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

var winston = require('winston'),
	logutils = module.exports,
	messages = require('../common/messages'),
	util = require('util'),
    config = process.mainModule.exports.config;

var logLevel = ((null != config) && (null != config.logs) &&
                (null != config.logs.level) && ('' != config.logs.level))
                ? config.logs.level : 'debug';

/**
 * Constructor to create new Winston logger.
 */
logutils.logger = new (winston.Logger)({
	transports:[
		new (winston.transports.Console)({colorize:true, timestamp:true, level: logLevel})
	]
});

if (!module.parent) {
	logutils.logger.warn(util.format(messages.warn.invalid_mod_call, module.filename));
	process.exit(1);
}

<commit_msg>Closes-Bug: #1465946 Using moment date-time formatter for web-ui logging to make it consistent with other contrail module logs. Depends-On: I7297e5dc5c5e17a190acb90ba968f3797bb4418b<commit_after>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

var winston = require('winston'),
	logutils = module.exports,
	messages = require('../common/messages'),
	util = require('util'),
    moment = require('moment'),
    config = process.mainModule.exports.config;

var logLevel = ((null != config) && (null != config.logs) &&
                (null != config.logs.level) && ('' != config.logs.level))
                ? config.logs.level : 'debug';

function getLoggingTime ()
{
    return moment().format('MM/DD/YYYY HH:MM:SS A');
}

/**
 * Constructor to create new Winston logger.
 */
logutils.logger = new (winston.Logger)({
	transports:[
		new (winston.transports.Console)({colorize:true,
                                         timestamp:getLoggingTime, level: logLevel})
	]
});

if (!module.parent) {
	logutils.logger.warn(util.format(messages.warn.invalid_mod_call, module.filename));
	process.exit(1);
}

<|endoftext|>


<commit_before>const config = require('../config.json');
exports.run = (client, message, args) => {
  var evalcode = message.content.split(" ").splice(1).join(" ");
  try {
    var evaled = eval(evalcode);
    if (typeof evaled !== "string")
    evaled = require("util").inspect(evaled);
    message.channel.sendMessage("Output:\n```js\n" + clean(evaled) + "```");
  }
  catch (err) {
    message.channel.sendMessage("Error: " + clean(err));
  }

  function clean(text) {
    if (typeof(text) === "string") {
      return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203));
    }
    else {
      return text;
    }
  }
}
<commit_msg>Fix error<commit_after>const config = require('../config.json');
exports.run = (client, message, args) => {

    function clean(text) {
    if (typeof(text) === "string") {
      return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203));
    }
    else {
      return text;
    }
  }

  var evalcode = message.content.split(" ").splice(1).join(" ");
  try {
    var evaled = eval(evalcode);
    if (typeof evaled !== "string")
    evaled = require("util").inspect(evaled);
    message.channel.sendMessage("Output:\n```js\n" + clean(evaled) + "```");
  }
  catch (err) {
    message.channel.sendMessage("Error: " + clean(err));
  }
}
<|endoftext|>


<commit_before>const {remote} = require('electron')
const {h, Component} = require('preact')
const classNames = require('classnames')

const MiniGoban = require('../MiniGoban')
const Drawer = require('./Drawer')

const dialog = require('../../modules/dialog')
const fileformats = require('../../modules/fileformats')
const gametree = require('../../modules/gametree')
const gamesort = require('../../modules/gamesort')
const helper = require('../../modules/helper')
const setting = remote.require('./setting')

let thumbnailSize = setting.get('gamechooser.thumbnail_size')
let itemMinWidth = thumbnailSize + 12 + 20
let itemHeight = 253 + 10 + 20

let getPreviewBoard = tree => {
    let node = tree.navigate(tree.root.id, 30, {})
    if (!node) node = tree.navigate(tree.root.id, tree.getCurrentHeight({}) - 1, {})

    return gametree.getBoard(tree, node.id)
}

class GameListItem extends Component {
    constructor() {
        super()

        let events = ['Click', 'ContextMenu', 'DragStart', 'DragOver']

        for (let name of events) {
            this[`handle${name}`] = evt => {
                let callback = this.props[`on${name}`]
                evt.tree = this.props.tree
                if (callback) callback(evt)
            }
        }
    }

    shouldComponentUpdate(nextProps) {
        for (let i in nextProps)
            if (nextProps[i] !== this.props[i]) return true

        return false
    }

    render({tree, left, top, draggable, showThumbnail, insertBefore, insertAfter}) {
        let gameInfo = sabaki.getGameInfo(tree)
        let {gameName, eventName, blackName, blackRank, whiteName, whiteRank} = gameInfo
        let name = gameName || eventName || ''

        return h('li',
            {
                ref: el => this.element = el,
                class: classNames({
                    insertbefore: insertBefore,
                    insertafter: insertAfter
                }),
                style: {left, top}
            },

            h('div',
                {
                    draggable,
                    onClick: this.handleClick,
                    onContextMenu: this.handleContextMenu,
                    onDragStart: this.handleDragStart,
                    onDragOver: this.handleDragOver
                },

                h('span', {title: name}, name),

                h(MiniGoban, {
                    board: getPreviewBoard(tree),
                    maxSize: thumbnailSize,
                    visible: showThumbnail
                }),

                h('span', {class: 'black', title: blackRank}, blackName || 'Black'),
                h('span', {class: 'white', title: whiteRank}, whiteName || 'White')
            )
        )
    }
}

class GameChooserDrawer extends Component {
    constructor() {
        super()

        this.itemElements = {}

        this.state = {
            scrollTop: 0,
            insertBefore: -1,
            animation: false,
            filterText: ''
        }

        this.handleFilterTextChange = evt => this.setState({
            filterText: evt.currentTarget.value.trim()
        })

        this.handleCloseButtonClick = () => sabaki.closeDrawer()

        this.handleListScroll = evt => {
            this.setState({scrollTop: evt.currentTarget.scrollTop})
        }

        this.handleItemContextMenu = evt => {
            let template = [
                {
                    label: '&Remove Game',
                    click: () => {
                        if (dialog.showMessageBox(
                            'Do you really want to remove this game permanently?',
                            'warning',
                            ['Remove Game', 'Cancel'], 1
                        ) === 1) return

                        let {gameTrees, onChange = helper.noop} = this.props
                        let index = gameTrees.indexOf(evt.tree)

                        onChange({gameTrees: gameTrees.filter((_, i) => i !== index)})
                    }
                },
                {
                    label: 'Remove &Other Games',
                    click: () => {
                        if (dialog.showMessageBox(
                            'Do you really want to remove all other games permanently?',
                            'warning',
                            ['Remove Games', 'Cancel'], 1
                        ) === 1) return

                        let {onChange = helper.noop} = this.props
                        onChange({gameTrees: [evt.tree]})
                    }
                }
            ]

            helper.popupMenu(template, evt.clientX, evt.clientY)
        }

        this.handleItemDragStart = evt => {
            this.dragData = this.props.gameTrees.indexOf(evt.tree)
        }

        this.handleItemDragOver = evt => {
            if (this.dragData == null) return

            evt.preventDefault()

            let element = evt.currentTarget
            let index = this.props.gameTrees.indexOf(evt.tree)

            let x = evt.clientX
            let {left, width} = element.getBoundingClientRect()
            let middle = left + width / 2

            if (x <= middle - 10) {
                this.setState({insertBefore: index})
            } else if (x >= middle + 10) {
                this.setState({insertBefore: index + 1})
            }
        }

        this.handleItemDrop = evt => {
            let {gameTrees, onChange = helper.noop} = this.props
            let {insertBefore} = this.state
            let newGameTrees = gameTrees.slice()

            if (this.dragData == null || insertBefore < 0) return
            if (insertBefore > this.dragData) insertBefore--

            let [tree] = newGameTrees.splice(this.dragData, 1)
            newGameTrees.splice(insertBefore, 0, tree)

            this.dragData = null
            this.setState({insertBefore: -1})

            onChange({gameTrees: newGameTrees})
        }

        this.handleCancelDrag = () => {
            this.dragData = null
            this.setState({insertBefore: -1})
        }

        this.handleItemClick = evt => {
            let {onItemClick = helper.noop} = this.props

            evt.selectedTree = evt.tree
            onItemClick(evt)
        }

        this.handleAddButtonClick = evt => {
            let template = [
                {
                    label: 'Add &New Game',
                    click: () => {
                        let tree = sabaki.getEmptyGameTree()
                        let {gameTrees, onChange = helper.noop} = this.props

                        onChange({gameTrees: [...gameTrees, tree]})
                    }
                },
                {
                    label: 'Add &Existing Files…',
                    click: () => {
                        dialog.showOpenDialog({
                            properties: ['openFile', 'multiSelections'],
                            filters: [...fileformats.meta, {name: 'All Files', extensions: ['*']}]
                        }, ({result}) => {
                            let {gameTrees, onChange = helper.noop} = this.props
                            let newTrees = []

                            sabaki.setBusy(true)

                            if (result) {
                                try {
                                    for (let filename of result) {
                                        let trees = fileformats.parseFile(filename)
                                        newTrees.push(...trees)
                                    }
                                } catch (err) {
                                    dialog.showMessageBox('Some files are unreadable.', 'warning')
                                }
                            }

                            onChange({gameTrees: [...gameTrees, ...newTrees]})
                            sabaki.setBusy(false)
                        })
                    }
                }
            ]

            let element = evt.currentTarget
            let {left, bottom} = element.getBoundingClientRect()

            helper.popupMenu(template, left, bottom)
        }

        this.handleSortButtonClick = evt => {
            let sortWith = (sorter) => () => {
                sabaki.setBusy(true)

                let {gameTrees, onChange = helper.noop} = this.props
                let newGameTrees = sorter(gameTrees.slice())

                onChange({gameTrees: newGameTrees})
                sabaki.setBusy(false)
            }

            let template = [
                {label: '&Black Player', click: sortWith(gamesort.byPlayerBlack)},
                {label: '&White Player', click: sortWith(gamesort.byPlayerWhite)},
                {label: 'Black R&ank', click: sortWith(gamesort.byBlackRank)},
                {label: 'White Ran&k', click: sortWith(gamesort.byWhiteRank)},
                {label: 'Game &Name', click: sortWith(gamesort.byGameName)},
                {label: 'Game &Event', click: sortWith(gamesort.byEvent)},
                {label: '&Date', click: sortWith(gamesort.byDate)},
                {label: 'Number of &Moves', click: sortWith(gamesort.byNumberOfMoves)},
                {type: 'separator'},
                {label: '&Reverse', click: sortWith(gamesort.reverse)}
            ]

            let element = evt.currentTarget
            let {left, bottom} = element.getBoundingClientRect()

            helper.popupMenu(template, left, bottom)
        }
    }

    componentDidMount() {
        window.addEventListener('resize', () => this.resize())

        this.resize()
        this.forceUpdate()
    }

    shouldComponentUpdate({show}, {animation}) {
        return animation !== this.state.animation || show || show !== this.props.show
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state.scrollTop !== prevState.scrollTop
        && this.state.scrollTop !== this.gamesListElement.scrollTop) {
            // Update scroll top

            this.gamesListElement.scrollTop = this.state.scrollTop
            this.setState({scrollTop: this.gamesListElement.scrollTop})
        }

        if (this.props.show && prevProps.gameTrees.length < this.props.gameTrees.length) {
            // Scroll down

            this.gamesListElement.scrollTop = this.gamesListElement.scrollHeight
            this.setState({scrollTop: this.gamesListElement.scrollTop})
        }

        if (!prevProps.show && this.props.show) {
            // Scroll current list element into view

            let index = this.shownGameTrees.findIndex(([, i]) => i === this.props.gameIndex)
            let scrollTop = 0
            if (index >= 0) scrollTop = this.getRowFromIndex(index) * itemHeight

            this.gamesListElement.scrollTop = scrollTop
            this.setState({scrollTop: this.gamesListElement.scrollTop})
        }

        if (prevProps.show !== this.props.show) {
            // Animate

            let gobanRect = document.getElementById('goban').getBoundingClientRect()
            let drawerRect = document.getElementById('gamechooser').getBoundingClientRect()

            let itemElement = this.itemElements[this.props.gameIndex]
            let svgElement = itemElement != null ? itemElement.querySelector('svg') : null

            if (itemElement != null && svgElement != null) {
                let {width, height, left, top} = itemElement.querySelector('svg').getBoundingClientRect()

                let miniGobanRect = {
                    left: left - drawerRect.left,
                    top: top - drawerRect.top,
                    width,
                    height
                }

                let direction = this.props.show ? 'reverse' : 'normal'

                this.setState({animation: [miniGobanRect, gobanRect, direction]})
                setTimeout(() => this.setState({animation: null}), 600)
            }
        }
    }

    resize() {
        let innerWidth = this.gamesListElement.offsetWidth - 28
        let height = this.gamesListElement.offsetHeight
        let rowCount = Math.floor(innerWidth / itemMinWidth)

        this.setState({innerWidth, height, rowCount})
    }

    getRowFromIndex(i) {
        return (i - i % this.state.rowCount) / this.state.rowCount
    }

    render({
        show,
        gameTrees,
        gameIndex
    }, {
        filterText,
        animation,
        scrollTop,
        insertBefore,
        rowCount,
        innerWidth,
        height
    }) {
        let itemWidth = Math.floor(innerWidth / rowCount)

        this.shownGameTrees = gameTrees.map((tree, index) => {
            return [tree, index]
        }).filter(([tree]) => {
            let gameInfo = sabaki.getGameInfo(tree)
            let data = Object.keys(gameInfo).map(x => gameInfo[x])

            return data.join(' ').toLowerCase().includes(filterText.toLowerCase())
        })

        return h('div', {onDrop: this.handleCancelDrag},
            h('style', {}, `
                #gamechooser .games-list .placeholder {
                    height: ${(this.getRowFromIndex(this.shownGameTrees.length - 1) + 1) * itemHeight + 20}px;
                }

                #gamechooser .games-list li {
                    width: ${itemWidth - 20}px;
                }
            `, animation && `
                #gamechooser-animation {
                    animation: gamechooser-animation .5s ${animation[2]} forwards;
                }

                @keyframes gamechooser-animation {
                    from {
                        transform: translate(${animation[0].left}px, ${animation[0].top}px);
                        opacity: 1;
                    }
                    to {
                        transform: translate(${animation[1].left}px, ${animation[1].top}px)
                            scale(${animation[1].width / animation[0].width},
                            ${animation[1].height / animation[0].height});
                        opacity: 0;
                    }
                }
            `),

            h(Drawer,
                {
                    type: 'gamechooser',
                    show
                },

                h('h2', {}, 'Manage Games'),

                h('input', {
                    type: 'search',
                    name: 'filter',
                    placeholder: 'Filter',
                    value: filterText,
                    onInput: this.handleFilterTextChange
                }),

                h('div',
                    {
                        ref: el => this.gamesListElement = el,
                        class: 'games-list',

                        onScroll: this.handleListScroll,
                        onDrop: this.handleItemDrop
                    },

                    h('div', {class: 'placeholder'}),

                    h('ol', {}, this.shownGameTrees.map(([tree, index], i) => {
                        let row = this.getRowFromIndex(i)
                        let itemTop = row * itemHeight + 10
                        let itemLeft = (i - row * rowCount) * itemWidth + 10

                        if (index !== gameIndex
                        && (itemTop + itemHeight * 2 <= scrollTop || itemTop - itemHeight >= scrollTop + height))
                            return

                        return h(GameListItem, {
                            ref: item => {
                                if (item != null) this.itemElements[index] = item.element
                            },
                            key: tree.id,
                            tree,
                            top: itemTop,
                            left: itemLeft,
                            draggable: filterText === '',

                            showThumbnail: index !== gameIndex || !animation,
                            insertBefore: insertBefore === index,
                            insertAfter: i === this.shownGameTrees.length - 1
                                && insertBefore === index + 1,

                            onClick: this.handleItemClick,
                            onContextMenu: this.handleItemContextMenu,
                            onDragStart: this.handleItemDragStart,
                            onDragOver: this.handleItemDragOver
                        })
                    }))
                ),

                h('p', {},
                    h('button', {
                        type: 'button',
                        class: 'dropdown',
                        onClick: this.handleAddButtonClick
                    }, 'Add'),

                    h('button', {
                        type: 'button',
                        class: 'dropdown',
                        onClick: this.handleSortButtonClick
                    }, 'Sort By'),

                    h('button', {
                        type: 'button',
                        onClick: this.handleCloseButtonClick
                    }, 'Close')
                )
            ),

            h('div',
                {
                    id: 'gamechooser-animation',
                    style: !animation ? {
                        opacity: 0,
                        pointerEvents: 'none'
                    } : {}
                },

                h(MiniGoban, {
                    board: getPreviewBoard(gameTrees[gameIndex]),
                    maxSize: thumbnailSize
                })
            )
        )
    }
}

module.exports = GameChooserDrawer
<commit_msg>Make GameChooserDrawer translatable<commit_after>const {remote} = require('electron')
const {h, Component} = require('preact')
const classNames = require('classnames')

const MiniGoban = require('../MiniGoban')
const Drawer = require('./Drawer')

const t = require('../../i18n').context('GameChooserDrawer')
const dialog = require('../../modules/dialog')
const fileformats = require('../../modules/fileformats')
const gametree = require('../../modules/gametree')
const gamesort = require('../../modules/gamesort')
const helper = require('../../modules/helper')
const setting = remote.require('./setting')

let thumbnailSize = setting.get('gamechooser.thumbnail_size')
let itemMinWidth = thumbnailSize + 12 + 20
let itemHeight = 253 + 10 + 20

let getPreviewBoard = tree => {
    let node = tree.navigate(tree.root.id, 30, {})
    if (!node) node = tree.navigate(tree.root.id, tree.getCurrentHeight({}) - 1, {})

    return gametree.getBoard(tree, node.id)
}

class GameListItem extends Component {
    constructor() {
        super()

        let events = ['Click', 'ContextMenu', 'DragStart', 'DragOver']

        for (let name of events) {
            this[`handle${name}`] = evt => {
                let callback = this.props[`on${name}`]
                evt.tree = this.props.tree
                if (callback) callback(evt)
            }
        }
    }

    shouldComponentUpdate(nextProps) {
        for (let i in nextProps)
            if (nextProps[i] !== this.props[i]) return true

        return false
    }

    render({tree, left, top, draggable, showThumbnail, insertBefore, insertAfter}) {
        let gameInfo = sabaki.getGameInfo(tree)
        let {gameName, eventName, blackName, blackRank, whiteName, whiteRank} = gameInfo
        let name = gameName || eventName || ''

        return h('li',
            {
                ref: el => this.element = el,
                class: classNames({
                    insertbefore: insertBefore,
                    insertafter: insertAfter
                }),
                style: {left, top}
            },

            h('div',
                {
                    draggable,
                    onClick: this.handleClick,
                    onContextMenu: this.handleContextMenu,
                    onDragStart: this.handleDragStart,
                    onDragOver: this.handleDragOver
                },

                h('span', {title: name}, name),

                h(MiniGoban, {
                    board: getPreviewBoard(tree),
                    maxSize: thumbnailSize,
                    visible: showThumbnail
                }),

                h('span', {class: 'black', title: blackRank}, blackName || t('Black')),
                h('span', {class: 'white', title: whiteRank}, whiteName || t('White'))
            )
        )
    }
}

class GameChooserDrawer extends Component {
    constructor() {
        super()

        this.itemElements = {}

        this.state = {
            scrollTop: 0,
            insertBefore: -1,
            animation: false,
            filterText: ''
        }

        this.handleFilterTextChange = evt => this.setState({
            filterText: evt.currentTarget.value.trim()
        })

        this.handleCloseButtonClick = () => sabaki.closeDrawer()

        this.handleListScroll = evt => {
            this.setState({scrollTop: evt.currentTarget.scrollTop})
        }

        this.handleItemContextMenu = evt => {
            let template = [
                {
                    label: t('&Remove Game'),
                    click: () => {
                        if (dialog.showMessageBox(
                            t('Do you really want to remove this game permanently?'),
                            'warning',
                            [t('Remove Game'), t('Cancel')], 1
                        ) === 1) return

                        let {gameTrees, onChange = helper.noop} = this.props
                        let index = gameTrees.indexOf(evt.tree)

                        onChange({gameTrees: gameTrees.filter((_, i) => i !== index)})
                    }
                },
                {
                    label: t('Remove &Other Games'),
                    click: () => {
                        if (dialog.showMessageBox(
                            t('Do you really want to remove all other games permanently?'),
                            'warning',
                            [t('Remove Games'), t('Cancel')], 1
                        ) === 1) return

                        let {onChange = helper.noop} = this.props
                        onChange({gameTrees: [evt.tree]})
                    }
                }
            ]

            helper.popupMenu(template, evt.clientX, evt.clientY)
        }

        this.handleItemDragStart = evt => {
            this.dragData = this.props.gameTrees.indexOf(evt.tree)
        }

        this.handleItemDragOver = evt => {
            if (this.dragData == null) return

            evt.preventDefault()

            let element = evt.currentTarget
            let index = this.props.gameTrees.indexOf(evt.tree)

            let x = evt.clientX
            let {left, width} = element.getBoundingClientRect()
            let middle = left + width / 2

            if (x <= middle - 10) {
                this.setState({insertBefore: index})
            } else if (x >= middle + 10) {
                this.setState({insertBefore: index + 1})
            }
        }

        this.handleItemDrop = evt => {
            let {gameTrees, onChange = helper.noop} = this.props
            let {insertBefore} = this.state
            let newGameTrees = gameTrees.slice()

            if (this.dragData == null || insertBefore < 0) return
            if (insertBefore > this.dragData) insertBefore--

            let [tree] = newGameTrees.splice(this.dragData, 1)
            newGameTrees.splice(insertBefore, 0, tree)

            this.dragData = null
            this.setState({insertBefore: -1})

            onChange({gameTrees: newGameTrees})
        }

        this.handleCancelDrag = () => {
            this.dragData = null
            this.setState({insertBefore: -1})
        }

        this.handleItemClick = evt => {
            let {onItemClick = helper.noop} = this.props

            evt.selectedTree = evt.tree
            onItemClick(evt)
        }

        this.handleAddButtonClick = evt => {
            let template = [
                {
                    label: t('Add &New Game'),
                    click: () => {
                        let tree = sabaki.getEmptyGameTree()
                        let {gameTrees, onChange = helper.noop} = this.props

                        onChange({gameTrees: [...gameTrees, tree]})
                    }
                },
                {
                    label: t('Add &Existing Files…'),
                    click: () => {
                        dialog.showOpenDialog({
                            properties: ['openFile', 'multiSelections'],
                            filters: [
                                ...fileformats.meta,
                                {name: t('All Files'), extensions: ['*']}
                            ]
                        }, ({result}) => {
                            let {gameTrees, onChange = helper.noop} = this.props
                            let newTrees = []

                            sabaki.setBusy(true)

                            if (result) {
                                try {
                                    for (let filename of result) {
                                        let trees = fileformats.parseFile(filename)
                                        newTrees.push(...trees)
                                    }
                                } catch (err) {
                                    dialog.showMessageBox(t('Some files are unreadable.'), 'warning')
                                }
                            }

                            onChange({gameTrees: [...gameTrees, ...newTrees]})
                            sabaki.setBusy(false)
                        })
                    }
                }
            ]

            let element = evt.currentTarget
            let {left, bottom} = element.getBoundingClientRect()

            helper.popupMenu(template, left, bottom)
        }

        this.handleSortButtonClick = evt => {
            let sortWith = (sorter) => () => {
                sabaki.setBusy(true)

                let {gameTrees, onChange = helper.noop} = this.props
                let newGameTrees = sorter(gameTrees.slice())

                onChange({gameTrees: newGameTrees})
                sabaki.setBusy(false)
            }

            let template = [
                {label: t('&Black Player'), click: sortWith(gamesort.byPlayerBlack)},
                {label: t('&White Player'), click: sortWith(gamesort.byPlayerWhite)},
                {label: t('Black R&ank'), click: sortWith(gamesort.byBlackRank)},
                {label: t('White Ran&k'), click: sortWith(gamesort.byWhiteRank)},
                {label: t('Game &Name'), click: sortWith(gamesort.byGameName)},
                {label: t('Game &Event'), click: sortWith(gamesort.byEvent)},
                {label: t('&Date'), click: sortWith(gamesort.byDate)},
                {label: t('Number of &Moves'), click: sortWith(gamesort.byNumberOfMoves)},
                {type: 'separator'},
                {label: t('&Reverse'), click: sortWith(gamesort.reverse)}
            ]

            let element = evt.currentTarget
            let {left, bottom} = element.getBoundingClientRect()

            helper.popupMenu(template, left, bottom)
        }
    }

    componentDidMount() {
        window.addEventListener('resize', () => this.resize())

        this.resize()
        this.forceUpdate()
    }

    shouldComponentUpdate({show}, {animation}) {
        return animation !== this.state.animation || show || show !== this.props.show
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state.scrollTop !== prevState.scrollTop
        && this.state.scrollTop !== this.gamesListElement.scrollTop) {
            // Update scroll top

            this.gamesListElement.scrollTop = this.state.scrollTop
            this.setState({scrollTop: this.gamesListElement.scrollTop})
        }

        if (this.props.show && prevProps.gameTrees.length < this.props.gameTrees.length) {
            // Scroll down

            this.gamesListElement.scrollTop = this.gamesListElement.scrollHeight
            this.setState({scrollTop: this.gamesListElement.scrollTop})
        }

        if (!prevProps.show && this.props.show) {
            // Scroll current list element into view

            let index = this.shownGameTrees.findIndex(([, i]) => i === this.props.gameIndex)
            let scrollTop = 0
            if (index >= 0) scrollTop = this.getRowFromIndex(index) * itemHeight

            this.gamesListElement.scrollTop = scrollTop
            this.setState({scrollTop: this.gamesListElement.scrollTop})
        }

        if (prevProps.show !== this.props.show) {
            // Animate

            let gobanRect = document.getElementById('goban').getBoundingClientRect()
            let drawerRect = document.getElementById('gamechooser').getBoundingClientRect()

            let itemElement = this.itemElements[this.props.gameIndex]
            let svgElement = itemElement != null ? itemElement.querySelector('svg') : null

            if (itemElement != null && svgElement != null) {
                let {width, height, left, top} = itemElement.querySelector('svg').getBoundingClientRect()

                let miniGobanRect = {
                    left: left - drawerRect.left,
                    top: top - drawerRect.top,
                    width,
                    height
                }

                let direction = this.props.show ? 'reverse' : 'normal'

                this.setState({animation: [miniGobanRect, gobanRect, direction]})
                setTimeout(() => this.setState({animation: null}), 600)
            }
        }
    }

    resize() {
        let innerWidth = this.gamesListElement.offsetWidth - 28
        let height = this.gamesListElement.offsetHeight
        let rowCount = Math.floor(innerWidth / itemMinWidth)

        this.setState({innerWidth, height, rowCount})
    }

    getRowFromIndex(i) {
        return (i - i % this.state.rowCount) / this.state.rowCount
    }

    render({
        show,
        gameTrees,
        gameIndex
    }, {
        filterText,
        animation,
        scrollTop,
        insertBefore,
        rowCount,
        innerWidth,
        height
    }) {
        let itemWidth = Math.floor(innerWidth / rowCount)

        this.shownGameTrees = gameTrees.map((tree, index) => {
            return [tree, index]
        }).filter(([tree]) => {
            let gameInfo = sabaki.getGameInfo(tree)
            let data = Object.keys(gameInfo).map(x => gameInfo[x])

            return data.join(' ').toLowerCase().includes(filterText.toLowerCase())
        })

        return h('div', {onDrop: this.handleCancelDrag},
            h('style', {}, `
                #gamechooser .games-list .placeholder {
                    height: ${(this.getRowFromIndex(this.shownGameTrees.length - 1) + 1) * itemHeight + 20}px;
                }

                #gamechooser .games-list li {
                    width: ${itemWidth - 20}px;
                }
            `, animation && `
                #gamechooser-animation {
                    animation: gamechooser-animation .5s ${animation[2]} forwards;
                }

                @keyframes gamechooser-animation {
                    from {
                        transform: translate(${animation[0].left}px, ${animation[0].top}px);
                        opacity: 1;
                    }
                    to {
                        transform: translate(${animation[1].left}px, ${animation[1].top}px)
                            scale(${animation[1].width / animation[0].width},
                            ${animation[1].height / animation[0].height});
                        opacity: 0;
                    }
                }
            `),

            h(Drawer,
                {
                    type: 'gamechooser',
                    show
                },

                h('h2', {}, t('Manage Games')),

                h('input', {
                    type: 'search',
                    name: 'filter',
                    placeholder: t('Filter'),
                    value: filterText,
                    onInput: this.handleFilterTextChange
                }),

                h('div',
                    {
                        ref: el => this.gamesListElement = el,
                        class: 'games-list',

                        onScroll: this.handleListScroll,
                        onDrop: this.handleItemDrop
                    },

                    h('div', {class: 'placeholder'}),

                    h('ol', {}, this.shownGameTrees.map(([tree, index], i) => {
                        let row = this.getRowFromIndex(i)
                        let itemTop = row * itemHeight + 10
                        let itemLeft = (i - row * rowCount) * itemWidth + 10

                        if (
                            index !== gameIndex
                            && (
                                itemTop + itemHeight * 2 <= scrollTop
                                || itemTop - itemHeight >= scrollTop + height
                            )
                        ) return

                        return h(GameListItem, {
                            ref: item => {
                                if (item != null) this.itemElements[index] = item.element
                            },
                            key: tree.id,
                            tree,
                            top: itemTop,
                            left: itemLeft,
                            draggable: filterText === '',

                            showThumbnail: index !== gameIndex || !animation,
                            insertBefore: insertBefore === index,
                            insertAfter: i === this.shownGameTrees.length - 1
                                && insertBefore === index + 1,

                            onClick: this.handleItemClick,
                            onContextMenu: this.handleItemContextMenu,
                            onDragStart: this.handleItemDragStart,
                            onDragOver: this.handleItemDragOver
                        })
                    }))
                ),

                h('p', {},
                    h('button', {
                        type: 'button',
                        class: 'dropdown',
                        onClick: this.handleAddButtonClick
                    }, t('Add')),

                    h('button', {
                        type: 'button',
                        class: 'dropdown',
                        onClick: this.handleSortButtonClick
                    }, t('Sort By')),

                    h('button', {
                        type: 'button',
                        onClick: this.handleCloseButtonClick
                    }, t('Close'))
                )
            ),

            h('div',
                {
                    id: 'gamechooser-animation',
                    style: !animation ? {
                        opacity: 0,
                        pointerEvents: 'none'
                    } : {}
                },

                h(MiniGoban, {
                    board: getPreviewBoard(gameTrees[gameIndex]),
                    maxSize: thumbnailSize
                })
            )
        )
    }
}

module.exports = GameChooserDrawer
<|endoftext|>


<commit_before>import { templateParser, parseQuotasUsage, parseComponents } from '../utils';
import { templateComparator } from './openstack-template';

// @ngInject
export default class openstackTenantChangePackageService {
  // Public API consists of two methods:
  // * loadData - returns promise with fields {package, template, templates}
  // * saveData - accepts dictionary with fields {tenant, package, template, newTemplate}

  constructor(
    $q,
    resourcesService,
    packageTemplatesService,
    openstackPackagesService,
    ncUtilsFlash) {
    this.$q = $q;
    this.resourcesService = resourcesService;
    this.packageTemplatesService = packageTemplatesService;
    this.openstackPackagesService = openstackPackagesService;
    this.ncUtilsFlash = ncUtilsFlash;
  }

  loadData(tenant) {
    let context = { tenant };
    return this.loadTenantQuotasUsage(context)
          .then(this.loadTenantPackage.bind(this))
          .then(this.loadPackageTemplate.bind(this))
          .then(this.loadTemplates.bind(this));
  }

  saveData(context) {
    return this.changePackage(context).then(() => {
      return this.loadTenant(context).then(tenant => {
        this.ncUtilsFlash.success(gettext('Tenant package has been changed.'));
        return tenant;
      });
    }).catch(response => {
      this.ncUtilsFlash.error(gettext('Unable to change tenant package.'));
      return this.$q.reject(response);
    });
  }

  // Private API section

  loadTenantQuotasUsage(context) {
    return this.loadTenant(context).then(tenant => angular.extend(context, {
      quotas: parseQuotasUsage(tenant.quotas)
    }));
  }

  loadTenant(context) {
    return this.resourcesService.$get(null, null, context.tenant.url)
  }

  loadTenantPackage(context) {
    return this.openstackPackagesService.getList({
      tenant_uuid: context.tenant.uuid
    }).then(packages => {
      if (packages.length === 1) {
        return angular.extend(context, {
          package: packages[0]
        });
      } else {
        return this.$q.reject();
      }
    });
  }

  loadPackageTemplate(context) {
    return this.packageTemplatesService.$get(
      null, context.package.template
    ).then(template => angular.extend(context, {
      template: templateParser(template)
    }));
  }

  loadTemplates(context) {
    return this.packageTemplatesService.getAll({
      service_settings_uuid: context.tenant.service_settings_uuid,
      archived: 'False',
    }).then(templates => angular.extend(context, {
      templates: templates
        .map(templateParser)
        .filter(this.checkTemplate.bind(this, context))
        .sort(templateComparator)
    }));
  }

  checkTemplate(context, template) {
    // Exclude current package template
    if (template.uuid === context.template.uuid) {
      return false;
    }

    // Allow to change package only if current usage of all quotas <= new package quotas
    const components = parseComponents(template.components);
    return (
      context.quotas.cores <= components.cores &&
      context.quotas.ram <= components.ram &&
      context.quotas.disk <= components.disk);
  }

  changePackage(context) {
    return this.openstackPackagesService.change(context.package.uuid, context.newTemplate.uuid);
  }
}
<commit_msg>Add dangling semicolon [WAL-812]<commit_after>import { templateParser, parseQuotasUsage, parseComponents } from '../utils';
import { templateComparator } from './openstack-template';

// @ngInject
export default class openstackTenantChangePackageService {
  // Public API consists of two methods:
  // * loadData - returns promise with fields {package, template, templates}
  // * saveData - accepts dictionary with fields {tenant, package, template, newTemplate}

  constructor(
    $q,
    resourcesService,
    packageTemplatesService,
    openstackPackagesService,
    ncUtilsFlash) {
    this.$q = $q;
    this.resourcesService = resourcesService;
    this.packageTemplatesService = packageTemplatesService;
    this.openstackPackagesService = openstackPackagesService;
    this.ncUtilsFlash = ncUtilsFlash;
  }

  loadData(tenant) {
    let context = { tenant };
    return this.loadTenantQuotasUsage(context)
          .then(this.loadTenantPackage.bind(this))
          .then(this.loadPackageTemplate.bind(this))
          .then(this.loadTemplates.bind(this));
  }

  saveData(context) {
    return this.changePackage(context).then(() => {
      return this.loadTenant(context).then(tenant => {
        this.ncUtilsFlash.success(gettext('Tenant package has been changed.'));
        return tenant;
      });
    }).catch(response => {
      this.ncUtilsFlash.error(gettext('Unable to change tenant package.'));
      return this.$q.reject(response);
    });
  }

  // Private API section

  loadTenantQuotasUsage(context) {
    return this.loadTenant(context).then(tenant => angular.extend(context, {
      quotas: parseQuotasUsage(tenant.quotas)
    }));
  }

  loadTenant(context) {
    return this.resourcesService.$get(null, null, context.tenant.url);
  }

  loadTenantPackage(context) {
    return this.openstackPackagesService.getList({
      tenant_uuid: context.tenant.uuid
    }).then(packages => {
      if (packages.length === 1) {
        return angular.extend(context, {
          package: packages[0]
        });
      } else {
        return this.$q.reject();
      }
    });
  }

  loadPackageTemplate(context) {
    return this.packageTemplatesService.$get(
      null, context.package.template
    ).then(template => angular.extend(context, {
      template: templateParser(template)
    }));
  }

  loadTemplates(context) {
    return this.packageTemplatesService.getAll({
      service_settings_uuid: context.tenant.service_settings_uuid,
      archived: 'False',
    }).then(templates => angular.extend(context, {
      templates: templates
        .map(templateParser)
        .filter(this.checkTemplate.bind(this, context))
        .sort(templateComparator)
    }));
  }

  checkTemplate(context, template) {
    // Exclude current package template
    if (template.uuid === context.template.uuid) {
      return false;
    }

    // Allow to change package only if current usage of all quotas <= new package quotas
    const components = parseComponents(template.components);
    return (
      context.quotas.cores <= components.cores &&
      context.quotas.ram <= components.ram &&
      context.quotas.disk <= components.disk);
  }

  changePackage(context) {
    return this.openstackPackagesService.change(context.package.uuid, context.newTemplate.uuid);
  }
}
<|endoftext|>


<commit_before><commit_msg>DB: Changed datatype of items.custom to JSON<commit_after><|endoftext|>