<commit_before>/**
 * @unrestricted
 */
SDK.HeapProfilerModel = class extends SDK.SDKModel {
  /**
   * @param {!SDK.Target} target
   */
  constructor(target) {
    super(target);
    target.registerHeapProfilerDispatcher(new SDK.HeapProfilerDispatcher(this));
    this._enabled = false;
    this._heapProfilerAgent = target.heapProfilerAgent();
    this._memoryAgent = target.memoryAgent();
    this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
  }

  /**
   * @return {!SDK.DebuggerModel}
   */
  debuggerModel() {
    return this._runtimeModel.debuggerModel();
  }

  /**
   * @return {!SDK.RuntimeModel}
   */
  runtimeModel() {
    return this._runtimeModel;
  }

  enable() {
    if (this._enabled)
      return;

    this._enabled = true;
    this._heapProfilerAgent.enable();
  }

  /**
   * @param {number=} samplingRateInBytes
   */
  startSampling(samplingRateInBytes) {
    const defaultSamplingIntervalInBytes = 16384;
    this._heapProfilerAgent.startSampling(samplingRateInBytes || defaultSamplingIntervalInBytes);
  }

  /**
   * @return {!Promise<?Protocol.HeapProfiler.SamplingHeapProfile>}
   */
  stopSampling() {
    return this._heapProfilerAgent.stopSampling();
  }

  /**
   * @return {!Promise<?Protocol.HeapProfiler.SamplingHeapProfile>}
   */
  getSamplingProfile() {
    return this._heapProfilerAgent.getSamplingProfile();
  }

  startNativeSampling() {
    const defaultSamplingIntervalInBytes = 65536;
    this._memoryAgent.startSampling(defaultSamplingIntervalInBytes);
  }

  /**
   * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
   */
  async stopNativeSampling() {
    const rawProfile = await this._memoryAgent.getSamplingProfile();
    this._memoryAgent.stopSampling();
    return this._convertNativeProfile(rawProfile);
  }

  /**
   * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
   */
  async takeNativeSnapshot() {
    const rawProfile = await this._memoryAgent.getAllTimeSamplingProfile();
    return this._convertNativeProfile(rawProfile);
  }

  /**
   * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
   */
  async takeNativeBrowserSnapshot() {
    const rawProfile = await this._memoryAgent.getBrowserSamplingProfile();
    return this._convertNativeProfile(rawProfile);
  }

  /**
   * @param {!Protocol.Memory.SamplingProfile} rawProfile
   * @return {!SDK.HeapProfilerModel.NativeHeapProfile}
   */
  _convertNativeProfile(rawProfile) {
    const head = /** @type {!Protocol.HeapProfiler.SamplingHeapProfileNode} */
        ({children: new Map(), selfSize: 0, callFrame: {functionName: '(root)', url: ''}});
    for (const sample of rawProfile.samples) {
      const node = sample.stack.reverse().reduce((node, name) => {
        let child = node.children.get(name);
        if (child)
          return child;
        const namespace = /^([^:]*)::/.exec(name);
        child = {
          children: new Map(),
          callFrame: {functionName: name, url: namespace && namespace[1] || ''},
          selfSize: 0
        };
        node.children.set(name, child);
        return child;
      }, head);
      node.selfSize += sample.total;
    }

    function convertChildren(node) {
      node.children = Array.from(node.children.values());
      node.children.forEach(convertChildren);
    }
    convertChildren(head);

    return new SDK.HeapProfilerModel.NativeHeapProfile(head, rawProfile.modules);
  }

  /**
   * @return {!Promise}
   */
  collectGarbage() {
    return this._heapProfilerAgent.collectGarbage();
  }

  /**
   * @param {string} objectId
   * @return {!Promise<?string>}
   */
  snapshotObjectIdForObjectId(objectId) {
    return this._heapProfilerAgent.getHeapObjectId(objectId);
  }

  /**
   * @param {string} snapshotObjectId
   * @param {string} objectGroupName
   * @return {!Promise<?SDK.RemoteObject>}
   */
  async objectForSnapshotObjectId(snapshotObjectId, objectGroupName) {
    const result = await this._heapProfilerAgent.getObjectByHeapObjectId(snapshotObjectId, objectGroupName);
    return result && result.type && this._runtimeModel.createRemoteObject(result) || null;
  }

  /**
   * @param {string} snapshotObjectId
   * @return {!Promise}
   */
  addInspectedHeapObject(snapshotObjectId) {
    return this._heapProfilerAgent.addInspectedHeapObject(snapshotObjectId);
  }

  /**
   * @param {boolean} reportProgress
   * @return {!Promise}
   */
  takeHeapSnapshot(reportProgress) {
    return this._heapProfilerAgent.takeHeapSnapshot(reportProgress);
  }

  /**
   * @param {boolean} recordAllocationStacks
   * @return {!Promise}
   */
  startTrackingHeapObjects(recordAllocationStacks) {
    return this._heapProfilerAgent.startTrackingHeapObjects(recordAllocationStacks);
  }

  /**
   * @param {boolean} reportProgress
   * @return {!Promise}
   */
  stopTrackingHeapObjects(reportProgress) {
    return this._heapProfilerAgent.stopTrackingHeapObjects(reportProgress);
  }

  /**
   * @param {!Array<number>} samples
   */
  heapStatsUpdate(samples) {
    this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.HeapStatsUpdate, samples);
  }

  /**
   * @param {number} lastSeenObjectId
   * @param {number} timestamp
   */
  lastSeenObjectId(lastSeenObjectId, timestamp) {
    this.dispatchEventToListeners(
        SDK.HeapProfilerModel.Events.LastSeenObjectId, {lastSeenObjectId: lastSeenObjectId, timestamp: timestamp});
  }

  /**
   * @param {string} chunk
   */
  addHeapSnapshotChunk(chunk) {
    this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.AddHeapSnapshotChunk, chunk);
  }

  /**
   * @param {number} done
   * @param {number} total
   * @param {boolean=} finished
   */
  reportHeapSnapshotProgress(done, total, finished) {
    this.dispatchEventToListeners(
        SDK.HeapProfilerModel.Events.ReportHeapSnapshotProgress, {done: done, total: total, finished: finished});
  }

  resetProfiles() {
    this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.ResetProfiles, this);
  }
};

SDK.SDKModel.register(SDK.HeapProfilerModel, SDK.Target.Capability.JS, false);

/** @enum {symbol} */
SDK.HeapProfilerModel.Events = {
  HeapStatsUpdate: Symbol('HeapStatsUpdate'),
  LastSeenObjectId: Symbol('LastSeenObjectId'),
  AddHeapSnapshotChunk: Symbol('AddHeapSnapshotChunk'),
  ReportHeapSnapshotProgress: Symbol('ReportHeapSnapshotProgress'),
  ResetProfiles: Symbol('ResetProfiles')
};

/**
 * @extends {Protocol.HeapProfiler.SamplingHeapProfile}
 */
SDK.HeapProfilerModel.NativeHeapProfile = class {
  /**
   * @param {!Protocol.HeapProfiler.SamplingHeapProfileNode} head
   * @param {!Array<!Protocol.Memory.Module>} modules
   */
  constructor(head, modules) {
    this.head = head;
    this.modules = modules;
  }
};

/**
 * @extends {Protocol.HeapProfilerDispatcher}
 * @unrestricted
 */
SDK.HeapProfilerDispatcher = class {
  constructor(model) {
    this._heapProfilerModel = model;
  }

  /**
   * @override
   * @param {!Array.<number>} samples
   */
  heapStatsUpdate(samples) {
    this._heapProfilerModel.heapStatsUpdate(samples);
  }

  /**
   * @override
   * @param {number} lastSeenObjectId
   * @param {number} timestamp
   */
  lastSeenObjectId(lastSeenObjectId, timestamp) {
    this._heapProfilerModel.lastSeenObjectId(lastSeenObjectId, timestamp);
  }

  /**
   * @override
   * @param {string} chunk
   */
  addHeapSnapshotChunk(chunk) {
    this._heapProfilerModel.addHeapSnapshotChunk(chunk);
  }

  /**
   * @override
   * @param {number} done
   * @param {number} total
   * @param {boolean=} finished
   */
  reportHeapSnapshotProgress(done, total, finished) {
    this._heapProfilerModel.reportHeapSnapshotProgress(done, total, finished);
  }

  /**
   * @override
   */
  resetProfiles() {
    this._heapProfilerModel.resetProfiles();
  }
};
<commit_msg>DevTools: Support multiple simulateneous sampling heap profiles.<commit_after>/**
 * @unrestricted
 */
