<commit_before>/*
 * Used to determine if we need to migrate how the data is stored.
 * Each time the data format changes, increment this number.
 */
var PSA_DATA_VERSION = 1;

// === INITIALIZE KEY TRACKING ===
Session.psKeys = {};
Session.psKeyList = [];
Session.psaKeys = {};
Session.psaKeyList = [];

// initialize default method setting
var default_method = 'temporary'; // valid options: 'temporary', 'persistent', 'authenticated'
if (Meteor.settings &&
    Meteor.settings.public &&
    Meteor.settings.public.persistent_session) {
  default_method = Meteor.settings.public.persistent_session.default_method;
}

// === LOCAL STORAGE INTERACTION ===
Session.store = function _psStore(type, key, value) {

  this.psKeyList  = amplify.store('__PSKEYS__') || [];
  this.psaKeyList = amplify.store('__PSAKEYS__')|| [];

  if (type == 'get') {
    return amplify.store(key);

  } else {

    this.psKeyList  = _.without(this.psKeyList, key);
    this.psaKeyList = _.without(this.psaKeyList, key);
    delete this.psKeys[key];
    delete this.psaKeys[key];

    if (value===undefined || value===null || type=='temporary') {
      value = null;

    } else if (type=='persistent') {
      this.psKeys[key] = EJSON.stringify(value);
      this.psKeyList = _.union(this.psKeyList, [key]);

    } else if (type=='authenticated') {
      this.psaKeys[key] = EJSON.stringify(value);
      this.psaKeyList = _.union(this.psaKeyList, [key]);
    }

    amplify.store('__PSKEYS__', this.psKeyList);
    amplify.store('__PSAKEYS__', this.psaKeyList);
    amplify.store(key, EJSON.stringify(value));
  }

};

// === GET ===
Session.old_get = Session.get;
Session.get = function _psGet(key) {
  var val = this.old_get(key);
  var psVal;
  var unparsedPsVal = Session.store('get', key);
  if (unparsedPsVal !== undefined) {
    psVal = EJSON.parse(Session.store('get', key));
  }
  /*
   * We can't do `return psVal || val;` here, as when psVal = undefined and
   * val = 0, it will return undefined, even though 0 is the correct value.
   */
  if (psVal === undefined || psVal === null) {
    return val;
  }
  return psVal;
};

// === SET ===
// defaults to a persistent, non-authenticated variable
Session.old_set = Session.set;
Session.set = function _psSet(keyOrObject, value, persist, auth) {

  // Taken from https://github.com/meteor/meteor/blob/107d858/packages/reactive-dict/reactive-dict.js
  if ((typeof keyOrObject === 'object') && (value === undefined)) {
    this._psSetObject(keyOrObject, persist, auth);
    return;
  }

  var key = keyOrObject;

  this.old_set(key, value);
  var type = 'temporary';
  if (persist || (persist===undefined && (default_method=='persistent' || default_method=='authenticated'))) {
    if (auth || (persist===undefined && auth===undefined && default_method=='authenticated')) {
      type = 'authenticated';
    } else {
      type = 'persistent';
    }
  }
  Session.store(type, key, value);
};

Session._psSetObject = function _psSetObject(object, persist, auth) {
  var self = this;

  _.each(object, function (value, key){
    self.set(key, value, persist, auth);
  });
};

// === SET TEMPORARY ===
// alias to Session.set(); sets a non-persistent variable
Session.setTemp = function _psSetTemp(keyOrObject, value) {
  this.set(keyOrObject, value, false, false);
};

// === SET PERSISTENT ===
// alias to Session.set(); sets a persistent variable
Session.setPersistent = function _psSetPersistent(keyOrObject, value) {
  this.set(keyOrObject, value, true, false);
};

// === SET AUTHENTICATED ===
// alias to Session.set(); sets a persistent variable that will be removed on logout
Session.setAuth = function _psSetAuth(keyOrObject, value) {
  this.set(keyOrObject, value, true, true);
};

// === MAKE TEMP / PERSISTENT / AUTH ===
// change the type of session var
Session.makeTemp = function _psMakeTemp(key) {
  this.store('temporary', key);
};
Session.makePersistent = function _psMakePersistent(key) {
  var val = this.get(key);
  this.store('persistent', key, val);
};
Session.makeAuth = function _psMakeAuth(key) {
  var val = this.get(key);
  this.store('authenticated', key, val);
};

// === CLEAR ===
Session.clear = function _psClear(key, list) {

  // remove all keys with Session.clear();
  if (key === undefined) {
    if (list===undefined) { list = this.keys; }
    for (var k in list) {
      this.set(k, undefined, false, false);
    }

  // remove a single key with Session.clear('key');
  } else {
    this.set(key, undefined, false, false);
  }

};

// === CLEAR TEMP ===
// clears all the temporary keys
Session.clearTemp = function _psClearTemp() {
  this.clear(undefined, _.keys(_.omit(this.keys, this.psKeys, this.psaKeys)));
};

// === CLEAR PERSISTENT ===
// clears all persistent keys
Session.clearPersistent = function _psClearPersistent() {
  this.clear(undefined, this.psKeys);
};

// === CLEAR AUTH ===
// clears all authenticated keys
Session.clearAuth = function _psClearAuth() {
  this.clear(undefined, this.psaKeys);
};

// === UPDATE ===
// updates the value of a session var without changing its type
Session.update = function _psUpdate(key, value) {
  var persist, auth;
  if ( _.indexOf(this.psaKeyList, key) >= 0 ) { auth = true; }
  if ( auth || _.indexOf(this.psKeyList, key) >= 0 ) { persist = true; }
  this.set(key, value, persist, auth);
};

// === SET DEFAULT ===
Session.old_setDefault = Session.setDefault;
Session.setDefault = function _psSetDefault(key, value, persist, auth) {
  if ( this.get(key) === undefined) {
    this.set(key, value, persist, auth);
  }
};

// === SET DEFAULT TEMP ===
Session.setDefaultTemp = function _psSetDefaultTemp(key, value) {
  this.setDefault(key, value, false, false);
};

// === SET DEFAULT PERSISTENT ===
Session.setDefaultPersistent = function _psSetDefaultPersistent(key, value) {
  this.setDefault(key, value, true, false);
};

// === SET DEFAULT AUTH ===
Session.setDefaultAuth = function _psSetDefaultAuth(key, value) {
  this.setDefault(key, value, true, true);
};

// === HOUSEKEEPING ===

/*
 * Converts previously stored values into EJSON compatible formats.
 */
function migrateToEJSON() {
  if (amplify.store('__PSDATAVERSION__') >= PSA_DATA_VERSION) {
    return;
  }

  var psKeyList = amplify.store('__PSKEYS__');
  var psaKeyList = amplify.store('__PSAKEYS__');

  _.each([psKeyList, psaKeyList], function(list) {
    _.each(list, function(key) {
      amplify.store(key, EJSON.stringify(amplify.store(key)));
    });
  });

  amplify.store('__PSDATAVERSION__', PSA_DATA_VERSION);
}

if (Meteor.isClient) {

  // --- on startup, load persistent data back into meteor session ---
  Meteor.startup(function(){
    var val;

    migrateToEJSON();

    // persistent data
    var psList = amplify.store('__PSKEYS__');
    if ( typeof psList == "object" && psList.length!==undefined ) {
      for (var i=0; i<psList.length; i++) {
        if (!_.has(Session.keys, psList[i])) {
          val = Session.get(psList[i]);
          Session.set(psList[i], val, true, false);
        }
      }
    }

    // authenticated data
    var psaList = amplify.store('__PSAKEYS__');
    if ( typeof psaList == "object" && psaList.length!==undefined ) {
      for (var i=0; i<psaList.length; i++) {
        if (!_.has(Session.keys, psaList[i])) {
          val = Session.get(psaList[i]);
          Session.setAuth(psaList[i], val, true, true);
        }
      }
    }

  });

  // --- clear authenticated data on logout ---
  var _logout = Meteor.logout;
  Meteor.logout = function _psLogout() {
    Session.clearAuth();
    _logout.apply(Meteor, arguments);
  };

}
<commit_msg>Don't try to parse values that weren't explicitly set through Session<commit_after>/*
 * Used to determine if we need to migrate how the data is stored.
 * Each time the data format changes, increment this number.
 */
var PSA_DATA_VERSION = 1;

// === INITIALIZE KEY TRACKING ===
Session.psKeys = {};
Session.psKeyList = [];
Session.psaKeys = {};
Session.psaKeyList = [];

// initialize default method setting
var default_method = 'temporary'; // valid options: 'temporary', 'persistent', 'authenticated'
if (Meteor.settings &&
    Meteor.settings.public &&
    Meteor.settings.public.persistent_session) {
  default_method = Meteor.settings.public.persistent_session.default_method;
}

// === LOCAL STORAGE INTERACTION ===
Session.store = function _psStore(type, key, value) {

  this.psKeyList  = amplify.store('__PSKEYS__') || [];
  this.psaKeyList = amplify.store('__PSAKEYS__')|| [];

  if (type == 'get') {
    return amplify.store(key);

  } else {

    this.psKeyList  = _.without(this.psKeyList, key);
    this.psaKeyList = _.without(this.psaKeyList, key);
    delete this.psKeys[key];
    delete this.psaKeys[key];

    if (value===undefined || value===null || type=='temporary') {
      value = null;

    } else if (type=='persistent') {
      this.psKeys[key] = EJSON.stringify(value);
      this.psKeyList = _.union(this.psKeyList, [key]);

    } else if (type=='authenticated') {
      this.psaKeys[key] = EJSON.stringify(value);
      this.psaKeyList = _.union(this.psaKeyList, [key]);
    }

    amplify.store('__PSKEYS__', this.psKeyList);
    amplify.store('__PSAKEYS__', this.psaKeyList);
    amplify.store(key, EJSON.stringify(value));
  }

};

// === GET ===
Session.old_get = Session.get;
Session.get = function _psGet(key) {
  var val = this.old_get(key);
  var psVal;
  var unparsedPsVal = Session.store('get', key);
  if (!_.contains(this.psKeyList, key) && !_.contains(this.psaKeyList, key)) {
    // This value was not set by Session previously, so we can't assume it's
    // in EJSON format.
    return unparsedPsVal;
  }
  if (unparsedPsVal !== undefined) {
    psVal = EJSON.parse(Session.store('get', key));
  }
  /*
   * We can't do `return psVal || val;` here, as when psVal = undefined and
   * val = 0, it will return undefined, even though 0 is the correct value.
   */
  if (psVal === undefined || psVal === null) {
    return val;
  }
  return psVal;
};

// === SET ===
// defaults to a persistent, non-authenticated variable
Session.old_set = Session.set;
Session.set = function _psSet(keyOrObject, value, persist, auth) {

  // Taken from https://github.com/meteor/meteor/blob/107d858/packages/reactive-dict/reactive-dict.js
  if ((typeof keyOrObject === 'object') && (value === undefined)) {
    this._psSetObject(keyOrObject, persist, auth);
    return;
  }

  var key = keyOrObject;

  this.old_set(key, value);
  var type = 'temporary';
  if (persist || (persist===undefined && (default_method=='persistent' || default_method=='authenticated'))) {
    if (auth || (persist===undefined && auth===undefined && default_method=='authenticated')) {
      type = 'authenticated';
    } else {
      type = 'persistent';
    }
  }
  Session.store(type, key, value);
};

Session._psSetObject = function _psSetObject(object, persist, auth) {
  var self = this;

  _.each(object, function (value, key){
    self.set(key, value, persist, auth);
  });
};

// === SET TEMPORARY ===
// alias to Session.set(); sets a non-persistent variable
Session.setTemp = function _psSetTemp(keyOrObject, value) {
  this.set(keyOrObject, value, false, false);
};

// === SET PERSISTENT ===
// alias to Session.set(); sets a persistent variable
Session.setPersistent = function _psSetPersistent(keyOrObject, value) {
  this.set(keyOrObject, value, true, false);
};

// === SET AUTHENTICATED ===
// alias to Session.set(); sets a persistent variable that will be removed on logout
Session.setAuth = function _psSetAuth(keyOrObject, value) {
  this.set(keyOrObject, value, true, true);
};

// === MAKE TEMP / PERSISTENT / AUTH ===
// change the type of session var
Session.makeTemp = function _psMakeTemp(key) {
  this.store('temporary', key);
};
Session.makePersistent = function _psMakePersistent(key) {
  var val = this.get(key);
  this.store('persistent', key, val);
};
Session.makeAuth = function _psMakeAuth(key) {
  var val = this.get(key);
  this.store('authenticated', key, val);
};

// === CLEAR ===
Session.clear = function _psClear(key, list) {

  // remove all keys with Session.clear();
  if (key === undefined) {
    if (list===undefined) { list = this.keys; }
    for (var k in list) {
      this.set(k, undefined, false, false);
    }

  // remove a single key with Session.clear('key');
  } else {
    this.set(key, undefined, false, false);
  }

};

// === CLEAR TEMP ===
// clears all the temporary keys
Session.clearTemp = function _psClearTemp() {
  this.clear(undefined, _.keys(_.omit(this.keys, this.psKeys, this.psaKeys)));
};

// === CLEAR PERSISTENT ===
// clears all persistent keys
Session.clearPersistent = function _psClearPersistent() {
  this.clear(undefined, this.psKeys);
};

// === CLEAR AUTH ===
// clears all authenticated keys
Session.clearAuth = function _psClearAuth() {
  this.clear(undefined, this.psaKeys);
};

// === UPDATE ===
// updates the value of a session var without changing its type
Session.update = function _psUpdate(key, value) {
  var persist, auth;
  if ( _.indexOf(this.psaKeyList, key) >= 0 ) { auth = true; }
  if ( auth || _.indexOf(this.psKeyList, key) >= 0 ) { persist = true; }
  this.set(key, value, persist, auth);
};

// === SET DEFAULT ===
Session.old_setDefault = Session.setDefault;
Session.setDefault = function _psSetDefault(key, value, persist, auth) {
  if ( this.get(key) === undefined) {
    this.set(key, value, persist, auth);
  }
};

// === SET DEFAULT TEMP ===
Session.setDefaultTemp = function _psSetDefaultTemp(key, value) {
  this.setDefault(key, value, false, false);
};

// === SET DEFAULT PERSISTENT ===
Session.setDefaultPersistent = function _psSetDefaultPersistent(key, value) {
  this.setDefault(key, value, true, false);
};

// === SET DEFAULT AUTH ===
Session.setDefaultAuth = function _psSetDefaultAuth(key, value) {
  this.setDefault(key, value, true, true);
};

// === HOUSEKEEPING ===

/*
 * Converts previously stored values into EJSON compatible formats.
 */
function migrateToEJSON() {
  if (amplify.store('__PSDATAVERSION__') >= PSA_DATA_VERSION) {
    return;
  }

  var psKeyList = amplify.store('__PSKEYS__');
  var psaKeyList = amplify.store('__PSAKEYS__');

  _.each([psKeyList, psaKeyList], function(list) {
    _.each(list, function(key) {
      amplify.store(key, EJSON.stringify(amplify.store(key)));
    });
  });

  amplify.store('__PSDATAVERSION__', PSA_DATA_VERSION);
}

if (Meteor.isClient) {

  // --- on startup, load persistent data back into meteor session ---
  Meteor.startup(function(){
    var val;

    migrateToEJSON();

    // persistent data
    var psList = amplify.store('__PSKEYS__');
    if ( typeof psList == "object" && psList.length!==undefined ) {
      for (var i=0; i<psList.length; i++) {
        if (!_.has(Session.keys, psList[i])) {
          val = Session.get(psList[i]);
          Session.set(psList[i], val, true, false);
        }
      }
    }

    // authenticated data
    var psaList = amplify.store('__PSAKEYS__');
    if ( typeof psaList == "object" && psaList.length!==undefined ) {
      for (var i=0; i<psaList.length; i++) {
        if (!_.has(Session.keys, psaList[i])) {
          val = Session.get(psaList[i]);
          Session.setAuth(psaList[i], val, true, true);
        }
      }
    }

  });

  // --- clear authenticated data on logout ---
  var _logout = Meteor.logout;
  Meteor.logout = function _psLogout() {
    Session.clearAuth();
    _logout.apply(Meteor, arguments);
  };

}
<|endoftext|>


<commit_before>var mergeDirs = require('merge-dirs').default;
var helpers = require('../../lib/helpers');
var path = require('path');

mergeDirs(path.resolve(__dirname, 'template/'), 'sb', 'overwrite');

var packageJson = helpers.getPackageJson();

packageJson.devDependencies = packageJson.devDependencies || {};
packageJson.devDependencies['ui-storybook'] = '^1.0.4';
packageJson.devDependencies['sb-react-helper'] = '^0.1.0';
packageJson.devDependencies['webpack-hot-middleware'] = '2.13.0';