SDK.HeapProfilerModel = class extends SDK.SDKModel {
  /**
   * @param {!SDK.Target} target
   */
  constructor(target) {
    super(target);
    target.registerHeapProfilerDispatcher(new SDK.HeapProfilerDispatcher(this));
    this._enabled = false;
    this._heapProfilerAgent = target.heapProfilerAgent();
    this._memoryAgent = target.memoryAgent();
    this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
    this._samplingProfilerDepth = 0;
  }

  /**
   * @return {!SDK.DebuggerModel}
   */
  debuggerModel() {
    return this._runtimeModel.debuggerModel();
  }

  /**
   * @return {!SDK.RuntimeModel}
   */
  runtimeModel() {
    return this._runtimeModel;
  }

  enable() {
    if (this._enabled)
      return;

    this._enabled = true;
    this._heapProfilerAgent.enable();
  }

  /**
   * @param {number=} samplingRateInBytes
   */
  startSampling(samplingRateInBytes) {
    if (this._samplingProfilerDepth++)
      return;
    const defaultSamplingIntervalInBytes = 16384;
    this._heapProfilerAgent.startSampling(samplingRateInBytes || defaultSamplingIntervalInBytes);
  }

  /**
   * @return {!Promise<?Protocol.HeapProfiler.SamplingHeapProfile>}
   */
  stopSampling() {
    if (!this._samplingProfilerDepth)
      throw new Error('Sampling profiler is not running.');
    if (--this._samplingProfilerDepth)
      return this.getSamplingProfile();
    return this._heapProfilerAgent.stopSampling();
  }

  /**
   * @return {!Promise<?Protocol.HeapProfiler.SamplingHeapProfile>}
   */
  getSamplingProfile() {
    return this._heapProfilerAgent.getSamplingProfile();
  }

  startNativeSampling() {
    const defaultSamplingIntervalInBytes = 65536;
    this._memoryAgent.startSampling(defaultSamplingIntervalInBytes);
  }

  /**
   * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
   */
  async stopNativeSampling() {
    const rawProfile = await this._memoryAgent.getSamplingProfile();
    this._memoryAgent.stopSampling();
    return this._convertNativeProfile(rawProfile);
  }

  /**
   * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
   */
  async takeNativeSnapshot() {
    const rawProfile = await this._memoryAgent.getAllTimeSamplingProfile();
    return this._convertNativeProfile(rawProfile);
  }

  /**
   * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
   */
  async takeNativeBrowserSnapshot() {
    const rawProfile = await this._memoryAgent.getBrowserSamplingProfile();
    return this._convertNativeProfile(rawProfile);
  }

  /**
   * @param {!Protocol.Memory.SamplingProfile} rawProfile
   * @return {!SDK.HeapProfilerModel.NativeHeapProfile}
   */
  _convertNativeProfile(rawProfile) {
    const head = /** @type {!Protocol.HeapProfiler.SamplingHeapProfileNode} */
        ({children: new Map(), selfSize: 0, callFrame: {functionName: '(root)', url: ''}});
    for (const sample of rawProfile.samples) {
      const node = sample.stack.reverse().reduce((node, name) => {
        let child = node.children.get(name);
        if (child)
          return child;
        const namespace = /^([^:]*)::/.exec(name);
        child = {
          children: new Map(),
          callFrame: {functionName: name, url: namespace && namespace[1] || ''},
          selfSize: 0
        };
        node.children.set(name, child);
        return child;
      }, head);
      node.selfSize += sample.total;
    }

    function convertChildren(node) {
      node.children = Array.from(node.children.values());
      node.children.forEach(convertChildren);
    }
    convertChildren(head);

    return new SDK.HeapProfilerModel.NativeHeapProfile(head, rawProfile.modules);
  }

  /**
   * @return {!Promise}
   */
  collectGarbage() {
    return this._heapProfilerAgent.collectGarbage();
  }

  /**
   * @param {string} objectId
   * @return {!Promise<?string>}
   */
  snapshotObjectIdForObjectId(objectId) {
    return this._heapProfilerAgent.getHeapObjectId(objectId);
  }

  /**
   * @param {string} snapshotObjectId
   * @param {string} objectGroupName
   * @return {!Promise<?SDK.RemoteObject>}
   */
  async objectForSnapshotObjectId(snapshotObjectId, objectGroupName) {
    const result = await this._heapProfilerAgent.getObjectByHeapObjectId(snapshotObjectId, objectGroupName);
    return result && result.type && this._runtimeModel.createRemoteObject(result) || null;
  }

  /**
   * @param {string} snapshotObjectId
   * @return {!Promise}
   */
  addInspectedHeapObject(snapshotObjectId) {
    return this._heapProfilerAgent.addInspectedHeapObject(snapshotObjectId);
  }

  /**
   * @param {boolean} reportProgress
   * @return {!Promise}
   */
  takeHeapSnapshot(reportProgress) {
    return this._heapProfilerAgent.takeHeapSnapshot(reportProgress);
  }

  /**
   * @param {boolean} recordAllocationStacks
   * @return {!Promise}
   */
  startTrackingHeapObjects(recordAllocationStacks) {
    return this._heapProfilerAgent.startTrackingHeapObjects(recordAllocationStacks);
  }

  /**
   * @param {boolean} reportProgress
   * @return {!Promise}
   */
  stopTrackingHeapObjects(reportProgress) {
    return this._heapProfilerAgent.stopTrackingHeapObjects(reportProgress);
  }

  /**
   * @param {!Array<number>} samples
   */
  heapStatsUpdate(samples) {
    this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.HeapStatsUpdate, samples);
  }

  /**
   * @param {number} lastSeenObjectId
   * @param {number} timestamp
   */
  lastSeenObjectId(lastSeenObjectId, timestamp) {
    this.dispatchEventToListeners(
        SDK.HeapProfilerModel.Events.LastSeenObjectId, {lastSeenObjectId: lastSeenObjectId, timestamp: timestamp});
  }

  /**
   * @param {string} chunk
   */
  addHeapSnapshotChunk(chunk) {
    this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.AddHeapSnapshotChunk, chunk);
  }

  /**
   * @param {number} done
   * @param {number} total
   * @param {boolean=} finished
   */
  reportHeapSnapshotProgress(done, total, finished) {
    this.dispatchEventToListeners(
        SDK.HeapProfilerModel.Events.ReportHeapSnapshotProgress, {done: done, total: total, finished: finished});
  }

  resetProfiles() {
    this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.ResetProfiles, this);
  }
};

SDK.SDKModel.register(SDK.HeapProfilerModel, SDK.Target.Capability.JS, false);

/** @enum {symbol} */
SDK.HeapProfilerModel.Events = {
  HeapStatsUpdate: Symbol('HeapStatsUpdate'),
  LastSeenObjectId: Symbol('LastSeenObjectId'),
  AddHeapSnapshotChunk: Symbol('AddHeapSnapshotChunk'),
  ReportHeapSnapshotProgress: Symbol('ReportHeapSnapshotProgress'),
  ResetProfiles: Symbol('ResetProfiles')
};

/**
 * @extends {Protocol.HeapProfiler.SamplingHeapProfile}
 */
SDK.HeapProfilerModel.NativeHeapProfile = class {
  /**
   * @param {!Protocol.HeapProfiler.SamplingHeapProfileNode} head
   * @param {!Array<!Protocol.Memory.Module>} modules
   */
  constructor(head, modules) {
    this.head = head;
    this.modules = modules;
  }
};

/**
 * @extends {Protocol.HeapProfilerDispatcher}
 * @unrestricted
 */
SDK.HeapProfilerDispatcher = class {
  constructor(model) {
    this._heapProfilerModel = model;
  }

  /**
   * @override
   * @param {!Array.<number>} samples
   */
  heapStatsUpdate(samples) {
    this._heapProfilerModel.heapStatsUpdate(samples);
  }

  /**
   * @override
   * @param {number} lastSeenObjectId
   * @param {number} timestamp
   */
  lastSeenObjectId(lastSeenObjectId, timestamp) {
    this._heapProfilerModel.lastSeenObjectId(lastSeenObjectId, timestamp);
  }

  /**
   * @override
   * @param {string} chunk
   */
  addHeapSnapshotChunk(chunk) {
    this._heapProfilerModel.addHeapSnapshotChunk(chunk);
  }

  /**
   * @override
   * @param {number} done
   * @param {number} total
   * @param {boolean=} finished
   */
  reportHeapSnapshotProgress(done, total, finished) {
    this._heapProfilerModel.reportHeapSnapshotProgress(done, total, finished);
  }

  /**
   * @override
   */
  resetProfiles() {
    this._heapProfilerModel.resetProfiles();
  }
};
<|endoftext|>


<commit_before>var source = new EventSource('/export/updates');

source.onopen = function() {
  document.querySelectorAll('.fusiontable').forEach(function($table) {
    $table.classList.add('fusiontable--loading');
  });
};

source.addEventListener('message', function(event) {
  var data = JSON.parse(event.data);

  if (!data) {
    return;
  }

  var $listEntry = document.querySelector(
    '.fusiontable[data-id="' + data.table.id + '"]'
  );

  $listEntry.classList.remove('fusiontable--loading');
  $listEntry.classList.add('fusiontable--success');

  var driveLink = '';

  if (data.driveFile.mimeType === 'application/vnd.google-apps.spreadsheet') {
    driveLink = ' Open Spreadsheet';
  } else {
    driveLink = ' Open Drive';
  }

  $listEntry.innerHTML += driveLink
}, false);
<commit_msg>feat: show direct link to CSV<commit_after>var source = new EventSource('/export/updates');

source.onopen = function() {
  document.querySelectorAll('.fusiontable').forEach(function($table) {
    $table.classList.add('fusiontable--loading');
  });
};

source.addEventListener('message', function(event) {
  var data = JSON.parse(event.data);

  if (!data) {
    return;
  }

  var $listEntry = document.querySelector(
    '.fusiontable[data-id="' + data.table.id + '"]'
  );

  $listEntry.classList.remove('fusiontable--loading');
  $listEntry.classList.add('fusiontable--success');

  var driveLink = '';

  if (data.driveFile.mimeType === 'application/vnd.google-apps.spreadsheet') {
    driveLink = ' Open Spreadsheet';
  } else {
    driveLink = ' Open CSV';
  }

  $listEntry.innerHTML += driveLink
}, false);
<|endoftext|>


<commit_before>import { check } from 'express-validator/check';

import {
  ifNoUser401,
  createValidatorErrorHandler
} from '../utils/middleware';
import { themes } from '../../common/utils/themes.js';
import { alertTypes } from '../../common/utils/flash.js';