packageJson.scripts = packageJson.scripts || {};
packageJson.scripts['sb'] = 'node ./sb/.webpack/server.js --NODE_ENV=dev';
packageJson.scripts['sb-build'] = 'webpack --config ./sb/.webpack/webpack.build.babel.js --NODE_ENV=production';
packageJson.scripts['sb-publish'] = 'node sb/.script/ghpages.js';

helpers.writePackageJson(packageJson);
<commit_msg>Added babel-preset-react to dev dep<commit_after>var mergeDirs = require('merge-dirs').default;
var helpers = require('../../lib/helpers');
var path = require('path');

mergeDirs(path.resolve(__dirname, 'template/'), 'sb', 'overwrite');

var packageJson = helpers.getPackageJson();

packageJson.devDependencies = packageJson.devDependencies || {};
packageJson.devDependencies['ui-storybook'] = '^1.0.4';
packageJson.devDependencies['sb-react-helper'] = '^0.1.0';
packageJson.devDependencies['webpack-hot-middleware'] = '2.13.0';
packageJson.devDependencies['babel-preset-react'] = '2.13.0';

packageJson.scripts = packageJson.scripts || {};
packageJson.scripts['sb'] = 'node ./sb/.webpack/server.js --NODE_ENV=dev';
packageJson.scripts['sb-build'] = 'webpack --config ./sb/.webpack/webpack.build.babel.js --NODE_ENV=production';
packageJson.scripts['sb-publish'] = 'node sb/.script/ghpages.js';

helpers.writePackageJson(packageJson);
<|endoftext|>


<commit_before>app.directive('taskHints', ['PEMApi', '$timeout', '$http', '$rootScope', function (PEMApi, $timeout, $http, $rootScope) {
   return {
      scope: false,
      restrict: 'EA',
      templateUrl: 'hints/template.html',
      link: function($scope, elem, attrs) {
      // TODO: fallback mechanism
         function findHintContent(hint, lang) {
            var content = '';
            _.forEach(hint.strings, function(string) {
               //if (string.sLanguage == lang) {
                  content = string.sContent;
                  return false;
               //}
            });
            return content;
         }
         function buildHintsArray(taskID, lang) {
            var hints = [];
            var raw_hints = ModelsManager.getRecords('tm_hints');
            _.forEach(raw_hints, function(hint) {
               var content = findHintContent(hint, lang);
               hints[hint.iRank-1] = {iRank: hint.iRank, content: content};
            });
            return hints;
         }
         function init() {
            $scope.hints = buildHintsArray($scope.tm_task.ID, $rootScope.sLocaleLang);
            $scope.nbHints = $scope.tm_task.nbHintsTotal;
            if ($scope.hints.length >= $scope.nbHints) {
               $scope.canAskHint = false;
            } else {
               $scope.canAskHint = true;
            }
            if ($scope.hintLoading && $scope.loadingHintRank == $scope.hints.length) {
               $scope.hintLoading = false;
            }
         }
         function updateHints() {
            SyncQueue.addSyncEndListeners('updateHints', function() {
               $timeout(function(){$scope.$apply(init);});
               SyncQueue.removeSyncEndListeners('updateHints');
            });
         }
         $scope.hints = [];
         $scope.canAskHint = false;
         init();
         ModelsManager.addListener('tm_hints', "inserted", 'hintsController', updateHints);
         ModelsManager.addListener('tm_hints', "updated", 'hintsController', updateHints);
         $scope.askHint = function() {
            $http.post('askHint.php', {sToken: $rootScope.sToken, sPlatform: $rootScope.sPlatform, taskId: $rootScope.taskId}, {responseType: 'json'}).success(function(postRes) {
               if (!postRes || !postRes.success) {
                  console.error('error calling saveAnswer.php'+(postRes ? ': '+postRes.sError : ''));
                  return;
               }
               var hintToken = postRes.hintToken;
               $scope.hintLoading = true;
               $scope.loadingHintRank = $scope.hints.length + 1;
               SyncQueue.params.getNewHints = true;
               SyncQueue.addSyncEndListeners('getHints', function() {
                  SyncQueue.params.getNewHints = false; // this *should* be safe
                  $scope.hintLoading = false;
               }, true);
               // askHint will call updateToken, which will make a sync, so no need
               // for a new sync here
               PEMApi.platform.askHint(hintToken, function() {});
            });
         };
      }
   };
}]);
<commit_msg>Document/update hints logic<commit_after>// Logic for hints
app.directive('taskHints', ['PEMApi', '$timeout', '$http', '$rootScope', function (PEMApi, $timeout, $http, $rootScope) {
   return {
      scope: false,
      restrict: 'EA',
      templateUrl: 'hints/template.html',
      link: function($scope, elem, attrs) {
      // TODO: fallback mechanism
         function findHintContent(hint, lang) {
            // Get, for each hint, the version in that language
            var content = '';
            _.forEach(hint.strings, function(string) {
               // TODO :: actually filter by language, set some language as default
               //if (string.sLanguage == lang) {
                  content = string.sContent;
                  return false;
               //}
            });
            return content;
         }

         function buildHintsArray(taskID, lang) {
            // Make array with all hints ordered and the right language selected
            var hints = [];
            var raw_hints = ModelsManager.getRecords('tm_hints');
            _.forEach(raw_hints, function(hint) {
               var content = findHintContent(hint, lang);
               hints[hint.iRank-1] = {iRank: hint.iRank, content: content};
            });
            return hints;
         }

         function init() {
            // Initialize hints display
            $scope.hints = buildHintsArray($scope.tm_task.ID, $rootScope.sLocaleLang);
            $scope.nbHints = $scope.tm_task.nbHintsTotal;
            $scope.canAskHint = ($scope.hints.length < $scope.nbHints);
            if ($scope.hintLoading && $scope.loadingHintRank == $scope.hints.length) {
               $scope.hintLoading = false;
            }
         }

         function updateHints() {
            // Reinitialize display when hints are updated
            SyncQueue.addSyncEndListeners('updateHints', function() {
               $timeout(function(){$scope.$apply(init);});
               SyncQueue.removeSyncEndListeners('updateHints');
            });
         }

         init();

         ModelsManager.addListener('tm_hints', "inserted", 'hintsController', updateHints);
         ModelsManager.addListener('tm_hints', "updated", 'hintsController', updateHints);

         $scope.askHint = function() {
            // Ask a hint: sends a local request to askHint.php to get a hint
            // request token
            // The token contains idTask, idUser, askedHint
            $http.post('askHint.php', {sToken: $rootScope.sToken, sPlatform: $rootScope.sPlatform, taskId: $rootScope.taskId}, {responseType: 'json'}).success(function(postRes) {
               if (!postRes || !postRes.success) {
                  console.error('error calling saveAnswer.php'+(postRes ? ': '+postRes.sError : ''));
                  return;
               }
               // With the hintToken signed by TaskPlatform, send a request to
               // the platform, which will send back a new token acknowledging
               // the hint request
               var hintToken = postRes.hintToken;
               $scope.hintLoading = true;
               $scope.loadingHintRank = $scope.hints.length + 1;
               SyncQueue.params.getNewHints = true;
               SyncQueue.addSyncEndListeners('getHints', function() {
                  SyncQueue.params.getNewHints = false; // this *should* be safe
                  $scope.hintLoading = false;
               }, true);
               // askHint will call updateToken, which will make a sync, so no need
               // for a new sync here
               PEMApi.platform.askHint(hintToken, function() {});
            });
         };
      }
   };
}]);
<|endoftext|>


<commit_before>'use strict';

const { QueryBuilderOperation } = require('./QueryBuilderOperation');
const { mapAfterAllReturn } = require('../../utils/promiseUtils');
const { isPostgres, isSqlite } = require('../../utils/knexUtils');
const { isObject } = require('../../utils/objectUtils');

// Base class for all insert operations.
class InsertOperation extends QueryBuilderOperation {
  constructor(name, opt) {
    super(name, opt);

    this.models = null;
    this.isArray = false;
    this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
  }

  onAdd(builder, args) {
    const json = args[0];
    const modelClass = builder.modelClass();

    this.isArray = Array.isArray(json);
    this.models = modelClass.ensureModelArray(json, this.modelOptions);

    return true;
  }

  onBefore2(builder, result) {
    if (this.models.length > 1 && !isPostgres(builder.knex())) {
      throw new Error('batch insert only works with Postgresql');
    } else {
      return mapAfterAllReturn(
        this.models,
        model => model.$beforeInsert(builder.context()),
        result
      );
    }
  }