export default function settingsController(app) {
  const api = app.loopback.Router();
  const toggleUserFlag = (flag, req, res, next) => {
    const { user } = req;
    const currentValue = user[ flag ];
    return user
      .update$({ [ flag ]: !currentValue })
      .subscribe(
        () => res.status(200).json({
          flag,
          value: !currentValue
        }),
        next
      );
  };

  function refetchCompletedChallenges(req, res, next) {
    const { user } = req;
    return user.requestCompletedChallenges()
      .subscribe(
        completedChallenges => res.json({ completedChallenges }),
        next
      );
  }

  const updateMyEmailValidators = [
    check('email')
      .isEmail()
      .withMessage('Email format is invalid.')
  ];

  function updateMyEmail(req, res, next) {
    const { user, body: { email } } = req;
    return user.requestUpdateEmail(email)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  const updateMyCurrentChallengeValidators = [
    check('currentChallengeId')
      .isMongoId()
      .withMessage('currentChallengeId is not a valid challenge ID')
  ];

  function updateMyCurrentChallenge(req, res, next) {
    const { user, body: { currentChallengeId } } = req;
    return user.update$({ currentChallengeId }).subscribe(
      () => res.json({
        message:
          `your current challenge has been updated to ${currentChallengeId}`
      }),
      next
    );
  }

  const updateMyThemeValidators = [
    check('theme')
    .isIn(Object.keys(themes))
    .withMessage('Theme is invalid.')
  ];

  function updateMyTheme(req, res, next) {
    const { body: { theme } } = req;
    if (req.user.theme === theme) {
      return res.sendFlash(alertTypes.info, 'Theme already set');
    }
    return req.user.updateTheme(theme)
    .then(
      () => res.sendFlash(alertTypes.info, 'Your theme has been updated'),
      next
    );
  }

  function updateFlags(req, res, next) {
    const { user, body: { values } } = req;
    const keys = Object.keys(values);
    if (
      keys.length === 1 &&
      typeof keys[0] === 'boolean'
    ) {
      return toggleUserFlag(keys[0], req, res, next);
    }
    return user.requestUpdateFlags(values)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  function updateMyPortfolio(req, res, next) {
    const {
      user,
      body: { portfolio }
    } = req;
    // if we only have one key, it should be the id
    // user cannot send only one key to this route
    // other than to remove a portfolio item
    const requestDelete = Object.keys(portfolio).length === 1;
    return user.updateMyPortfolio(portfolio, requestDelete)
      .subscribe(
        message => res.json({ message }),
        next
      );
    }

  function updateMyProfileUI(req, res, next) {
    const {
      user,
      body: { profileUI }
    } = req;
    return user.updateMyProfileUI(profileUI)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  function updateMyProjects(req, res, next) {
    const {
      user,
      body: { projects: project }
    } = req;
    return user.updateMyProjects(project)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  function updateMyUsername(req, res, next) {
    const { user, body: { username } } = req;
    return user.updateMyUsername(username)
    .subscribe(
      message => res.json({ message }),
      next
    );
  }

  api.post(
    '/refetch-user-completed-challenges',
    ifNoUser401,
    refetchCompletedChallenges
  );
  api.post(
    '/update-flags',
    ifNoUser401,
    updateFlags
  );
  api.post(
    '/update-my-email',
    ifNoUser401,
    updateMyEmailValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyEmail
  );
  api.post(
    '/update-my-current-challenge',
    ifNoUser401,
    updateMyCurrentChallengeValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyCurrentChallenge
  );
  api.post(
    '/update-my-portfolio',
    ifNoUser401,
    updateMyPortfolio
  );
  api.post(
    '/update-my-profile-ui',
    ifNoUser401,
    updateMyProfileUI
  );
  api.post(
    '/update-my-projects',
    ifNoUser401,
    updateMyProjects
  );
  api.post(
    '/update-my-theme',
    ifNoUser401,
    updateMyThemeValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyTheme
  );
  api.post(
    '/update-my-username',
    ifNoUser401,
    updateMyUsername
  );

  app.use(api);
}
<commit_msg>feat(ext): Add /external/update-my-current-challenge endpoint (#17242)<commit_after>import { check } from 'express-validator/check';

import {
  ifNoUser401,
  createValidatorErrorHandler
} from '../utils/middleware';
import { themes } from '../../common/utils/themes.js';
import { alertTypes } from '../../common/utils/flash.js';

export default function settingsController(app) {
  const api = app.loopback.Router();
  const toggleUserFlag = (flag, req, res, next) => {
    const { user } = req;
    const currentValue = user[ flag ];
    return user
      .update$({ [ flag ]: !currentValue })
      .subscribe(
        () => res.status(200).json({
          flag,
          value: !currentValue
        }),
        next
      );
  };

  function refetchCompletedChallenges(req, res, next) {
    const { user } = req;
    return user.requestCompletedChallenges()
      .subscribe(
        completedChallenges => res.json({ completedChallenges }),
        next
      );
  }

  const updateMyEmailValidators = [
    check('email')
      .isEmail()
      .withMessage('Email format is invalid.')
  ];

  function updateMyEmail(req, res, next) {
    const { user, body: { email } } = req;
    return user.requestUpdateEmail(email)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  const updateMyCurrentChallengeValidators = [
    check('currentChallengeId')
      .isMongoId()
      .withMessage('currentChallengeId is not a valid challenge ID')
  ];

  function updateMyCurrentChallenge(req, res, next) {
    const { user, body: { currentChallengeId } } = req;
    return user.update$({ currentChallengeId }).subscribe(
      () => res.json({
        message:
          `your current challenge has been updated to ${currentChallengeId}`
      }),
      next
    );
  }

  const updateMyThemeValidators = [
    check('theme')
    .isIn(Object.keys(themes))
    .withMessage('Theme is invalid.')
  ];

  function updateMyTheme(req, res, next) {
    const { body: { theme } } = req;
    if (req.user.theme === theme) {
      return res.sendFlash(alertTypes.info, 'Theme already set');
    }
    return req.user.updateTheme(theme)
    .then(
      () => res.sendFlash(alertTypes.info, 'Your theme has been updated'),
      next
    );
  }

  function updateFlags(req, res, next) {
    const { user, body: { values } } = req;
    const keys = Object.keys(values);
    if (
      keys.length === 1 &&
      typeof keys[0] === 'boolean'
    ) {
      return toggleUserFlag(keys[0], req, res, next);
    }
    return user.requestUpdateFlags(values)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  function updateMyPortfolio(req, res, next) {
    const {
      user,
      body: { portfolio }
    } = req;
    // if we only have one key, it should be the id
    // user cannot send only one key to this route
    // other than to remove a portfolio item
    const requestDelete = Object.keys(portfolio).length === 1;
    return user.updateMyPortfolio(portfolio, requestDelete)
      .subscribe(
        message => res.json({ message }),
        next
      );
    }

  function updateMyProfileUI(req, res, next) {
    const {
      user,
      body: { profileUI }
    } = req;
    return user.updateMyProfileUI(profileUI)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  function updateMyProjects(req, res, next) {
    const {
      user,
      body: { projects: project }
    } = req;
    return user.updateMyProjects(project)
      .subscribe(
        message => res.json({ message }),
        next
      );
  }

  function updateMyUsername(req, res, next) {
    const { user, body: { username } } = req;
    return user.updateMyUsername(username)
    .subscribe(
      message => res.json({ message }),
      next
    );
  }

  api.post(
    '/refetch-user-completed-challenges',
    ifNoUser401,
    refetchCompletedChallenges
  );
  api.post(
    '/update-flags',
    ifNoUser401,
    updateFlags
  );
  api.post(
    '/update-my-email',
    ifNoUser401,
    updateMyEmailValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyEmail
  );
  api.post(
    '/update-my-current-challenge',
    ifNoUser401,
    updateMyCurrentChallengeValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyCurrentChallenge
  );
  api.post(
    '/external/update-my-current-challenge',
    ifNoUser401,
    updateMyCurrentChallengeValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyCurrentChallenge
  );
  api.post(
    '/update-my-portfolio',
    ifNoUser401,
    updateMyPortfolio
  );
  api.post(
    '/update-my-profile-ui',
    ifNoUser401,
    updateMyProfileUI
  );
  api.post(
    '/update-my-projects',
    ifNoUser401,
    updateMyProjects
  );
  api.post(
    '/update-my-theme',
    ifNoUser401,
    updateMyThemeValidators,
    createValidatorErrorHandler(alertTypes.danger),
    updateMyTheme
  );
  api.post(
    '/update-my-username',
    ifNoUser401,
    updateMyUsername
  );

  app.use(api);
}
<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular.module('formly.onsenui', [
        'formly'
        ]);
})();
<commit_msg>Deleted dist folder<commit_after><|endoftext|>


<commit_before>var Actions = {
    init: function() {
        selectAll = document.getElementById('action-toggle');
        if (selectAll) {
            selectAll.style.display = 'inline';
            addEvent(selectAll, 'change', function() {
                Actions.checker(this.checked);
            });
        }
    },
    checker: function(checked) {
        actionCheckboxes = document.getElementsBySelector('tr input.action-select');
        for(var i = 0; i < actionCheckboxes.length; i++) {
            actionCheckboxes[i].checked = checked;
        }
    }
}

addEvent(window, 'load', Actions.init);
<commit_msg>Fixed #10597 -- select all checkbox on admin changelist now works under IE 6 and 7. Thanks kyle.fox.<commit_after>var Actions = {
    init: function() {
        selectAll = document.getElementById('action-toggle');
        if (selectAll) {
            selectAll.style.display = 'inline';
            addEvent(selectAll, 'click', function() {
                Actions.checker(selectAll.checked);
            });
        }
    },
    checker: function(checked) {
        actionCheckboxes = document.getElementsBySelector('tr input.action-select');
        for(var i = 0; i < actionCheckboxes.length; i++) {
            actionCheckboxes[i].checked = checked;
        }
    }
}

addEvent(window, 'load', Actions.init);
<|endoftext|>


<commit_before>var Tasks = {
  TASK_SAVED_EVENT: 'tasks:task_saved',
  TASK_EDITING_EVENT: 'tasks:task_editing',
  TASK_CANCEL_EDITING_EVENT: 'tasks:task_cancel_editing',

  // events used in sorting
  TASK_IDENTIFY_BY_ROW_EVENT: 'tasks:task_identify',
  TASK_REQUEST_SORT_EVENT: 'tasks:request_sort',

  // events for when the table becomes draggable
  TASKS_DRAGGABLE_EVENT: 'tasks:draggable',
  TASKS_NOT_DRAGGABLE_EVENT: 'tasks:not_draggable',

  HIDE_STATUS_DELAY: 15, // seconds

  load: function(event)
  {
    Tasks.table = $('tasks_list');
    if (!Tasks.table || Tasks.table.hasClassName('archived')) { return; }

    new ModalDialog.Ajax($('add_list'), {
      afterShown: function() {
        var newListName = $('new_list_name');
        if (newListName) { newListName.activate(); }
      }
    });

    Tasks.addRow = $('add_row');

    Tasks.tasksForm = $('tasks_form');
    Tasks.newTaskTableHTML = Tasks.tasksForm.innerHTML;

    Tasks.addRow.observe('click', Tasks.onClickAddTask);

    Tasks.wireSortingEvents();

    var rows = Tasks.table.select('tr.task-row');
    for (var i = 0; i < rows.length; i += 2)
    {
      // NOTE: This makes us depdendent on the order that these
      //       rows are output. That is not good, but this is fast.
      new TaskRow(rows[i + 1], rows[i]);
    }

    Tasks.setHideStatus();

    Tasks.wireHistory();
  },

  wireSortingEvents: function()
  {
    Tasks.table.select('th>a').each(function(sortingLink) {
      sortingLink.observe('click',Tasks.onClickSort);
    });
  },

  wireHistory: function()
  {
    Tasks.onHistoryChange();
    History.Observer.observe('all', Tasks.onHistoryChange);
    History.Observer.start();
  },

  addHistoryEvent: function(data)
  {
    History.setMultiple(data);
  },

  draggable: function()
  {
    return Tasks.table.hasClassName('draggable');
  },

  onHistoryChange: function(name)
  {
    Tasks.sort(History.get('order'), History.get('descending'));
  },

  onClickSort: function(event)
  {
    event.stop();

    var link = event.element();
    link = link.match('a') ? link : link.up('a');
    var headerCell = link.up('th');

    var column = link.href.match(/order=([\w_]+)/)[1];
    var descending = false;

    if (headerCell.match('.sorted.descending'))
    {
      column = null;
    }
    else if (headerCell.match('.sorted'))
    {
      descending = true;
    }

    var data = { order: column || "" };
    if (column && descending) {
      data.descending = true;
    } else {
      data.descending = null;
    }
    Tasks.addHistoryEvent(data);

    Tasks.sort(column,descending);
  },

  sort: function(column,descending)
  {
    Tasks.cancelAll();

    Tasks.table.select('th').each(function(cell){
      ['sorted','descending'].each(function(c){cell.removeClassName(c)});
      if (cell.hasClassName(column)) {
        cell.addClassName('sorted');
        if (descending) {
          cell.addClassName('descending');
        }
      }
    });

    // TaskRows that are listening add themselves to the event.memo array
    var rows = Event.fire(Tasks.table, Tasks.TASK_REQUEST_SORT_EVENT, []).memo;

    // Then we sort them
    rows.sort(function(a,b){
      return a.compareTo(b,column,descending);
    });

    rows.each(function(row){
      row.removeRows();
      row.addRowsBefore(Tasks.addRow);
    });

    if (column && Tasks.table.hasClassName('draggable')) {
      Event.fire(Tasks.table,Tasks.TASKS_NOT_DRAGGABLE_EVENT);
      Tasks.table.removeClassName('draggable');
    } else if (!column && !Tasks.table.hasClassName('draggable')) {
      Event.fire(Tasks.table,Tasks.TASKS_DRAGGABLE_EVENT);
      Tasks.table.addClassName('draggable');
    }
  },

  taskFromRow: function(row)
  {
    // This fires an event asking for the TaskRow object that has this row to identify itself
    var e = Event.fire(Tasks.table, Tasks.TASK_IDENTIFY_BY_ROW_EVENT, { row: row });
    return e.memo.task;
  },

  onClickAddTask: function(event)
  {
    event.stop();

    Tasks.cancelAll();
    // event.memo is set to be the task that was just added by the TaskRow's
    // save method, which fires a TASK_SAVED_EVENT using its editRow as memo
    Tasks.doAddNewTask(Tasks.getNewTaskRow(), event.memo);
  },

  addCanceled: function(event)
  {
    Tasks.addRow.show();
    Event.stopObserving(Tasks.table, Tasks.TASK_SAVED_EVENT, Tasks.addSaved);
    event.stop();
  },

  addSaved: function(event)
  {
    Tasks.onClickAddTask(event);
  },

  doAddNewTask: function(row, existingTask, activateClassName)
  {
    var tbody = Tasks.table.select('tbody')[0];

    Tasks.addRow.remove();
    tbody.insert(row);
    tbody.insert(Tasks.addRow);

    if (existingTask)
    {
      ['context','project'].each(function(className){
        var selector = 'td.' + className + '>input';
        var oldinput = existingTask.select(selector).first();
        var newinput = row.select(selector).first();

        if (newinput && oldinput)
        {
          newinput.setValue(oldinput.getValue());
        }
      });
    }

    var task = new TaskRow(null, row);
    Tasks.table.observe(Tasks.TASK_SAVED_EVENT, Tasks.addSaved);
    row.observe(Tasks.TASK_CANCEL_EDITING_EVENT, Tasks.addCanceled);

    Tasks.addRow.hide();
    task.activate(activateClassName);
  },

  cancelAll: function()
  {
    Event.fire(Tasks.table, Tasks.TASK_EDITING_EVENT);
  },

  loadStatus: function(container)
  {
    //
    // container.select("#status") is broken because disconnected
    // nodes with the same ID as a connected nodes are not OK in this
    // version of prototype. Stupid.
    //
    var status = container.select("div").find(function(div){
      return div.id == "status";
    });

    if (!status)
    {
      return;
    }

    var existingStatus = $("status");
    if (existingStatus)
    {
      existingStatus.innerHTML = status.innerHTML;
      status = existingStatus;
    }
    else
    {
      status.hide();
      Tasks.table.up('div').appendChild(status);
    }

    Tasks.showStatus();
    Tasks.setHideStatus();
  },

  setHideStatus: function()
  {
    if (Tasks.hideStatusTimeout)
    {
      clearTimeout(Tasks.hideStatusTimeout);
    }
    Tasks.hideStatusTimeout = setTimeout(Tasks.hideStatus, Tasks.HIDE_STATUS_DELAY * 1000);
  },

  hideStatus: function()
  {
    var status = $('status');
    if (!status) { return; }

    var subeffects = status.immediateDescendants().collect(function(child){
      return new Effect.Fade(child, { sync: true });
    });

    new Effect.Parallel(subeffects, {
      duration: 0.1,
      afterFinish: function() {
        new Effect.BlindUp(status, { duration: 0.1 });
      }
    });
  },

  showStatus: function()
  {
    var status = $('status');
    if (!status || status.visible()) { return; }

    var subeffects = status.immediateDescendants().collect(function(child){
      child.hide();
      return new Effect.Appear(child, { sync: true });
    });

    new Effect.BlindDown(status, {
      duration: 0.1,
      afterFinish: function() {
        new Effect.Parallel(subeffects, { duration: 0.1 });
      }
    });
  },

  updateStatusFromResponse: function(xhr)
  {
    Tasks.loadStatus(Tasks.containerFromResponse(xhr));
  },

  updateProjects: function(row)
  {
    var project = row.select('td.project>input').first();
    project = project && project.getValue();
    if (!project) { return; }

    DNZO.projects = [project, DNZO.projects.without(project)].flatten();
  },

  updateContexts: function(row)
  {
    var contexts = row.select('td.context>input').first();
    contexts = contexts && contexts.getValue();
    if (!contexts) { return; }

    contexts.split(/[,;\s]+/).each(function(context){
      // copy django's slugify method
      context = context.replace(/[^\w\s-]/, '').strip().toLowerCase();
      context = "@" + context.replace(/[-\s]+/, '-');

      DNZO.contexts = [context, DNZO.contexts.without(context)].flatten();
    });
  },

  saveTask: function(action, row, options)
  {
    var duplicateBySelector = function(from,to,selector) {
      var fromFields = from.select(selector);
      var toFields   = to.select(selector);

      if (fromFields.length != toFields.length) return;

      var i = 0;
      fromFields.each(function(fromField) {
        toFields[i].setValue(fromField.getValue());
        i += 1;
      });
    }

    duplicateBySelector(row, Tasks.tasksForm, 'input[type=text]');
    var chk = 'input[type=checkbox]';

    Tasks.tasksForm.select(chk)[0].checked = row.select(chk)[0].checked;

    var oldAction = Tasks.tasksForm.action;

    Tasks.tasksForm.action = action ? action : oldAction;
    Tasks.tasksForm.request(options);
    Tasks.tasksForm.action = oldAction;

    Tasks.updateProjects(row);
    Tasks.updateContexts(row);
  },

  getNewTaskRow: function()
  {
    var temp = new Element('div');
    temp.innerHTML = Tasks.newTaskTableHTML;
    return temp.select("tr")[0];
  },

  containerFromResponse: function(xhr)
  {
    var temp = new Element('div');
    temp.innerHTML = xhr.responseText;
    return temp;
  },

  showError: function(message)
  {
    if (typeof message == 'undefined')
    {
      message = 'DEFAULT_ERROR';
    }

    var errorContainer = new Element('div', { className: 'error_dialog dialog_content' });

    var h2 = new Element('h2');
    h2.innerHTML = 'Whoops!';
    errorContainer.appendChild(h2);
    var ul = new Element('ul');
    errorContainer.appendChild(ul);

    DNZO.Messages[message].split("\n").each(function(str){
      var li = new Element('li');
      li.innerHTML = str;
      ul.appendChild(li);
    });
    var buttons = new Element('li', { className: 'buttons' });
    buttons.appendChild(new Element('input', { type: 'submit', value: 'OK', className: 'hide_dialog' }));
    ul.appendChild(buttons);

    (new ModalDialog(errorContainer)).show();
  },

  doFail: function(xhr)
  {
    Tasks.showError();
  }
};

Event.observe(window,'load',Tasks.load);
<commit_msg>Adds 'a' key to add a new task, adds double-click to cancel editing currently editing task.<commit_after>var Tasks = {
  TASK_SAVED_EVENT: 'tasks:task_saved',
  TASK_EDITING_EVENT: 'tasks:task_editing',
  TASK_CANCEL_EDITING_EVENT: 'tasks:task_cancel_editing',

  // events used in sorting
  TASK_IDENTIFY_BY_ROW_EVENT: 'tasks:task_identify',
  TASK_REQUEST_SORT_EVENT: 'tasks:request_sort',

  // events for when the table becomes draggable
  TASKS_DRAGGABLE_EVENT: 'tasks:draggable',
  TASKS_NOT_DRAGGABLE_EVENT: 'tasks:not_draggable',

  HIDE_STATUS_DELAY: 15, // seconds

  load: function(event)
  {
    Tasks.table = $('tasks_list');
    if (!Tasks.table || Tasks.table.hasClassName('archived')) { return; }

    new ModalDialog.Ajax($('add_list'), {
      afterShown: function() {
        var newListName = $('new_list_name');
        if (newListName) { newListName.activate(); }
      }
    });

    Tasks.addRow = $('add_row');

    Tasks.tasksForm = $('tasks_form');
    Tasks.newTaskTableHTML = Tasks.tasksForm.innerHTML;

    Tasks.addRow.observe('click', Tasks.onClickAddTask);

    Tasks.wireSortingEvents();

    var rows = Tasks.table.select('tr.task-row');
    for (var i = 0; i < rows.length; i += 2)
    {
      // NOTE: This makes us depdendent on the order that these
      //       rows are output. That is not good, but this is fast.
      new TaskRow(rows[i + 1], rows[i]);
    }

    Event.observe(document, 'dblclick', Tasks.onDoubleClickBody);
    Event.observe(document, 'keypress', Tasks.onKeyPress);

    Tasks.setHideStatus();

    Tasks.wireHistory();
  },

  wireSortingEvents: function()
  {
    Tasks.table.select('th>a').each(function(sortingLink) {
      sortingLink.observe('click',Tasks.onClickSort);
    });
  },

  wireHistory: function()
  {
    Tasks.onHistoryChange();
    History.Observer.observe('all', Tasks.onHistoryChange);
    History.Observer.start();
  },

  addHistoryEvent: function(data)
  {
    History.setMultiple(data);
  },

  draggable: function()
  {
    return Tasks.table.hasClassName('draggable');
  },

  onDoubleClickBody: function(event)
  {
    Tasks.cancelAll();
  },

  onKeyPress: function(event)
  {
    if (event.altKey || !event.isChar)
    {
      return;
    }

    switch(event.charCode)
    {
      case 65:
      case 97:
        var element = event.findElement();
        if (!element.match('input') && !element.match('select'))
        {
          Tasks.onClickAddTask(event);
        }
    }
  },

  onHistoryChange: function(name)
  {
    Tasks.sort(History.get('order'), History.get('descending'));
  },

  onClickSort: function(event)
  {
    event.stop();

    var link = event.element();
    link = link.match('a') ? link : link.up('a');
    var headerCell = link.up('th');

    var column = link.href.match(/order=([\w_]+)/)[1];
    var descending = false;

    if (headerCell.match('.sorted.descending'))
    {
      column = null;
    }
    else if (headerCell.match('.sorted'))
    {
      descending = true;
    }

    var data = { order: column || "" };
    if (column && descending) {
      data.descending = true;
    } else {
      data.descending = null;
    }
    Tasks.addHistoryEvent(data);

    Tasks.sort(column,descending);
  },

  sort: function(column,descending)
  {
    Tasks.cancelAll();

    Tasks.table.select('th').each(function(cell){
      ['sorted','descending'].each(function(c){cell.removeClassName(c)});
      if (cell.hasClassName(column)) {
        cell.addClassName('sorted');
        if (descending) {
          cell.addClassName('descending');
        }
      }
    });

    // TaskRows that are listening add themselves to the event.memo array
    var rows = Event.fire(Tasks.table, Tasks.TASK_REQUEST_SORT_EVENT, []).memo;

    // Then we sort them
    rows.sort(function(a,b){
      return a.compareTo(b,column,descending);
    });

    rows.each(function(row){
      row.removeRows();
      row.addRowsBefore(Tasks.addRow);
    });

    if (column && Tasks.table.hasClassName('draggable')) {
      Event.fire(Tasks.table,Tasks.TASKS_NOT_DRAGGABLE_EVENT);
      Tasks.table.removeClassName('draggable');
    } else if (!column && !Tasks.table.hasClassName('draggable')) {
      Event.fire(Tasks.table,Tasks.TASKS_DRAGGABLE_EVENT);
      Tasks.table.addClassName('draggable');
    }
  },

  taskFromRow: function(row)
  {
    // This fires an event asking for the TaskRow object that has this row to identify itself
    var e = Event.fire(Tasks.table, Tasks.TASK_IDENTIFY_BY_ROW_EVENT, { row: row });
    return e.memo.task;
  },

  onClickAddTask: function(event)
  {
    event.stop();

    Tasks.cancelAll();
    // event.memo is set to be the task that was just added by the TaskRow's
    // save method, which fires a TASK_SAVED_EVENT using its editRow as memo
    Tasks.doAddNewTask(Tasks.getNewTaskRow(), event.memo);
  },

  addCanceled: function(event)
  {
    Tasks.addRow.show();
    Event.stopObserving(Tasks.table, Tasks.TASK_SAVED_EVENT, Tasks.addSaved);
    event.stop();
  },

  addSaved: function(event)
  {
    Tasks.onClickAddTask(event);
  },

  doAddNewTask: function(row, existingTask, activateClassName)
  {
    var tbody = Tasks.table.select('tbody')[0];

    Tasks.addRow.remove();
    tbody.insert(row);
    tbody.insert(Tasks.addRow);

    if (existingTask)
    {
      ['context','project'].each(function(className){
        var selector = 'td.' + className + '>input';
        var oldinput = existingTask.select(selector).first();
        var newinput = row.select(selector).first();

        if (newinput && oldinput)
        {
          newinput.setValue(oldinput.getValue());
        }
      });
    }

    var task = new TaskRow(null, row);
    Tasks.table.observe(Tasks.TASK_SAVED_EVENT, Tasks.addSaved);
    row.observe(Tasks.TASK_CANCEL_EDITING_EVENT, Tasks.addCanceled);

    Tasks.addRow.hide();
    task.activate(activateClassName);
  },

  cancelAll: function()
  {
    Event.fire(Tasks.table, Tasks.TASK_EDITING_EVENT);
  },

  loadStatus: function(container)
  {
    //
    // container.select("#status") is broken because disconnected
    // nodes with the same ID as a connected nodes are not OK in this
    // version of prototype. Stupid.
    //
    var status = container.select("div").find(function(div){
      return div.id == "status";
    });

    if (!status)
    {
      return;
    }

    var existingStatus = $("status");
    if (existingStatus)
    {
      existingStatus.innerHTML = status.innerHTML;
      status = existingStatus;
    }
    else
    {
      status.hide();
      Tasks.table.up('div').appendChild(status);
    }

    Tasks.showStatus();
    Tasks.setHideStatus();
  },

  setHideStatus: function()
  {
    if (Tasks.hideStatusTimeout)
    {
      clearTimeout(Tasks.hideStatusTimeout);
    }
    Tasks.hideStatusTimeout = setTimeout(Tasks.hideStatus, Tasks.HIDE_STATUS_DELAY * 1000);
  },

  hideStatus: function()
  {
    var status = $('status');
    if (!status) { return; }

    var subeffects = status.immediateDescendants().collect(function(child){
      return new Effect.Fade(child, { sync: true });
    });

    new Effect.Parallel(subeffects, {
      duration: 0.1,
      afterFinish: function() {
        new Effect.BlindUp(status, { duration: 0.1 });
      }
    });
  },

  showStatus: function()
  {
    var status = $('status');
    if (!status || status.visible()) { return; }

    var subeffects = status.immediateDescendants().collect(function(child){
      child.hide();
      return new Effect.Appear(child, { sync: true });
    });

    new Effect.BlindDown(status, {
      duration: 0.1,
      afterFinish: function() {
        new Effect.Parallel(subeffects, { duration: 0.1 });
      }
    });
  },

  updateStatusFromResponse: function(xhr)
  {
    Tasks.loadStatus(Tasks.containerFromResponse(xhr));
  },

  updateProjects: function(row)
  {
    var project = row.select('td.project>input').first();
    project = project && project.getValue();
    if (!project) { return; }

    DNZO.projects = [project, DNZO.projects.without(project)].flatten();
  },

  updateContexts: function(row)
  {
    var contexts = row.select('td.context>input').first();
    contexts = contexts && contexts.getValue();
    if (!contexts) { return; }

    contexts.split(/[,;\s]+/).each(function(context){
      // copy django's slugify method
      context = context.replace(/[^\w\s-]/, '').strip().toLowerCase();
      context = "@" + context.replace(/[-\s]+/, '-');

      DNZO.contexts = [context, DNZO.contexts.without(context)].flatten();
    });
  },

  saveTask: function(action, row, options)
  {
    var duplicateBySelector = function(from,to,selector) {
      var fromFields = from.select(selector);
      var toFields   = to.select(selector);

      if (fromFields.length != toFields.length) return;

      var i = 0;
      fromFields.each(function(fromField) {
        toFields[i].setValue(fromField.getValue());
        i += 1;
      });
    }

    duplicateBySelector(row, Tasks.tasksForm, 'input[type=text]');
    var chk = 'input[type=checkbox]';

    Tasks.tasksForm.select(chk)[0].checked = row.select(chk)[0].checked;

    var oldAction = Tasks.tasksForm.action;

    Tasks.tasksForm.action = action ? action : oldAction;
    Tasks.tasksForm.request(options);
    Tasks.tasksForm.action = oldAction;

    Tasks.updateProjects(row);
    Tasks.updateContexts(row);
  },

  getNewTaskRow: function()
  {
    var temp = new Element('div');
    temp.innerHTML = Tasks.newTaskTableHTML;
    return temp.select("tr")[0];
  },

  containerFromResponse: function(xhr)
  {
    var temp = new Element('div');
    temp.innerHTML = xhr.responseText;
    return temp;
  },

  showError: function(message)
  {
    if (typeof message == 'undefined')
    {
      message = 'DEFAULT_ERROR';
    }

    var errorContainer = new Element('div', { className: 'error_dialog dialog_content' });

    var h2 = new Element('h2');
    h2.innerHTML = 'Whoops!';
    errorContainer.appendChild(h2);
    var ul = new Element('ul');
    errorContainer.appendChild(ul);

    DNZO.Messages[message].split("\n").each(function(str){
      var li = new Element('li');
      li.innerHTML = str;
      ul.appendChild(li);
    });
    var buttons = new Element('li', { className: 'buttons' });
    buttons.appendChild(new Element('input', { type: 'submit', value: 'OK', className: 'hide_dialog' }));
    ul.appendChild(buttons);

    (new ModalDialog(errorContainer)).show();
  },

  doFail: function(xhr)
  {
    Tasks.showError();
  }
};

Event.observe(window,'load',Tasks.load);
<|endoftext|>


<commit_before>import { argv } from 'yargs'

const threshold = 0

export default config => ({
  compiler_devtool: 'inline-source-map',
  coverage_enabled: !argv.watch,
  coverage_reporters: [
    { type: 'text-summary' },
    { type: 'html', dir: 'coverage' }
  ],
  coverage_check: {
    global: {
      statements: threshold,
      branches: threshold,
      functions: threshold,
      lines: threshold
    },
    each: {
      statements: threshold,
      branches: threshold,
      functions: threshold,
      lines: threshold
    }
  }
})
<commit_msg>update coverage setting<commit_after>import { argv } from 'yargs'

const threshold = 0

export default config => ({
  compiler_devtool: 'inline-source-map',
  coverage_enabled: !argv.watch,
  coverage_reporters: [
    { type: 'text-summary' },
    { type: 'lcov', dir: 'coverage' }
  ],
  coverage_check: {
    global: {
      statements: threshold,
      branches: threshold,
      functions: threshold,
      lines: threshold
    },
    each: {
      statements: threshold,
      branches: threshold,
      functions: threshold,
      lines: threshold
    }
  }
})
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2017, Ivan Mironchik
 * All rights reserved.
 *
 * This source code is licensed under the license found in the LICENSE file in
 * the root directory of this source tree.
 */

export default {
  entry: './src/index.js',
};<commit_msg>Remove entry<commit_after>/**
 * Copyright (c) 2017, Ivan Mironchik
 * All rights reserved.
 *
 * This source code is licensed under the license found in the LICENSE file in
 * the root directory of this source tree.
 */

export default {};
<|endoftext|>


<commit_before>var data = {
  preview: {
      oki: {
          img: 'oki.jpg',
          url: '/archive/oki.html',
          title: 'FreetoPay-OK — приложение для одноклассников',
          text: 'Верстка для freetopay в виде приложения для одноклассников.',
          date: 'Начало 2012 года',
          class: 'preview--primary'
      },
      ugkh: {
          img: 'ugkh.jpg',
          url: '/archive/ugkh.html',
          title: 'Управление ЖКХ Гомельского облисполкома',
          text: 'На сайте есть все, что касается жилищно-коммунального хозяйства гомельской области и даже чуть-чуть больше.',
          date: 'Октябрь 2010 года',
          class: 'preview--primary'
      },
      kontur: {
          img: 'kontur.png',
          url: '/archive/kontur.html',
          title: 'Тестовое задание на летнюю стажировку СКБ Контур 2014',
          text: 'Весной решил сделать тестовое задание для стажировки, авось прошел бы. В декабре того же года, сделал вариацию используя Extjs.',
          date: 'Весна 2014 года',
          class: ''
      },
      vladlen: {
          img: 'vladlen.png',
          url: '/archive/vladlen.html',
          title: 'Владлен де люкс',
          text: 'Владлен де люкс это магазин профессиональной косметики. Сайт представляет собой полноценный интернет магазин.',
          date: 'Начало 2012 года',
          class: ''
      },
      freeToPay: {
          img: 'free-to-pay.png',
          url: '/archive/free-to-pay.html',
          title: 'Вёрстка freetopay',
          text: 'Новый лучший фритупей. Вариация приложения для одноклассников в светлых тонах.',
          date: 'Середина февраля 2012 года',
          class: ''
      },
      tuanna: {
          img: 'tuanna.png',
          url: '/archive/tuanna.html',
          title: 'Туанна логистик',
          text: 'Комфортный, удобный и привлекательный сайт для логистической компании.',
          date: 'Конец 2011 года',
          class: ''
      },
      getbonus: {
          img: 'getbonus.png',
          url: '/archive/getbonus.html',
          title: 'Вёрстка страницы getbonus',
          text: 'Верстка большой и интересной страницы, с множеством нестандартных элементов.',
          date: 'Декабрь 2011 года',
          class: ''
      },
      superdog: {
          img: 'superdog.jpg',
          url: '/archive/superdog.html',
          title: 'Супердог — Сайт для домашнего любимца',
          text: 'Сайт для владельцев домашних животных и их питомцев. Яркий, красивый и стильный дизайн с прекрасными иллюстрациями.',
          date: 'Апрель 2011 года',
          class: ''
      },
      zemle: {
          img: 'zemle.png',
          url: '/archive/zemle.html',
          title: 'Землеустроительная служба Гомельского облисполкома',
          text: 'Сайт позволяет вам выразить свое мнение по актуальным проблемам земельных отношений,  задать интересующие вопросы и оперативно получить на них ответы.',
          date: 'Зима-весна 2011 года',
          class: ''
      },
      freeToPayOk: {
          img: 'free-to-pay-ok.png',
          url: '/archive/free-to-pay-ok.html',
          title: 'Free to pay',
          text: 'Верстка приложения freetopay для одноклассников. Freetopay это: Офферная система — система монетизации игр, социальных приложений и сетей с помощью рекламных предложений.',
          date: 'Май 2011 года',
          class: ''
      },
      ctolik: {
          img: 'ctolik.png',
          url: '/archive/ctolik.html',
          title: 'Проект Столик',
          text: 'Сайт сотрудничает с заведениями города Гомеля и старается дать максимально полную информацию об услугах, которые они могут предложить.',
          date: '2010-2011 года',
          class: ''
      },
      kiselev: {
          img: 'kiselev.png',
          url: '/archive/kiselev.html',
          title: 'Архитектурная мастерская Сергей Киселев и Партнеры',
          text: 'Сложнейший сайт с уникальным дизайном напичканный всевозможными наворотами, хитростями и скриптами.',
          date: '2010 год',
          class: ''
      },
      studio: {
          img: 'studio.png',
          url: '/archive/studio.html',
          title: 'Киностудия «Студия-А»',
          text: 'Сайт визитка для киностудии «Студия-А». Дизайн сайта сделан в стили минимализма + «управляемый хаос». Светлые цвета делают сайт приятным и легким.',
          date: 'Конец 2010 — начало 2011',
          class: ''
      },
      ubo: {
          img: 'ubo.png',
          url: '/archive/ubo.html',
          title: 'Государственное Учреждение «Управление бытового обслуживания Гомельской области»',
          text: 'На сайте размещается информация о деятельности учреждения, его целях и задачах, а также география и предприятия.',
          date: 'Октябрь 2010 года',
          class: ''
      },
      htmlEmail: {
          img: 'html-email.png',
          url: '/home/html-email.html',
          title: 'Вёрстка html-писем',
          text: 'Создание html-верстки для электронных писем на проекте Dormis.',
          date: 'Август 2016 год',
          class: 'preview--primary'
      },
      sas: {
          img: 'sas.jpg',
          url: '/home/sas.html',
          title: 'Smart automation system',
          text: 'Создание сайта для smart automation system.',
          date: 'Июнь 2015 год',
          class: 'preview--primary'
      },
      bai: {
          img: 'bai.png',
          url: '/home/bai.html',
          title: 'BAI: crm, сайт, админка',
          text: 'Для BAI были переверстаны сайт, и его админская часть, а также страница crm.',
          date: '2016 год',
          class: 'preview--primary'
      },
      dormis: {
          img: 'dormis.jpg',
          url: '/home/dormis.html',
          title: 'Проект Dormis',
          text: 'Вёрстка сайта по бронированию квартир dormis.com.',
          date: '2015-2017 года',
          class: 'preview--primary'
      }
  }
};
<commit_msg>Fix preview text.<commit_after>var data = {
  preview: {
      oki: {
          img: 'oki.jpg',
          url: '/archive/oki.html',
          title: 'FreetoPay-OK — приложение для одноклассников',
          text: 'Верстка для freetopay в виде приложения для одноклассников.',
          date: 'Начало 2012 года',
          class: 'preview--primary'
      },
      ugkh: {
          img: 'ugkh.jpg',
          url: '/archive/ugkh.html',
          title: 'Управление ЖКХ Гомельского облисполкома',
          text: 'На сайте есть все, что касается жилищно-коммунального хозяйства гомельской области и даже чуть-чуть больше.',
          date: 'Октябрь 2010 года',
          class: 'preview--primary'
      },
      kontur: {
          img: 'kontur.png',
          url: '/archive/kontur.html',
          title: 'Тестовое задание на летнюю стажировку СКБ Контур 2014',
          text: 'Весной решил сделать тестовое задание для стажировки, авось прошел бы. В декабре того же года, сделал вариацию используя Extjs.',
          date: 'Весна 2014 года',
          class: ''
      },
      vladlen: {
          img: 'vladlen.png',
          url: '/archive/vladlen.html',
          title: 'Владлен де люкс',
          text: 'Владлен де люкс это магазин профессиональной косметики. Сайт представляет собой полноценный интернет магазин.',
          date: 'Начало 2012 года',
          class: ''
      },
      freeToPay: {
          img: 'free-to-pay.png',
          url: '/archive/free-to-pay.html',
          title: 'Вёрстка freetopay',
          text: 'Новый лучший фритупей. Вариация приложения для одноклассников в светлых тонах.',
          date: 'Середина февраля 2012 года',
          class: ''
      },
      tuanna: {
          img: 'tuanna.png',
          url: '/archive/tuanna.html',
          title: 'Туанна логистик',
          text: 'Комфортный, удобный и привлекательный сайт для логистической компании.',
          date: 'Конец 2011 года',
          class: ''
      },
      getbonus: {
          img: 'getbonus.png',
          url: '/archive/getbonus.html',
          title: 'Вёрстка страницы getbonus',
          text: 'Верстка большой и интересной страницы, с множеством нестандартных элементов.',
          date: 'Декабрь 2011 года',
          class: ''
      },
      superdog: {
          img: 'superdog.jpg',
          url: '/archive/superdog.html',
          title: 'Супердог — Сайт для домашнего любимца',
          text: 'Сайт для владельцев домашних животных и их питомцев. Яркий, красивый и стильный дизайн с прекрасными иллюстрациями.',
          date: 'Апрель 2011 года',
          class: ''
      },
      zemle: {
          img: 'zemle.png',
          url: '/archive/zemle.html',
          title: 'Землеустроительная служба Гомельского облисполкома',
          text: 'Сайт позволяет вам выразить свое мнение по актуальным проблемам земельных отношений,  задать интересующие вопросы и оперативно получить на них ответы.',
          date: 'Зима-весна 2011 года',
          class: ''
      },
      freeToPayOk: {
          img: 'free-to-pay-ok.png',
          url: '/archive/free-to-pay-ok.html',
          title: 'Free to pay',
          text: 'Верстка приложения freetopay для одноклассников. Freetopay это: Офферная система — система монетизации игр, социальных приложений и сетей с помощью рекламных предложений.',
          date: 'Май 2011 года',
          class: ''
      },
      ctolik: {
          img: 'ctolik.png',
          url: '/archive/ctolik.html',
          title: 'Проект Столик',
          text: 'Сайт сотрудничает с заведениями города Гомеля и старается дать максимально полную информацию об услугах, которые они могут предложить.',
          date: '2010-2011 года',
          class: ''
      },
      kiselev: {
          img: 'kiselev.png',
          url: '/archive/kiselev.html',
          title: 'Архитектурная мастерская Сергей Киселев и Партнеры',
          text: 'Сложнейший сайт с уникальным дизайном напичканный всевозможными наворотами, хитростями и скриптами.',
          date: '2010 год',
          class: ''
      },
      studio: {
          img: 'studio.png',
          url: '/archive/studio.html',
          title: 'Киностудия «Студия-А»',
          text: 'Сайт визитка для киностудии «Студия-А». Дизайн сайта сделан в стили минимализма + «управляемый хаос». Светлые цвета делают сайт приятным и легким.',
          date: 'Конец 2010 — начало 2011',
          class: ''
      },
      ubo: {
          img: 'ubo.png',
          url: '/archive/ubo.html',
          title: 'Государственное Учреждение «Управление бытового обслуживания Гомельской области»',
          text: 'На сайте размещается информация о деятельности учреждения, его целях и задачах, а также география и предприятия.',
          date: 'Октябрь 2010 года',
          class: ''
      },
      htmlEmail: {
          img: 'html-email.png',
          url: '/home/html-email.html',
          title: 'Вёрстка html-писем',
          text: 'Создание html-верстки для электронных писем на проекте Dormis.',
          date: 'Август 2016 год',
          class: 'preview--primary'
      },
      sas: {
          img: 'sas.jpg',
          url: '/home/sas.html',
          title: 'Smart automation system',
          text: 'Создание сайта для smart automation system - проект умного дома.',
          date: 'Июнь 2015 год',
          class: 'preview--primary'
      },
      bai: {
          img: 'bai.png',
          url: '/home/bai.html',
          title: 'BAI: crm, сайт, админка',
          text: 'Для BAI были переверстаны сайт, и его админская часть, а также страница crm.',
          date: '2016 год',
          class: 'preview--primary'
      },
      dormis: {
          img: 'dormis.jpg',
          url: '/home/dormis.html',
          title: 'Проект Dormis',
          text: 'Вёрстка сайта по поиску и бронированию квартир в различных городах и странах.',
          date: '2015-2017 года',
          class: 'preview--primary'
      }
  }
};
<|endoftext|>


<commit_before>/**
 * Copyright 2016 Google Inc. 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';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const request = require('request-promise');

// List of output languages.
const LANGUAGES = ['en', 'es', 'de', 'fr', 'sv', 'ga', 'it', 'jp'];

// Translate an incoming message.
exports.translate = functions.database.ref('/messages/$languageID/$messageID').onWrite(event => {
  const snapshot = event.data;
  if (snapshot.val().translated) {
    return;
  }
  const paths = snapshot.ref.toString().split('/');
  const promises = [];
  for (let i = 0; i < LANGUAGES.length; i++) {
    var language = LANGUAGES[i];
    if (language !== paths[1]) {
      promises.push(createTranslationPromise(paths[1], language, snapshot));
    }
  }
  return Promise.all(promises);
});

// URL to the Google Translate API.
function createTranslateUrl(source, target, payload) {
  return `https://www.googleapis.com/language/translate/v2?key=${functions.config().firebase.apiKey}&source=${source}&target=${target}&q=${payload}`;
}

function createTranslationPromise(source, target, snapshot) {
  const key = snapshot.key;
  const message = snapshot.val().message;
  return request(createTranslateUrl(source, target, message), {resolveWithFullResponse: true}).then(
      response => {
        if (response.statusCode === 200) {
          const data = JSON.parse(response.body).data;
          return admin.database().ref(`/messages/${target}/${key}`)
              .set({message: data.translations[0].translatedText, translated: true});
        }
        throw response.body;
      });
}
<commit_msg>Fixing wildcards.<commit_after>/**
 * Copyright 2016 Google Inc. 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';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const request = require('request-promise');

// List of output languages.
const LANGUAGES = ['en', 'es', 'de', 'fr', 'sv', 'ga', 'it', 'jp'];

// Translate an incoming message.
exports.translate = functions.database.ref('/messages/{languageID}/{messageID}').onWrite(event => {
  const snapshot = event.data;
  if (snapshot.val().translated) {
    return;
  }
  const paths = snapshot.ref.toString().split('/');
  const promises = [];
  for (let i = 0; i < LANGUAGES.length; i++) {
    var language = LANGUAGES[i];
    if (language !== paths[1]) {
      promises.push(createTranslationPromise(paths[1], language, snapshot));
    }
  }
  return Promise.all(promises);
});

// URL to the Google Translate API.
function createTranslateUrl(source, target, payload) {
  return `https://www.googleapis.com/language/translate/v2?key=${functions.config().firebase.apiKey}&source=${source}&target=${target}&q=${payload}`;
}

function createTranslationPromise(source, target, snapshot) {
  const key = snapshot.key;
  const message = snapshot.val().message;
  return request(createTranslateUrl(source, target, message), {resolveWithFullResponse: true}).then(
      response => {
        if (response.statusCode === 200) {
          const data = JSON.parse(response.body).data;
          return admin.database().ref(`/messages/${target}/${key}`)
              .set({message: data.translations[0].translatedText, translated: true});
        }
        throw response.body;
      });
}
<|endoftext|>


<commit_before><commit_msg>[feat] sets up model for Url's<commit_after>var Sequelize = require("sequelize");

module.exports = function(sequelize, tableConfig) {
  return sequelize.define('url', {
    url: Sequelize.STRING
  }, tableConfig)
}<|endoftext|>


<commit_before>"use strict"
// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

var app = angular.module('faasGateway', ['ngMaterial', 'faasGateway.funcStore']);

app.controller("home", ['$scope', '$log', '$http', '$location', '$interval', '$filter', '$mdDialog', '$mdToast', '$mdSidenav',
    function($scope, $log, $http, $location, $interval, $filter, $mdDialog, $mdToast, $mdSidenav) {
        var FUNCSTORE_DEPLOY_TAB_INDEX = 0;
        var MANUAL_DEPLOY_TAB_INDEX = 1;

        var newFuncTabIdx = FUNCSTORE_DEPLOY_TAB_INDEX;
        $scope.functions = [];
        $scope.invocationInProgress = false;
        $scope.invocationRequest = "";
        $scope.invocationResponse = "";
        $scope.invocationStatus = "";
        $scope.invocationStart = new Date().getTime();
        $scope.roundTripDuration = "";
        $scope.invocation = {
            contentType: "text"
        };

        $scope.baseUrl = $location.absUrl().replace(/\ui\/$/, '');
        try {
            $scope.canCopyToClipboard = document.queryCommandSupported('copy');
        } catch (err) {
            console.error(err);
            $scope.canCopyToClipboard = false;
        }
        $scope.copyClicked = function(e) {
            e.target.parentElement.querySelector('input').select()
            var copySuccessful = false;
            try {
                copySuccessful = document.execCommand('copy');
            } catch (err) {
                console.error(err);
            }
            var msg = copySuccessful ? 'Copied to Clipboard' : 'Copy failed. Please copy it manually';
            showPostInvokedToast(msg);
        }

        $scope.toggleSideNav = function() {
            $mdSidenav('left').toggle();
        };

        $scope.functionTemplate = {
            image: "",
            envProcess: "",
            network: "",
            service: "",
            envVars: {},
            labels: {}
        };

        $scope.invocation.request = "";
        var fetchFunctionsDelay = 3500;
        var queryFunctionDelay = 2500;

        var fetchFunctionsInterval = $interval(function() {
            refreshData();
        }, fetchFunctionsDelay);

        var queryFunctionInterval = $interval(function() {
            if($scope.selectedFunction && $scope.selectedFunction.name) {
                refreshFunction($scope.selectedFunction);
            }
        }, queryFunctionDelay);

        var refreshFunction = function(functionInstance) {
            $http.get("../system/function/" + functionInstance.name)
            .then(function(response) {
                functionInstance.ready = (response.data && response.data.availableReplicas && response.data.availableReplicas > 0);
            })
            .catch(function(err) {
                console.error(err);
            });
        };

        var showPostInvokedToast = function(message, duration) {
            $mdToast.show(
                $mdToast.simple()
                .textContent(message)
                .position("top right")
                .hideDelay(duration || 500)
            );
        };

        $scope.fireRequest = function() {
            var requestContentType = $scope.invocation.contentType == "json" ? "application/json" : "text/plain";
            if ($scope.invocation.contentType == "binary") {
                requestContentType = "binary/octet-stream";
            }

            var options = {
                url: "../function/" + $scope.selectedFunction.name,
                data: $scope.invocation.request,
                method: "POST",
                headers: { "Content-Type": requestContentType },
                responseType: $scope.invocation.contentType == "binary" ? "arraybuffer" : $scope.invocation.contentType
            };

            $scope.invocationInProgress = true;
            $scope.invocationResponse = "";
            $scope.invocationStatus = null;
            $scope.roundTripDuration = "";
            $scope.invocationStart = new Date().getTime()

            var tryDownload = function(data, filename) {
                var caught;

                try {
                    var blob = new Blob([data], { type: "binary/octet-stream" });

                    if (window.navigator.msSaveBlob) { // // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
                        window.navigator.msSaveOrOpenBlob(blob, filename);
                    }
                    else {
                        var linkElement = window.document.createElement("a");
                        linkElement.href = window.URL.createObjectURL(blob);
                        linkElement.download = filename;
                        document.body.appendChild(linkElement);
                        linkElement.click();
                        document.body.removeChild(linkElement);
                    }

                } catch (ex) {
                    caught = ex;
                }
                return caught;
            }

            $http(options)
                .then(function (response) {
                    var data = response.data;
                    var status = response.status;

                    if($scope.invocation.contentType == "binary") {
                        var filename = uuidv4();

                        if($scope.selectedFunction.labels) {
                            var ext = $scope.selectedFunction.labels["com.openfaas.ui.ext"];
                            if(ext && ext.length > 0 ) {
                                filename = filename + "." + ext;
                            }
                        }

                        var caught = tryDownload(data, filename);
                        if(caught) {
                            console.log(caught);
                            $scope.invocationResponse = caught
                        } else {
                            $scope.invocationResponse = data.byteLength + " byte(s) received";
                        }

                    } else {

                        if (typeof data == 'object') {
                            $scope.invocationResponse = JSON.stringify(data, null, 2);
                        } else {
                            $scope.invocationResponse = data;
                        }
                    }

                    $scope.invocationInProgress = false;
                    $scope.invocationStatus = status;
                    var now = new Date().getTime();
                    $scope.roundTripDuration = (now - $scope.invocationStart) / 1000;
                    showPostInvokedToast("Success");

                }).catch(function(error1) {
                    $scope.invocationInProgress = false;
                    $scope.invocationResponse = error1.statusText + "\n" + error1.data;
                    $scope.invocationStatus = error1.status;
                    var now = new Date().getTime();
                    $scope.roundTripDuration = (now - $scope.invocationStart) / 1000;

                    showPostInvokedToast("Error");
                });
        };

        var refreshData = function () {
            var previous = $scope.functions;

            var cl = function (previousItems) {
                $http.get("../system/functions").then(function (response) {
                    if (response == null || response.data == null) {
                        return
                    }

                    if (previousItems.length != response.data.length) {
                        $scope.functions = response.data;

                        // update the selected function object because the newly fetched object from the API becomes a different object
                        var filteredSelectedFunction = $filter('filter')($scope.functions, { name: $scope.selectedFunction.name }, true);
                        if (filteredSelectedFunction && filteredSelectedFunction.length > 0) {
                            $scope.selectedFunction = filteredSelectedFunction[0];
                        } else {
                            $scope.selectedFunction = undefined;
                        }
                    } else {
                        for (var i = 0; i < $scope.functions.length; i++) {
                            for (var j = 0; j < response.data.length; j++) {
                                if ($scope.functions[i].name == response.data[j].name) {
                                    $scope.functions[i].image = response.data[j].image;
                                    $scope.functions[i].replicas = response.data[j].replicas;
                                    $scope.functions[i].invocationCount = response.data[j].invocationCount;
                                }
                            }
                        }
                    }
                });
            };
            cl(previous);
        }

        var fetch = function() {
            $http.get("../system/functions").then(function(response) {
                $scope.functions = response.data;
            });
        };

        $scope.showFunction = function(fn) {
            if ($scope.selectedFunction != fn) {
                $scope.selectedFunction = fn;
                $scope.invocation.request = "";
                $scope.invocationResponse = "";
                $scope.invocationStatus = "";
                $scope.invocationInProgress = false;
                if (fn.labels && fn.labels['com.openfaas.ui.ext']) {
                  $scope.invocation.contentType = "binary";
                } else {
                  $scope.invocation.contentType = "text";
                }
                $scope.invocation.roundTripDuration = "";
            }
        };

        var showDialog = function($event) {
            var parentEl = angular.element(document.body);
            $mdDialog.show({
                parent: parentEl,
                targetEvent: $event,
                templateUrl: "templates/newfunction.html",
                locals: {
                    item: $scope.functionTemplate
                },
                controller: DialogController
            });
        };

        var DialogController = function($scope, $mdDialog, item) {
            $scope.selectedTabIdx = newFuncTabIdx;
            $scope.item = item;
            $scope.selectedFunc = null;
            $scope.closeDialog = function() {
                $mdDialog.hide();
            };

            $scope.onFuncSelected = function(func) {
                $scope.item.image = func.image;
                $scope.item.service = func.name;
                $scope.item.envProcess = func.fprocess;
                $scope.item.network = func.network;
                $scope.item.envVars = func.environment;
                $scope.item.labels = func.labels;

                $scope.selectedFunc = func;
            }

            $scope.onTabSelect = function(idx) {
                newFuncTabIdx = idx;
            }

            $scope.onStoreTabDeselect = function() {
                $scope.selectedFunc = null;
            }

            $scope.onManualTabDeselect = function() {
                $scope.item = {};
            }

            $scope.createFunc = function() {
                var options = {
                    url: "../system/functions",
                    data: $scope.item,
                    method: "POST",
                    headers: { "Content-Type": "application/json" },
                    responseType: "text"
                };

                $http(options)
                    .then(function(response) {
                        item.image = "";
                        item.service = "";
                        item.envProcess = "";
                        item.network = "";
                        item.envVars = {};
                        item.labels = {};

                        $scope.validationError = "";
                        $scope.closeDialog();
                        showPostInvokedToast("Function created");
                    }).catch(function(error1) {
                        showPostInvokedToast("Error");
                        $scope.selectedTabIdx = MANUAL_DEPLOY_TAB_INDEX;
                        $scope.validationError = error1.data;
                    });
            };
        };

        $scope.newFunction = function() {
            showDialog();
        };

        $scope.deleteFunction = function($event) {
            var confirm = $mdDialog.confirm()
                .title('Delete Function')
                .textContent('Are you sure you want to delete ' + $scope.selectedFunction.name + '?')
                .ariaLabel('Delete function')
                .targetEvent($event)
                .ok('OK')
                .cancel('Cancel');

            $mdDialog.show(confirm)
                .then(function() {
                    var options = {
                        url: "../system/functions",
                        data: {
                            functionName: $scope.selectedFunction.name
                        },
                        method: "DELETE",
                        headers: { "Content-Type": "application/json" },
                        responseType: "json"
                    };

                    return $http(options);
                }).then(function() {
                    showPostInvokedToast("Success");
                }).catch(function(err) {
                    if (err) {
                        // show error toast only if there actually is an err.
                        // because hitting 'Cancel' also rejects the promise.
                        showPostInvokedToast("Error");
                    }
                });
        };

        fetch();
    }
]);

function uuidv4() {
    var cryptoInstance = window.crypto || window.msCrypto; // for IE11
    return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, function(c) {
        return (c ^ cryptoInstance.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    })
}  <commit_msg>Undo early return in updateData callback<commit_after>"use strict"
// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

var app = angular.module('faasGateway', ['ngMaterial', 'faasGateway.funcStore']);

app.controller("home", ['$scope', '$log', '$http', '$location', '$interval', '$filter', '$mdDialog', '$mdToast', '$mdSidenav',
    function($scope, $log, $http, $location, $interval, $filter, $mdDialog, $mdToast, $mdSidenav) {
        var FUNCSTORE_DEPLOY_TAB_INDEX = 0;
        var MANUAL_DEPLOY_TAB_INDEX = 1;

        var newFuncTabIdx = FUNCSTORE_DEPLOY_TAB_INDEX;
        $scope.functions = [];
        $scope.invocationInProgress = false;
        $scope.invocationRequest = "";
        $scope.invocationResponse = "";
        $scope.invocationStatus = "";
        $scope.invocationStart = new Date().getTime();
        $scope.roundTripDuration = "";
        $scope.invocation = {
            contentType: "text"
        };

        $scope.baseUrl = $location.absUrl().replace(/\ui\/$/, '');
        try {
            $scope.canCopyToClipboard = document.queryCommandSupported('copy');
        } catch (err) {
            console.error(err);
            $scope.canCopyToClipboard = false;
        }
        $scope.copyClicked = function(e) {
            e.target.parentElement.querySelector('input').select()
            var copySuccessful = false;
            try {
                copySuccessful = document.execCommand('copy');
            } catch (err) {
                console.error(err);
            }
            var msg = copySuccessful ? 'Copied to Clipboard' : 'Copy failed. Please copy it manually';
            showPostInvokedToast(msg);
        }

        $scope.toggleSideNav = function() {
            $mdSidenav('left').toggle();
        };

        $scope.functionTemplate = {
            image: "",
            envProcess: "",
            network: "",
            service: "",
            envVars: {},
            labels: {}
        };

        $scope.invocation.request = "";
        var fetchFunctionsDelay = 3500;
        var queryFunctionDelay = 2500;

        var fetchFunctionsInterval = $interval(function() {
            refreshData();
        }, fetchFunctionsDelay);

        var queryFunctionInterval = $interval(function() {
            if($scope.selectedFunction && $scope.selectedFunction.name) {
                refreshFunction($scope.selectedFunction);
            }
        }, queryFunctionDelay);

        var refreshFunction = function(functionInstance) {
            $http.get("../system/function/" + functionInstance.name)
            .then(function(response) {
                functionInstance.ready = (response.data && response.data.availableReplicas && response.data.availableReplicas > 0);
            })
            .catch(function(err) {
                console.error(err);
            });
        };

        var showPostInvokedToast = function(message, duration) {
            $mdToast.show(
                $mdToast.simple()
                .textContent(message)
                .position("top right")
                .hideDelay(duration || 500)
            );
        };

        $scope.fireRequest = function() {
            var requestContentType = $scope.invocation.contentType == "json" ? "application/json" : "text/plain";
            if ($scope.invocation.contentType == "binary") {
                requestContentType = "binary/octet-stream";
            }

            var options = {
                url: "../function/" + $scope.selectedFunction.name,
                data: $scope.invocation.request,
                method: "POST",
                headers: { "Content-Type": requestContentType },
                responseType: $scope.invocation.contentType == "binary" ? "arraybuffer" : $scope.invocation.contentType
            };

            $scope.invocationInProgress = true;
            $scope.invocationResponse = "";
            $scope.invocationStatus = null;
            $scope.roundTripDuration = "";
            $scope.invocationStart = new Date().getTime()

            var tryDownload = function(data, filename) {
                var caught;

                try {
                    var blob = new Blob([data], { type: "binary/octet-stream" });

                    if (window.navigator.msSaveBlob) { // // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
                        window.navigator.msSaveOrOpenBlob(blob, filename);
                    }
                    else {
                        var linkElement = window.document.createElement("a");
                        linkElement.href = window.URL.createObjectURL(blob);
                        linkElement.download = filename;
                        document.body.appendChild(linkElement);
                        linkElement.click();
                        document.body.removeChild(linkElement);
                    }

                } catch (ex) {
                    caught = ex;
                }
                return caught;
            }

            $http(options)
                .then(function (response) {
                    var data = response.data;
                    var status = response.status;

                    if($scope.invocation.contentType == "binary") {
                        var filename = uuidv4();

                        if($scope.selectedFunction.labels) {
                            var ext = $scope.selectedFunction.labels["com.openfaas.ui.ext"];
                            if(ext && ext.length > 0 ) {
                                filename = filename + "." + ext;
                            }
                        }

                        var caught = tryDownload(data, filename);
                        if(caught) {
                            console.log(caught);
                            $scope.invocationResponse = caught
                        } else {
                            $scope.invocationResponse = data.byteLength + " byte(s) received";
                        }

                    } else {

                        if (typeof data == 'object') {
                            $scope.invocationResponse = JSON.stringify(data, null, 2);
                        } else {
                            $scope.invocationResponse = data;
                        }
                    }

                    $scope.invocationInProgress = false;
                    $scope.invocationStatus = status;
                    var now = new Date().getTime();
                    $scope.roundTripDuration = (now - $scope.invocationStart) / 1000;
                    showPostInvokedToast("Success");

                }).catch(function(error1) {
                    $scope.invocationInProgress = false;
                    $scope.invocationResponse = error1.statusText + "\n" + error1.data;
                    $scope.invocationStatus = error1.status;
                    var now = new Date().getTime();
                    $scope.roundTripDuration = (now - $scope.invocationStart) / 1000;

                    showPostInvokedToast("Error");
                });
        };

        var refreshData = function () {
            var previous = $scope.functions;

            var cl = function (previousItems) {
                $http.get("../system/functions").then(function (response) {
                    if (response && response.data) {
                        if (previousItems.length != response.data.length) {
                            $scope.functions = response.data;

                            // update the selected function object because the newly fetched object from the API becomes a different object
                            var filteredSelectedFunction = $filter('filter')($scope.functions, { name: $scope.selectedFunction.name }, true);
                            if (filteredSelectedFunction && filteredSelectedFunction.length > 0) {
                                $scope.selectedFunction = filteredSelectedFunction[0];
                            } else {
                                $scope.selectedFunction = undefined;
                            }
                        } else {
                            for (var i = 0; i < $scope.functions.length; i++) {
                                for (var j = 0; j < response.data.length; j++) {
                                    if ($scope.functions[i].name == response.data[j].name) {
                                        $scope.functions[i].image = response.data[j].image;
                                        $scope.functions[i].replicas = response.data[j].replicas;
                                        $scope.functions[i].invocationCount = response.data[j].invocationCount;
                                    }
                                }
                            }
                        }
                    }
                });
            };
            cl(previous);
        }

        var fetch = function() {
            $http.get("../system/functions").then(function(response) {
                $scope.functions = response.data;
            });
        };

        $scope.showFunction = function(fn) {
            if ($scope.selectedFunction != fn) {
                $scope.selectedFunction = fn;
                $scope.invocation.request = "";
                $scope.invocationResponse = "";
                $scope.invocationStatus = "";
                $scope.invocationInProgress = false;
                if (fn.labels && fn.labels['com.openfaas.ui.ext']) {
                  $scope.invocation.contentType = "binary";
                } else {
                  $scope.invocation.contentType = "text";
                }
                $scope.invocation.roundTripDuration = "";
            }
        };

        var showDialog = function($event) {
            var parentEl = angular.element(document.body);
            $mdDialog.show({
                parent: parentEl,
                targetEvent: $event,
                templateUrl: "templates/newfunction.html",
                locals: {
                    item: $scope.functionTemplate
                },
                controller: DialogController
            });
        };

        var DialogController = function($scope, $mdDialog, item) {
            $scope.selectedTabIdx = newFuncTabIdx;
            $scope.item = item;
            $scope.selectedFunc = null;
            $scope.closeDialog = function() {
                $mdDialog.hide();
            };

            $scope.onFuncSelected = function(func) {
                $scope.item.image = func.image;
                $scope.item.service = func.name;
                $scope.item.envProcess = func.fprocess;
                $scope.item.network = func.network;
                $scope.item.envVars = func.environment;
                $scope.item.labels = func.labels;

                $scope.selectedFunc = func;
            }

            $scope.onTabSelect = function(idx) {
                newFuncTabIdx = idx;
            }

            $scope.onStoreTabDeselect = function() {
                $scope.selectedFunc = null;
            }

            $scope.onManualTabDeselect = function() {
                $scope.item = {};
            }

            $scope.createFunc = function() {
                var options = {
                    url: "../system/functions",
                    data: $scope.item,
                    method: "POST",
                    headers: { "Content-Type": "application/json" },
                    responseType: "text"
                };

                $http(options)
                    .then(function(response) {
                        item.image = "";
                        item.service = "";
                        item.envProcess = "";
                        item.network = "";
                        item.envVars = {};
                        item.labels = {};

                        $scope.validationError = "";
                        $scope.closeDialog();
                        showPostInvokedToast("Function created");
                    }).catch(function(error1) {
                        showPostInvokedToast("Error");
                        $scope.selectedTabIdx = MANUAL_DEPLOY_TAB_INDEX;
                        $scope.validationError = error1.data;
                    });
            };
        };

        $scope.newFunction = function() {
            showDialog();
        };

        $scope.deleteFunction = function($event) {
            var confirm = $mdDialog.confirm()
                .title('Delete Function')
                .textContent('Are you sure you want to delete ' + $scope.selectedFunction.name + '?')
                .ariaLabel('Delete function')
                .targetEvent($event)
                .ok('OK')
                .cancel('Cancel');

            $mdDialog.show(confirm)
                .then(function() {
                    var options = {
                        url: "../system/functions",
                        data: {
                            functionName: $scope.selectedFunction.name
                        },
                        method: "DELETE",
                        headers: { "Content-Type": "application/json" },
                        responseType: "json"
                    };

                    return $http(options);
                }).then(function() {
                    showPostInvokedToast("Success");
                }).catch(function(err) {
                    if (err) {
                        // show error toast only if there actually is an err.
                        // because hitting 'Cancel' also rejects the promise.
                        showPostInvokedToast("Error");
                    }
                });
        };

        fetch();
    }
]);

function uuidv4() {
    var cryptoInstance = window.crypto || window.msCrypto; // for IE11
    return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, function(c) {
        return (c ^ cryptoInstance.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    })
}  <|endoftext|>