  onBuildKnex(knexBuilder, builder) {
    if (!isSqlite(builder.knex()) && !builder.has(/returning/)) {
      // If the user hasn't specified a `returning` clause, we make sure
      // that at least the identifier is returned.
      knexBuilder.returning(builder.modelClass().getIdColumn());
    }

    knexBuilder.insert(this.models.map(model => model.$toDatabaseJson(builder)));
  }

  onAfter1(builder, ret) {
    if (!Array.isArray(ret) || !ret.length || ret === this.models) {
      // Early exit if there is nothing to do.
      return this.models;
    }

    if (isObject(ret[0])) {
      // If the user specified a `returning` clause the result may be an array of objects.
      // Merge all values of the objects to our models.
      for (let i = 0, l = this.models.length; i < l; ++i) {
        this.models[i].$set(ret[i]);
      }
    } else {
      // If the return value is not an array of objects, we assume it is an array of identifiers.
      for (let i = 0, l = this.models.length; i < l; ++i) {
        const model = this.models[i];

        // Don't set the id if the model already has one. MySQL and Sqlite don't return the correct
        // primary key value if the id is not generated in db, but given explicitly.
        if (!model.$id()) {
          model.$id(ret[i]);
        }
      }
    }

    return this.models;
  }

  onAfter2(builder, models) {
    const result = this.isArray ? models : models[0] || null;
    return mapAfterAllReturn(models, model => model.$afterInsert(builder.context()), result);
  }

  clone() {
    const clone = super.clone();

    clone.models = this.models;
    clone.isArray = this.isArray;

    return clone;
  }
}

module.exports = {
  InsertOperation
};
<commit_msg>Exclude MySQL from returning clause as well<commit_after>'use strict';

const { QueryBuilderOperation } = require('./QueryBuilderOperation');
const { mapAfterAllReturn } = require('../../utils/promiseUtils');
const { isPostgres, isSqlite, isMySql } = require('../../utils/knexUtils');
const { isObject } = require('../../utils/objectUtils');

// Base class for all insert operations.
class InsertOperation extends QueryBuilderOperation {
  constructor(name, opt) {
    super(name, opt);

    this.models = null;
    this.isArray = false;
    this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
  }

  onAdd(builder, args) {
    const json = args[0];
    const modelClass = builder.modelClass();

    this.isArray = Array.isArray(json);
    this.models = modelClass.ensureModelArray(json, this.modelOptions);

    return true;
  }

  onBefore2(builder, result) {
    if (this.models.length > 1 && !isPostgres(builder.knex())) {
      throw new Error('batch insert only works with Postgresql');
    } else {
      return mapAfterAllReturn(
        this.models,
        model => model.$beforeInsert(builder.context()),
        result
      );
    }
  }

  onBuildKnex(knexBuilder, builder) {
    if (!isSqlite(builder.knex() && !isMySql(builder.knex())) && !builder.has(/returning/)) {
      // If the user hasn't specified a `returning` clause, we make sure
      // that at least the identifier is returned.
      knexBuilder.returning(builder.modelClass().getIdColumn());
    }

    knexBuilder.insert(this.models.map(model => model.$toDatabaseJson(builder)));
  }

  onAfter1(builder, ret) {
    if (!Array.isArray(ret) || !ret.length || ret === this.models) {
      // Early exit if there is nothing to do.
      return this.models;
    }

    if (isObject(ret[0])) {
      // If the user specified a `returning` clause the result may be an array of objects.
      // Merge all values of the objects to our models.
      for (let i = 0, l = this.models.length; i < l; ++i) {
        this.models[i].$set(ret[i]);
      }
    } else {
      // If the return value is not an array of objects, we assume it is an array of identifiers.
      for (let i = 0, l = this.models.length; i < l; ++i) {
        const model = this.models[i];

        // Don't set the id if the model already has one. MySQL and Sqlite don't return the correct
        // primary key value if the id is not generated in db, but given explicitly.
        if (!model.$id()) {
          model.$id(ret[i]);
        }
      }
    }

    return this.models;
  }

  onAfter2(builder, models) {
    const result = this.isArray ? models : models[0] || null;
    return mapAfterAllReturn(models, model => model.$afterInsert(builder.context()), result);
  }

  clone() {
    const clone = super.clone();

    clone.models = this.models;
    clone.isArray = this.isArray;

    return clone;
  }
}

module.exports = {
  InsertOperation
};
<|endoftext|>


<commit_before>import {
  GraphQLString,
  GraphQLNonNull,
  GraphQLList,
  GraphQLFloat,
} from 'graphql';

import client from 'util/client';
import { assertUser } from 'graphql/util';
import ArticleCategory from 'graphql/models/ArticleCategory';

/**
 *
 * @param {object} param
 * @param {object} param.article - The article instance to attach category to
 * @param {object} param.categoryId - The categoryId to attach to article
 * @param {string} param.userId - The user adding this article-reply connection
 * @param {string} param.appId
 * @returns {ArticleCategory[]} The article categories after creation
 */
export async function createArticleCategory({
  article,
  categoryId,
  userId,
  appId,
  aiModel,
  aiConfidence,
}) {
  assertUser({ userId, appId });
  if (!article || !categoryId) {
    throw new Error(
      'articleId and categoryId are mandatory when creating ArticleCategory.'
    );
  }

  const now = new Date().toISOString();

  const articleCategory = {
    userId,
    appId,
    aiModel,
    aiConfidence,
    positiveFeedbackCount: 0,
    negativeFeedbackCount: 0,
    categoryId,
    status: 'NORMAL',
    createdAt: now,
    updatedAt: now,
  };

  const {
    result: articleResult,
    get: { _source },
  } = await client.update({
    index: 'articles',
    type: 'doc',
    id: article.id,
    body: {
      script: {
        /**
         * Check if the category is already connected in the article.
         * If so, do nothing;
         * otherwise, do update.
         */
        source: `
          if(
            ctx._source.articleCategories.stream().anyMatch(
              ar -> ar.get('categoryId').equals(params.articleCategory.get('categoryId'))
            )
          ) {
            ctx.op = 'none';
          } else {
            ctx._source.articleCategories.add(params.articleCategory);
            ctx._source.normalArticleCategoryCount = ctx._source.articleCategories.stream().filter(
              ar -> ar.get('status').equals('NORMAL')
            ).count();
          }
        `,
        lang: 'painless',
        params: { articleCategory },
      },
      _source: ['articleCategories.*'],
    },
  });

  if (articleResult === 'noop') {
    throw new Error(
      `Cannot add articleCategory ${JSON.stringify(
        articleCategory
      )} to article ${article.id}`
    );
  }

  return _source.articleCategories;
}

export default {
  type: new GraphQLList(ArticleCategory),
  description: 'Adds specified category to specified article.',
  args: {
    articleId: { type: new GraphQLNonNull(GraphQLString) },
    categoryId: { type: new GraphQLNonNull(GraphQLString) },
    aiModel: { type: GraphQLString },
    aiConfidence: { type: GraphQLFloat },
  },
  async resolve(
    rootValue,
    { articleId, categoryId, aiModel, aiConfidence },
    { userId, appId, loaders }
  ) {
    const article = await loaders.docLoader.load({
      index: 'articles',
      id: articleId,
    });

    const articleCategories = await createArticleCategory({
      article,
      categoryId,
      userId,
      appId,
      aiModel,
      aiConfidence,
    });

    // When returning, insert articleId so that ArticleReply object type can resolve article.
    return articleCategories.map(ac => ({ ...ac, articleId }));
  },
};
<commit_msg>Fix existed deleted ArticleCategory<commit_after>import {
  GraphQLString,
  GraphQLNonNull,
  GraphQLList,
  GraphQLFloat,
} from 'graphql';

import client from 'util/client';
import { assertUser } from 'graphql/util';
import ArticleCategory from 'graphql/models/ArticleCategory';

/**
 *
 * @param {object} param
 * @param {object} param.article - The article instance to attach category to
 * @param {object} param.categoryId - The categoryId to attach to article
 * @param {string} param.userId - The user adding this article-reply connection
 * @param {string} param.appId
 * @returns {ArticleCategory[]} The article categories after creation
 */
export async function createArticleCategory({
  article,
  categoryId,
  userId,
  appId,
  aiModel,
  aiConfidence,
}) {
  assertUser({ userId, appId });
  if (!article || !categoryId) {
    throw new Error(
      'articleId and categoryId are mandatory when creating ArticleCategory.'
    );
  }

  const now = new Date().toISOString();

  const articleCategory = {
    userId,
    appId,
    aiModel,
    aiConfidence,
    positiveFeedbackCount: 0,
    negativeFeedbackCount: 0,
    categoryId,
    status: 'NORMAL',
    createdAt: now,
    updatedAt: now,
  };

  const {
    result: articleResult,
    get: { _source },
  } = await client.update({
    index: 'articles',
    type: 'doc',
    id: article.id,
    body: {
      script: {
        /**
         * Check if the category is already connected in the article.
         * If so, do nothing;
         * otherwise, do update.
         */
        source: `
          def found = ctx._source.articleCategories.stream()
            .filter(ar -> ar.get('categoryId').equals(params.articleCategory.get('categoryId')))
            .findFirst();

          if (found.isPresent()) {
            HashMap ar = found.get();
            if (ar.get('status').equals('DELETED')) {
              ar.put('status', 'NORMAL');
              ar.put('userId', '${userId}');
              ar.put('appId', '${appId}');
              ar.put('updatedAt', '${now}');
            } else {
              ctx.op = 'none';
            }
          } else {
            ctx._source.articleCategories.add(params.articleCategory);
            ctx._source.normalArticleCategoryCount = ctx._source.articleCategories.stream().filter(
              ar -> ar.get('status').equals('NORMAL')
            ).count();
          }
        `,
        lang: 'painless',
        params: { articleCategory },
      },
      _source: ['articleCategories.*'],
    },
  });

  if (articleResult === 'noop') {
    throw new Error(
      `Cannot add articleCategory ${JSON.stringify(
        articleCategory
      )} to article ${article.id}`
    );
  }

  return _source.articleCategories;
}

export default {
  type: new GraphQLList(ArticleCategory),
  description: 'Adds specified category to specified article.',
  args: {
    articleId: { type: new GraphQLNonNull(GraphQLString) },
    categoryId: { type: new GraphQLNonNull(GraphQLString) },
    aiModel: { type: GraphQLString },
    aiConfidence: { type: GraphQLFloat },
  },
  async resolve(
    rootValue,
    { articleId, categoryId, aiModel, aiConfidence },
    { userId, appId, loaders }
  ) {
    const article = await loaders.docLoader.load({
      index: 'articles',
      id: articleId,
    });

    const articleCategories = await createArticleCategory({
      article,
      categoryId,
      userId,
      appId,
      aiModel,
      aiConfidence,
    });

    // When returning, insert articleId so that ArticleReply object type can resolve article.
    return articleCategories.map(ac => ({ ...ac, articleId }));
  },
};
<|endoftext|>


<commit_before>/**
 * Hooks into `require()` to watch for modifications of the required
 * file. If a modification is detected, the process exits with code
 * `101`.
 */

/**
 * Module dependencies.
 */
var fs = require('fs');
var Path = require('path');

/**
 * Watches the given module's filename.
 */
function watch(module) {
  if (!module.loaded) {
    fs.watchFile(module.filename, {interval : 500}, function(cur, prev) {
      if (cur && +cur.mtime !== +prev.mtime) {
        process.exit(101);
      }
    });
  }
}

//['node', '/pathto/wrapper.js', '--option1', '--optionN', 'script', 'arg1', 'argN']
process.argv.splice(1, 1);

var arg;
for (var i=1; i < process.argv.length; i++) {
  arg = process.argv[i];
  if (!/^-/.test(arg)) {
    break;
  }
}
var main = Path.resolve(process.cwd(), arg);

/**
 * Hook into `require`.
 */
var requireJs = require.extensions['.js'];
require.extensions['.js'] = function(module, filename) {
  if (module.id == main) {
    module.id = '.';
    module.parent = null;
  }
  watch(module);
  requireJs(module, filename);
};

require(main);<commit_msg>Added comments<commit_after>/**
 * Hooks into `require()` to watch for modifications of the required
 * file. If a modification is detected, the process exits with code
 * `101`.
 */

/**
 * Module dependencies.
 */
var fs = require('fs');
var Path = require('path');

/**
 * Watches the given module's filename.
 */
function watch(module) {
  if (!module.loaded) {
    fs.watchFile(module.filename, {interval : 500}, function(cur, prev) {
      if (cur && +cur.mtime !== +prev.mtime) {
        process.exit(101);
      }
    });
  }
}

/**
 * This is how the argv array looks like:
 * `['node', '/path/to/wrapper.js', '--option1', '--optionN', 'script', 'arg1', 'argN']`
 * ... so we remove ourself:
 */
process.argv.splice(1, 1);

/** Find the first arg that is not an option, starting at index 1 */
var arg;
for (var i=1; i < process.argv.length; i++) {
  arg = process.argv[i];
  if (!/^-/.test(arg)) {
    break;
  }
}

/** Resolve the location of the main script relative to cwd */
var main = Path.resolve(process.cwd(), arg);

/** Hook into `require()` */
var requireJs = require.extensions['.js'];
require.extensions['.js'] = function(module, filename) {
  if (module.id == main) {
    module.id = '.';
    module.parent = null;
  }
  watch(module);
  requireJs(module, filename);
};

/** Load the wrapped script */
require(main);<|endoftext|>


<commit_before>/* @flow */

import React from "react";
import { Disposable } from "atom";

import StatusBar from "./status-bar-component";
import SignalListView from "./signal-list-view";

import { reactFactory } from "../../../utils";

import type { Store } from "../../../store";
import type Kernel from "../../../kernel";
import type MarkerStore from "../../../store/markers";

export class StatusBarConsumer {
  handleKernelCommand: Function;

  addStatusBar(
    store: Store,
    statusBar: atom$StatusBar,
    handleKernelCommand: Function
  ) {
    const statusBarElement = document.createElement("div");
    statusBarElement.classList.add("inline-block", "hydrogen");

    const statusBarTile = statusBar.addLeftTile({
      item: statusBarElement,
      priority: 100
    });

    this.handleKernelCommand = handleKernelCommand;

    const onClick = ({ kernel, markers }) => {
      this.showKernelCommands({ kernel, markers });
    };

    reactFactory(
      <StatusBar store={store} onClick={onClick} />,
      statusBarElement
    );

    const disposable = new Disposable(() => statusBarTile.destroy());
    store.subscriptions.add(disposable);
    return disposable;
  }

  showKernelCommands({ kernel, markers }) {
    if (!this.signalListView) {
      this.signalListView = new SignalListView(kernel);
      this.signalListView.onConfirmed = (kernelCommand: { command: string }) =>
        this.handleKernelCommand(kernelCommand, { kernel, markers });
    }
    this.signalListView.toggle();
  }
}

const statusBarConsumer = new StatusBarConsumer();
export default statusBarConsumer;
<commit_msg>fix flow<commit_after>/* @flow */

import React from "react";
import { Disposable } from "atom";

import StatusBar from "./status-bar-component";
import SignalListView from "./signal-list-view";

import { reactFactory } from "../../../utils";

import type { Store } from "../../../store";
import type Kernel from "../../../kernel";
import type MarkerStore from "../../../store/markers";

export class StatusBarConsumer {
  signalListView: SignalListView;
  handleKernelCommand: Function;

  addStatusBar(
    store: Store,
    statusBar: atom$StatusBar,
    handleKernelCommand: Function
  ) {
    const statusBarElement = document.createElement("div");
    statusBarElement.classList.add("inline-block", "hydrogen");

    const statusBarTile = statusBar.addLeftTile({
      item: statusBarElement,
      priority: 100
    });

    this.handleKernelCommand = handleKernelCommand;

    const onClick = ({ kernel, markers }) => {
      this.showKernelCommands({ kernel, markers });
    };

    reactFactory(
      <StatusBar store={store} onClick={onClick} />,
      statusBarElement
    );

    const disposable = new Disposable(() => statusBarTile.destroy());
    store.subscriptions.add(disposable);
    return disposable;
  }

  showKernelCommands({
    kernel,
    markers
  }: {
    kernel: Kernel,
    markers: MarkerStore
  }) {
    let signalListView = this.signalListView;
    if (!signalListView) {
      signalListView = new SignalListView(kernel);
      signalListView.onConfirmed = (kernelCommand: { command: string }) =>
        this.handleKernelCommand(kernelCommand, { kernel, markers });
      this.signalListView = signalListView;
    }
    signalListView.toggle();
  }
}

const statusBarConsumer = new StatusBarConsumer();
export default statusBarConsumer;
<|endoftext|>


<commit_before>// @flow

const moment = require('moment');

const { sendToLagoonLogs } = require('@lagoon/commons/src/logs');
const { logger } = require('@lagoon/commons/src/local-logging');
const {
  addBackup,
  getEnvironmentByOpenshiftProjectName
} = require('@lagoon/commons/src/api');
const R = require('ramda');

import type { WebhookRequestData } from '../types';

// TODO: Use this function and uncomment section in webhook-handler when single backup
// webhooks have all the needed data.
// async function resticbackupSnapshotFinishedNew(webhook: WebhookRequestData) {
//   const { webhooktype, event, uuid, body } = webhook;

//   try {
//     const { name, bucket_name, backup_metrics } = body;
//     const environmentResult = await getEnvironmentByOpenshiftProjectName(bucket_name);
//     const environment = R.prop('environmentByOpenshiftProjectName', environmentResult)

//     if (!environment) {
//       logger.warn(`Skipping ${webhooktype}:${event}. Error: environment ${bucket_name} not found.`);
//       return;
//     }

//     const backupId = R.prop('id', backup_metrics);
//     // mariadb expects a specific timeformat of 'YYYY-MM-DD HH:mm:ss'
//     const created = R.ifElse(
//       R.propSatisfies(timestamp => timestamp == 0, 'backup_end_timestamp'),
//       R.always(moment().format(
//         'YYYY-MM-DD HH:mm:ss'
//       )),
//       R.always(moment(R.prop('backup_end_timestamp', backup_metrics)).format(
//         'YYYY-MM-DD HH:mm:ss'
//       ))
//     )(backup_metrics);

//     let source;
//     const mountedPvc = R.path(['mounted_PVCs', 0], backup_metrics);
//     const folderName = R.pipe(
//       R.prop('Folder'),
//       R.replace(`${name}-`, ''),
//       R.replace('-prebackuppod', ''),
//     )(backup_metrics);

//     if (mountedPvc) {
//       source = mountedPvc;
//     } else if (folderName) {
//       source = folderName;
//     } else {
//       source = 'unknown';
//     }

//     await addBackup(null, environment.id, source, backupId, created);

//     return;
//   } catch (error) {
//     sendToLagoonLogs(
//       'error',
//       '',
//       uuid,
//       `${webhooktype}:${event}:error`,
//       {
//         data: body
//       },
//       `Could not sync snapshots, reason: ${error}`
//     );

//     return;
//   }
// }

async function resticbackupSnapshotFinished(webhook: WebhookRequestData) {
  const { webhooktype, event, uuid, body } = webhook;

  try {
    const { name, bucket_name, snapshots } = body;
    const environmentResult = await getEnvironmentByOpenshiftProjectName(name);
    const environment = R.prop('environmentByOpenshiftProjectName', environmentResult)

    if (!environment) {
      logger.warn(`Skipping ${webhooktype}:${event}. Error: environment ${name} not found.`);
      return;
    }

    const snapshot = R.prop(0, snapshots);
    if (!snapshot) {
      logger.warn(`Skipping ${webhooktype}:${event}. Error: no snapshot data.`);
      return;
    }

    const backupId = R.prop('id', snapshot);
    // mariadb expects a specific timeformat of 'YYYY-MM-DD HH:mm:ss'
    const created = moment(R.prop('time', snapshot)).format(
      'YYYY-MM-DD HH:mm:ss'
    );

    // Determine source from the snapshot path.
    // 1: `/data/*` --> means this is a PVC we use whatever is after `/data/` as the name of the backup
    // 2: `*.tar` or `*.sql` --> current implementation with the name of the backup right before the ending, for example: foo.bar.tar (the backup is called `bar`)
    let source;
    const paths = R.prop('paths', snapshot);
    const pattern = /^\/data\/([\w-]+)|([\w-]+).(?:sql|tar)$/;
    if (R.isEmpty(paths)) {
      source = 'unknown';
    } else {
      const path = R.head(paths);
      if (!R.test(pattern, path)) {
        source = 'unknown';
      } else {
        const matches = R.match(pattern, path);
        if (R.prop(1, matches)) {
          source = R.prop(1, matches);
        } else if (R.prop(2, matches)) {
          source = R.prop(2, matches);
        } else {
          source = 'unknown';
        }
      }
    }

    await addBackup(null, environment.id, source, backupId, created);

    return;
  } catch (error) {
    sendToLagoonLogs(
      'error',
      '',
      uuid,
      `${webhooktype}:${event}:error`,
      {
        data: body
      },
      `Could not sync snapshots, reason: ${error}`
    );

    return;
  }
}

module.exports = resticbackupSnapshotFinished;
<commit_msg>Cater for missing extensions in the restic backups.<commit_after>// @flow

const moment = require('moment');

const { sendToLagoonLogs } = require('@lagoon/commons/src/logs');
const { logger } = require('@lagoon/commons/src/local-logging');
const {
  addBackup,
  getEnvironmentByOpenshiftProjectName
} = require('@lagoon/commons/src/api');
const R = require('ramda');

import type { WebhookRequestData } from '../types';

// TODO: Use this function and uncomment section in webhook-handler when single backup
// webhooks have all the needed data.
// async function resticbackupSnapshotFinishedNew(webhook: WebhookRequestData) {
//   const { webhooktype, event, uuid, body } = webhook;

//   try {
//     const { name, bucket_name, backup_metrics } = body;
//     const environmentResult = await getEnvironmentByOpenshiftProjectName(bucket_name);
//     const environment = R.prop('environmentByOpenshiftProjectName', environmentResult)

//     if (!environment) {
//       logger.warn(`Skipping ${webhooktype}:${event}. Error: environment ${bucket_name} not found.`);
//       return;
//     }

//     const backupId = R.prop('id', backup_metrics);
//     // mariadb expects a specific timeformat of 'YYYY-MM-DD HH:mm:ss'
//     const created = R.ifElse(
//       R.propSatisfies(timestamp => timestamp == 0, 'backup_end_timestamp'),
//       R.always(moment().format(
//         'YYYY-MM-DD HH:mm:ss'
//       )),
//       R.always(moment(R.prop('backup_end_timestamp', backup_metrics)).format(
//         'YYYY-MM-DD HH:mm:ss'
//       ))
//     )(backup_metrics);

//     let source;
//     const mountedPvc = R.path(['mounted_PVCs', 0], backup_metrics);
//     const folderName = R.pipe(
//       R.prop('Folder'),
//       R.replace(`${name}-`, ''),
//       R.replace('-prebackuppod', ''),
//     )(backup_metrics);

//     if (mountedPvc) {
//       source = mountedPvc;
//     } else if (folderName) {
//       source = folderName;
//     } else {
//       source = 'unknown';
//     }

//     await addBackup(null, environment.id, source, backupId, created);

//     return;
//   } catch (error) {
//     sendToLagoonLogs(
//       'error',
//       '',
//       uuid,
//       `${webhooktype}:${event}:error`,
//       {
//         data: body
//       },
//       `Could not sync snapshots, reason: ${error}`
//     );

//     return;
//   }
// }

async function resticbackupSnapshotFinished(webhook: WebhookRequestData) {
  const { webhooktype, event, uuid, body } = webhook;

  try {
    const { name, bucket_name, snapshots } = body;
    const environmentResult = await getEnvironmentByOpenshiftProjectName(name);
    const environment = R.prop('environmentByOpenshiftProjectName', environmentResult)

    if (!environment) {
      logger.warn(`Skipping ${webhooktype}:${event}. Error: environment ${name} not found.`);
      return;
    }

    const snapshot = R.prop(0, snapshots);
    if (!snapshot) {
      logger.warn(`Skipping ${webhooktype}:${event}. Error: no snapshot data.`);
      return;
    }

    const backupId = R.prop('id', snapshot);
    // mariadb expects a specific timeformat of 'YYYY-MM-DD HH:mm:ss'
    const created = moment(R.prop('time', snapshot)).format(
      'YYYY-MM-DD HH:mm:ss'
    );

    // Determine source from the snapshot path. This is used in the UI to show
    // the type of backup this is.
    //
    // 1: `/data/*` --> means this is a PVC we use whatever is after `/data/` as
    // the name of the backup.
    // 2: `*.tar` or `*.sql` --> current implementation with the name of the
    // backup right before the ending. For example: foo.bar.tar (the backup is
    // called `bar`). This logic is made slightly more complex by the fact that
    // there was a bug in the k8up system that produced filenames like
    //
    // * drupal-example-site-master-solr-prebackuppod.solr.tar
    // * drupal-example-site-master-solr-prebackuppod
    // * drupal-example-site-master-mariadb-prebackuppod
    // * drupal-example-site-master-mariadb-prebackuppod.mariadb.sql
    //
    // So we need to cater for these additional filenames.
    let source;
    const paths = R.prop('paths', snapshot);
    const pattern = /^\/data\/([\w-]+)|([\w-]+)\.(?:sql|tar)$/;
    if (R.isEmpty(paths)) {
      source = 'unknown';
    } else {
      const path = R.head(paths);
      if (!R.test(pattern, path)) {
        // Cater for the case where the extension was missing, and we can take
        // a guess for the type of backup it is.
        const missingExtensionPattern = /([\w]+)-prebackuppod/;
        if (!R.test(missingExtensionPattern, path)) {
          source = 'unknown';
        } else {
          const matches = R.match(missingExtensionPattern, path);
          if (R.prop(1, matches)) {
            source = R.prop(1, matches);
          }
        }
      } else {
        const matches = R.match(pattern, path);
        if (R.prop(1, matches)) {
          source = R.prop(1, matches);
        } else if (R.prop(2, matches)) {
          source = R.prop(2, matches);
        } else {
          source = 'unknown';
        }
      }
    }

    await addBackup(null, environment.id, source, backupId, created);

    return;
  } catch (error) {
    sendToLagoonLogs(
      'error',
      '',
      uuid,
      `${webhooktype}:${event}:error`,
      {
        data: body
      },
      `Could not sync snapshots, reason: ${error}`
    );

    return;
  }
}

module.exports = resticbackupSnapshotFinished;
<|endoftext|>


<commit_before>// Using NAMI: https://github.com/marcelog/Nami/
var namiLib = require("nami");

var namiConfig = {
  host: "localhost",
  port: 5038,
  username: "admin",
  secret: "secret5"
};

var logger = require('log4js').getLogger('App.astools');
var nami = new namiLib.Nami(namiConfig);
var amiConnected = false;
/*
nami.on('namiEvent', function (event) { });
nami.on('namiEventDial', function (event) { });
nami.on('namiEventVarSet', function (event) { });
nami.on('namiEventHangup', function (event) { });
process.on('SIGINT', function () {
  nami.close();
  process.exit();
});
*/
nami.on('namiConnected', function (event) {
  //nami.send(new namiLib.Actions.CoreShowChannelsAction(), function(response){
  //  logger.debug(' ---- Response: ' + util.inspect(response));
  //});
  amiConnected = true;
});
nami.open();

/*
 'action':'originate',
 'channel':'SIP/myphone',
 'context':'default',
 'exten':1234,
 'priority':1,
 'variables':{
   'name1':'value1',
   'name2':'value2'
 }
*/
function asCallOriginate(data) {
  var to_number = data["to_number"];
  var connect_extn = data["connect_extn"];
  var record_call = data["record_call"];
  logger.info("New call to " + to_number + " from " + connect_extn + " call_record " + record_call);

  var action = new namiLib.Actions.Originate();
  action.Channel = 'SIP/' + to_number;
  action.Context = "click2call";
  action.Exten = connect_extn;
  action.Priority = 1;
  action.variables = {
    'call_record':record_call,
    'message':'',
    'tripid':0
  };
  standardSend(action);
}

function standardSend(action) {
  nami.send(action, function (response) {
    logger.debug(' ---- Response: ' + util.inspect(response));
  });
}

function makeNewCall(data) {
  if (amiConnected) {
    asCallOriginate(data);
  }
  return amiConnected;
}

module.exports.makeNewCall = makeNewCall;
<commit_msg>add callerID<commit_after>// Using NAMI: https://github.com/marcelog/Nami/
var namiLib = require("nami");

var namiConfig = {
  host: "localhost",
  port: 5038,
  username: "admin",
  secret: "secret5"
};

var logger = require('log4js').getLogger('App.astools');
var nami = new namiLib.Nami(namiConfig);
var amiConnected = false;
/*
nami.on('namiEvent', function (event) { });
nami.on('namiEventDial', function (event) { });
nami.on('namiEventVarSet', function (event) { });
nami.on('namiEventHangup', function (event) { });
process.on('SIGINT', function () {
  nami.close();
  process.exit();
});
*/
nami.on('namiConnected', function (event) {
  //nami.send(new namiLib.Actions.CoreShowChannelsAction(), function(response){
  //  logger.debug(' ---- Response: ' + util.inspect(response));
  //});
  amiConnected = true;
});
nami.open();

/*
 'action':'originate',
 'channel':'SIP/myphone',
 'context':'default',
 'exten':1234,
 'priority':1,
 'variables':{
   'name1':'value1',
   'name2':'value2'
 }
*/
function asCallOriginate(data) {
  var to_number = data["to_number"];
  var connect_extn = data["connect_extn"];
  var record_call = data["record_call"];
  logger.info("New call to " + to_number + " from " + connect_extn + " call_record " + record_call);

  var action = new namiLib.Actions.Originate();
  action.Channel = 'SIP/' + to_number;
  action.Context = "click2call";
  action.Exten = connect_extn;
  action.Priority = 1;
  action.CallerID = "MoveIVR Caller";
  action.variables = {
    'call_record':record_call,
    'message':'',
    'tripid':0
  };
  standardSend(action);
}

function standardSend(action) {
  nami.send(action, function (response) {
    logger.debug(' ---- Response: ' + util.inspect(response));
  });
}

function makeNewCall(data) {
  if (amiConnected) {
    asCallOriginate(data);
  }
  return amiConnected;
}

module.exports.makeNewCall = makeNewCall;
<|endoftext|>


<commit_before>var
    esPhinx;

(function ($) {
    "use strict";

    $.prototype.extend({

        autocomplete: function (nodeObject, options, callback) {
            var
                nonCharacterKeysPattern = new RegExp(esPhinx
                    .nonCharacterKeysPattern()),
                inline = false,
                searchTextBox = this,
                offlineListener,

                resolveAmountChar = function (options) {
                    if (options.afterAmountChar) {
                        return options.afterAmountChar;
                    } else {
                        return 1;
                    }
                },

                offlineSearch = function (nodeObject, options) {
                    var
                        resolvedAnswer;

                    if (typeof offlineListener == "function") {
                        searchTextBox.off("input", offlineListener);
                        searchTextBox.off("focus", offlineListener);
                    }

                    offlineListener = function (e) {
                        if (searchTextBox.value()) {
                            resolvedAnswer = resolveAnswer(nodeObject,
                                options.order);
                            callback.call($(this), resolvedAnswer.nodes,
                                          resolvedAnswer.maps, e);
                        } else {
                            callback.call($(this), $(), e);
                        }

                    };

                    searchTextBox.on("input", offlineListener);
                    searchTextBox.on("focus", offlineListener);
                },

                remoteSearch = function (options) {
                    var
                        amountChar = resolveAmountChar(options),
                        word,
                        prevText,
                        nextText,
                        nodeObject,
                        params,
                        resolvedAnswer,
                        clipboardData,

                        request = function (e) {
                            if (options.remote.params) {
                                params = options.remote.params
                                    .call(searchTextBox);
                            }

                            $.Ajax.new(options.remote.url
                                .call(searchTextBox), {
                                params: params,
                                progress: function (xhr) {
                                    if (options.remote.loading) {
                                        options.remote
                                            .loading(xhr, e);
                                    }
                                },
                                complete: function () {
                                    $(e.target).off("keypress");
                                },
                                success: function (a) {
                                    nodeObject = $(a);
                                    resolvedAnswer = resolveAnswer(nodeObject,
                                        options.order);
                                    // debugger
                                    callback.call(searchTextBox,
                                        resolvedAnswer.nodes,
                                        resolvedAnswer.maps, e);
                                    if (nodeObject.length) {
                                        offlineSearch(nodeObject,
                                            options);
                                    }
                                }
                            });
                        };

                    searchTextBox.on("keyup", function (e) {
                        word = searchTextBox.value();

                        if (word.length > amountChar) {
                            inline = true;
                        } else if (word.length < amountChar) {
                            inline = false;
                        }

                        if (word.length == amountChar &&
                            !nonCharacterKeysPattern.test(e.key) &&
                            !inline &&
                            options.remote) {
                            $(e.target).on("keypress", function (e) {
                                e.preventDefault();
                            });

                            request(e);
                        }

                    });

                    searchTextBox.on("paste", function (e) {
                        word = searchTextBox.value();
                        prevText = word
                            .slice(0, searchTextBox.cursorStart());
                        nextText = word
                            .slice(searchTextBox.cursorEnd(), word.length);

                        clipboardData = e.clipboardData.getData("text");

                        if (word.length >= amountChar) {
                            inline = true;
                        } else {
                            inline = false;
                        }

                        word = prevText + clipboardData + nextText;

                        if (word.length >= amountChar &&
                            !inline &&
                            options.remote) {
                            searchTextBox.value(word);

                            request(e);
                            e.preventDefault();
                        }
                    });

                },

                resolveAnswer = function (nodeCollection, order) {
                    if (order != "asc") {order = "desc";}
                // resolveAnswer = function (nodeCollection, order = "desc") {
                    var
                        found = {nodes: $(), maps: []},
                        textBoxContentArr = searchTextBox.value()
                            .toLowerCase().trim().split(" "),
                        nodeText,
                        mapped,
                        nodeTextAsArray;

                    if (nodeCollection.elements().count() === 1 &&
                        (nodeCollection.tagName() == "ul" ||
                        nodeCollection.tagName() == "ol")) {
                        nodeCollection = nodeCollection.childElements();
                    }

                    nodeCollection.sort(order).selectEach(function (node) {
                        nodeText = $(node).textContent().toLowerCase().trim();
                        nodeTextAsArray = nodeText.split(" ");
                        mapped = map(textBoxContentArr, nodeTextAsArray);
                        if (mapped) {
                            found.nodes.push(node);
                            found.maps.push(mapped);
                        }
                    });

                    return found;
                },

                map = function (searchTextAsArray, nodeTextAsArray) {
                    var
                        nodeTextHashSet = $.Object.asHashMap(nodeTextAsArray),
                        mapped = {},
                        count = 0,
                        lastIndex = -1,
                        index = 0,
                        i,
                        slice;

                    if (nodeTextHashSet.length >= searchTextAsArray.length) {

                        for (i in searchTextAsArray) {
                            if (searchTextAsArray.hasOwnProperty(i)) {
                                slice = searchTextAsArray[i];
                                slice = slice.trim();

                                index = $.Object
                                    .firstFromASlice(nodeTextHashSet, slice,
                                                        index);
                                if (index && nodeTextAsArray
                                    .countItemSlice(slice) >=
                                    searchTextAsArray.countItem(slice)
                                ) {
                                    lastIndex = index;
                                    mapped[index] = slice;
                                    $.Object.delete(nodeTextHashSet, index);
                                    count += 1;
                                } else {
                                    break;
                                }
                            }
                        }

                        if (count == searchTextAsArray.length) {
                            return mapped;
                        }
                    }

                    return false;
                };

            // init
            if (Object.getPrototypeOf(nodeObject) !=
                Object.getPrototypeOf({})) {
                offlineSearch(nodeObject, options);
            } else {
                options = nodeObject;
                remoteSearch(options);
            }
        }

    });

})(esPhinx);
<commit_msg>adequations<commit_after>var
    esPhinx;

(function ($) {
    "use strict";

    $.prototype.extend({

        autocomplete: function (nodeObject, options, callback) {
            var
                nonCharacterKeysPattern = new RegExp(esPhinx
                    .nonCharacterKeysPattern()),
                inline = false,
                searchTextBox = this,
                offlineListener,

                resolveAmountChar = function (options) {
                    if (options.afterAmountChar) {
                        return options.afterAmountChar;
                    } else {
                        return 1;
                    }
                },

                offlineSearch = function (nodeObject, options) {
                    var
                        resolvedAnswer;

                    if (typeof offlineListener == "function") {
                        searchTextBox.off("input", offlineListener);
                        searchTextBox.off("focus", offlineListener);
                    }

                    offlineListener = function (e) {
                        if (searchTextBox.value()) {
                            resolvedAnswer = resolveAnswer(nodeObject,
                                options.order);
                            callback.call($(this), resolvedAnswer.nodes,
                                          resolvedAnswer.maps, e);
                        } else {
                            callback.call($(this), $(), e);
                        }

                    };

                    searchTextBox.on("input", offlineListener);
                    searchTextBox.on("focus", offlineListener);
                },

                remoteSearch = function (options) {
                    var
                        amountChar = resolveAmountChar(options),
                        word,
                        prevText,
                        nextText,
                        nodeObject,
                        params,
                        resolvedAnswer,
                        clipboardData,

                        request = function (e) {
                            if (options.remote.params) {
                                params = options.remote.params
                                    .call(searchTextBox);
                            }

                            $.Ajax.new(options.remote.url
                                .call(searchTextBox), {
                                params: params,
                                progress: function (xhr) {
                                    if (options.remote.loading) {
                                        options.remote
                                            .loading(xhr, e);
                                    }
                                },
                                complete: function () {
                                    $(e.target).off("keypress");
                                },
                                success: function (a) {
                                    nodeObject = $(a);
                                    resolvedAnswer = resolveAnswer(nodeObject,
                                        options.order);
                                    // debugger
                                    callback.call(searchTextBox,
                                        resolvedAnswer.nodes,
                                        resolvedAnswer.maps, e);
                                    if (nodeObject.length) {
                                        offlineSearch(nodeObject,
                                            options);
                                    }
                                }
                            });
                        };

                    searchTextBox.on("keyup", function (e) {
                        word = searchTextBox.value();

                        if (word.length > amountChar) {
                            inline = true;
                        } else if (word.length < amountChar) {
                            inline = false;
                        }

                        if (word.length == amountChar &&
                            !nonCharacterKeysPattern.test(e.key) &&
                            !inline &&
                            options.remote) {
                            $(e.target).on("keypress", function (e) {
                                e.preventDefault();
                            });

                            request(e);
                        }

                    });

                    searchTextBox.on("paste", function (e) {
                        word = searchTextBox.value();
                        prevText = word
                            .slice(0, searchTextBox.cursorStart());
                        nextText = word
                            .slice(searchTextBox.cursorEnd(), word.length);

                        clipboardData = e.clipboardData.getData("text");

                        if (word.length >= amountChar) {
                            inline = true;
                        } else {
                            inline = false;
                        }

                        word = prevText + clipboardData + nextText;

                        if (word.length >= amountChar &&
                            !inline &&
                            options.remote) {
                            searchTextBox.value(word);

                            request(e);
                            e.preventDefault();
                        }
                    });

                },

                resolveAnswer = function (nodeCollection, order) {
                    if (order != "asc") {order = "desc";}
                // resolveAnswer = function (nodeCollection, order = "desc") {
                    var
                        found = {nodes: $(), maps: []},
                        textBoxContentArr = searchTextBox.value()
                            .toLowerCase().trim().split(" "),
                        nodeText,
                        mapped,
                        nodeTextAsArray;

                    if (nodeCollection.elements().count() === 1 &&
                        (nodeCollection.tagName() == "ul" ||
                        nodeCollection.tagName() == "ol")) {
                        nodeCollection = nodeCollection.childElements();
                    }

                    nodeCollection.sort(order).selectEach(function (node) {
                        nodeText = $(node).textContent().toLowerCase().trim();
                        nodeTextAsArray = nodeText.split(" ");
                        mapped = map(textBoxContentArr, nodeTextAsArray);
                        if (mapped) {
                            found.nodes.push(node);
                            found.maps.push(mapped);
                        }
                    });

                    return found;
                },

                map = function (searchTextAsArray, nodeTextAsArray) {
                    var
                        nodeTextHashSet = $.Object
                            .asMap(nodeTextAsArray),
                        mapped = {},
                        count = 0,
                        lastIndex = -1,
                        index = 0,
                        i,
                        slice;

                    if (nodeTextHashSet.length >= searchTextAsArray.length) {

                        for (i in searchTextAsArray) {
                            if (searchTextAsArray.hasOwnProperty(i)) {
                                slice = searchTextAsArray[i];
                                slice = slice.trim();

                                index = $.Object
                                    .firstFromASlice(nodeTextHashSet, slice,
                                                        index);
                                if (index && nodeTextAsArray
                                    .countItemSlice(slice) >=
                                    searchTextAsArray.countItem(slice)
                                ) {
                                    lastIndex = index;
                                    mapped[index] = slice;
                                    $.Object.delete(nodeTextHashSet, index);
                                    count += 1;
                                } else {
                                    break;
                                }
                            }
                        }

                        if (count == searchTextAsArray.length) {
                            return mapped;
                        }
                    }

                    return false;
                };

            // init
            if (Object.getPrototypeOf(nodeObject) !=
                Object.getPrototypeOf({})) {
                offlineSearch(nodeObject, options);
            } else {
                options = nodeObject;
                remoteSearch(options);
            }
        }

    });

})(esPhinx);
<|endoftext|>