<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief test the common database interface
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");
var internal = require("internal");
var arangodb = require("org/arangodb");
var ERRORS = arangodb.errors;

// -----------------------------------------------------------------------------
// --SECTION--                                                  database methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: database methods
////////////////////////////////////////////////////////////////////////////////

function DatabaseSuite () {
  return {

    setUp : function () {
      internal.db._useDatabase("_system");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test the version information
////////////////////////////////////////////////////////////////////////////////

    testVersion : function () {
      assertMatch(/^1\.4/, internal.db._version());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _name function
////////////////////////////////////////////////////////////////////////////////

    testName : function () {
      assertEqual("_system", internal.db._name());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _path function
////////////////////////////////////////////////////////////////////////////////

    testPath : function () {
      assertTrue(typeof internal.db._path() === "string");
      assertTrue(internal.db._path() !== "");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _isSystem function
////////////////////////////////////////////////////////////////////////////////

    testIsSystem : function () {
      assertTrue(typeof internal.db._isSystem() === "boolean");
      assertTrue(internal.db._isSystem());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _query function
////////////////////////////////////////////////////////////////////////////////

    testQuery : function () {
      assertEqual([ 1 ], internal.db._query("return 1").toArray());
      assertEqual([ [ 1, 2, 9, "foo" ] ], internal.db._query("return [ 1, 2, 9, \"foo\" ]").toArray());
      assertEqual([ [ 1, 454 ] ], internal.db._query("return [ @low, @high ]", { low : 1, high : 454 }).toArray());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _executeTransaction
////////////////////////////////////////////////////////////////////////////////

    testExecuteTransaction1 : function () {
      var result = internal.db._executeTransaction({
        collections: { },
        action: function (params) {
          return params.v1 + params.v2;
        },
        params: {
          "v1": 1,
          "v2": 2
        }
      });

      assertEqual(3, result);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _executeTransaction
////////////////////////////////////////////////////////////////////////////////

    testExecuteTransaction2 : function () {
      var result = internal.db._executeTransaction({
        collections: { },
        action: "function () { return params.v1[0] - params.v1[1]; }",
        params: {
          "v1": [ 10, 4 ],
        }
      });

      assertEqual(6, result);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _listDatabases function
////////////////////////////////////////////////////////////////////////////////

    testListDatabases : function () {
      var actual, n;

      assertEqual("_system", internal.db._name());

      actual = internal.db._listDatabases();
      assertTrue(Array.isArray(actual));
      n = actual.length;
      assertTrue(n > 0);
      assertTrue(function () {
        for (var i = 0; i < actual.length; ++i) {
          if (actual[i] === "_system") {
            return true;
          }
        }
        return false;
      }());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");

      actual = internal.db._listDatabases();
      assertTrue(Array.isArray(actual));
      assertEqual(n + 1, actual.length);
      assertTrue(function () {
        for (var i = 0; i < actual.length; ++i) {
          if (actual[i] === "UnitTestsDatabase0") {
            return true;
          }
        }
        return false;
      }());

      internal.db._dropDatabase("UnitTestsDatabase0");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabase : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      try {
        internal.db._dropDatabase("UnitTestsDatabase1");
      }
      catch (err2) {
      }

      assertTrue(internal.db._createDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._createDatabase("UnitTestsDatabase1"));

      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._dropDatabase("UnitTestsDatabase1"));
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseInvalidName : function () {
      assertEqual("_system", internal.db._name());

      [ "", " ", "-", "0", "99999", ":::", "fox::", "test!" ].forEach (function (d) {
        try {
          internal.db._createDatabase(d);
          fail();
        }
        catch (err) {
          assertEqual(ERRORS.ERROR_ARANGO_DATABASE_NAME_INVALID.code, err.errorNum)
        }
      });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseNonSystem : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");
      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());

      // creation of new databases should fail here
      try {
        internal.db._createDatabase("UnitTestsDatabase1");
        fail();
      }
      catch (err2) {
        assertEqual(ERRORS.ERROR_ARANGO_USE_SYSTEM_DATABASE.code, err2.errorNum)
      }

      // removing a database should fail here
      try {
        internal.db._dropDatabase("UnitTestsDatabase1");
        fail();
      }
      catch (err3) {
        assertEqual(ERRORS.ERROR_ARANGO_USE_SYSTEM_DATABASE.code, err3.errorNum)
      }

      internal.db._useDatabase("_system");
      internal.db._dropDatabase("UnitTestsDatabase0");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseDuplicate : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");

      try {
        internal.db._createDatabase("UnitTestsDatabase0");
        fail();
      }
      catch (err2) {
        assertEqual(ERRORS.ERROR_ARANGO_DUPLICATE_NAME.code, err2.errorNum)
      }

      internal.db._dropDatabase("UnitTestsDatabase0");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseCase : function () {
      assertEqual("_system", internal.db._name());

      var getCollections = function () {
        var result = [ ];

        internal.db._collections().forEach(function (c) {
          if (c.name()[0] !== '_') {
            result.push(c.name());
          }
        });
        result.sort();

        return result;
      };

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      try {
        internal.db._dropDatabase("UNITTESTSDATABASE0");
      }
      catch (err2) {
      }

      assertTrue(internal.db._createDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._createDatabase("UNITTESTSDATABASE0"));

      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());
      var c1 = internal.db._create("test1");
      assertEqual([ "test1" ], getCollections());
      c1.save({ "_key": "foo" });
      assertEqual(1, internal.db._collection("test1").count());
      assertEqual(1, c1.count());

      internal.db._useDatabase("UNITTESTSDATABASE0");
      assertEqual("UNITTESTSDATABASE0", internal.db._name());
      var c2 = internal.db._create("test1");
      assertEqual([ "test1" ], getCollections());
      c2.save({ "_key": "foo" });
      c2.save({ "_key": "bar" });
      c2.save({ "_key": "baz" });
      assertEqual(3, internal.db._collection("test1").count());
      assertEqual(3, c2.count());

      c1.remove("foo");
      assertEqual(0, c1.count());
      assertEqual(3, c2.count());
      assertEqual(3, internal.db._collection("test1").count());

      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual(0, c1.count());
      assertEqual(3, c2.count());
      assertEqual(0, internal.db._collection("test1").count());
      c1.drop();
      c1 = null;

      internal.db._useDatabase("UNITTESTSDATABASE0");
      assertEqual(3, internal.db._collection("test1").count());
      assertEqual(3, c2.count());
      c2.remove("foo");
      assertEqual(2, internal.db._collection("test1").count());
      assertEqual(2, c2.count());

      internal.db._useDatabase("_system");
      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._dropDatabase("UNITTESTSDATABASE0"));
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _useDatabase function
////////////////////////////////////////////////////////////////////////////////

    testUseDatabase : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");
      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());

      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());

      internal.db._useDatabase("_system");
      assertEqual("_system", internal.db._name());

      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));

      try {
        internal.db._useDatabase("UnitTestsDatabase0");
        fail();
      }
      catch (err2) {
        assertTrue(err2.errorNum === ERRORS.ERROR_ARANGO_DATABASE_NOT_FOUND.code ||
                   err2.errorNum === ERRORS.ERROR_HTTP_NOT_FOUND.code);
      }

      assertEqual("_system", internal.db._name());

      try {
        internal.db._useDatabase("THISDATABASEDOESNOTEXIST");
        fail();
      }
      catch (err3) {
        assertTrue(err3.errorNum === ERRORS.ERROR_ARANGO_DATABASE_NOT_FOUND.code ||
                   err3.errorNum === ERRORS.ERROR_HTTP_NOT_FOUND.code);
      }
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _dropDatabase function
////////////////////////////////////////////////////////////////////////////////

    testDropDatabase : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      var isContained = function (name) {
        var l = internal.db._listDatabases();
        for (var i = 0; i < l.length; ++i) {
          if (l[i] === name) {
            return true;
          }
        }
        return false;
      };

      internal.db._createDatabase("UnitTestsDatabase0");
      assertTrue(isContained("UnitTestsDatabase0"));
      assertTrue(isContained("_system"));

      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));
      assertFalse(isContained("UnitTestsDatabase0"));
      assertTrue(isContained("_system"));
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                              main
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////

jsunity.run(DatabaseSuite);

return jsunity.done();

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

<commit_msg>added tests for collections caching<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief test the common database interface
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");
var internal = require("internal");
var arangodb = require("org/arangodb");
var ERRORS = arangodb.errors;

// -----------------------------------------------------------------------------
// --SECTION--                                                  database methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: database methods
////////////////////////////////////////////////////////////////////////////////

function DatabaseSuite () {
  return {

    setUp : function () {
      internal.db._useDatabase("_system");
    },

    tearDown : function () {
      // always go back to system database
      internal.db._useDatabase("_system");

      try {
        // drop this database if it exists
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err) {
        // ignore
      }
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test the version information
////////////////////////////////////////////////////////////////////////////////

    testVersion : function () {
      assertMatch(/^1\.4/, internal.db._version());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _name function
////////////////////////////////////////////////////////////////////////////////

    testName : function () {
      assertEqual("_system", internal.db._name());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _path function
////////////////////////////////////////////////////////////////////////////////

    testPath : function () {
      assertTrue(typeof internal.db._path() === "string");
      assertTrue(internal.db._path() !== "");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _isSystem function
////////////////////////////////////////////////////////////////////////////////

    testIsSystem : function () {
      assertTrue(typeof internal.db._isSystem() === "boolean");
      assertTrue(internal.db._isSystem());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _query function
////////////////////////////////////////////////////////////////////////////////

    testQuery : function () {
      assertEqual([ 1 ], internal.db._query("return 1").toArray());
      assertEqual([ [ 1, 2, 9, "foo" ] ], internal.db._query("return [ 1, 2, 9, \"foo\" ]").toArray());
      assertEqual([ [ 1, 454 ] ], internal.db._query("return [ @low, @high ]", { low : 1, high : 454 }).toArray());
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _executeTransaction
////////////////////////////////////////////////////////////////////////////////

    testExecuteTransaction1 : function () {
      var result = internal.db._executeTransaction({
        collections: { },
        action: function (params) {
          return params.v1 + params.v2;
        },
        params: {
          "v1": 1,
          "v2": 2
        }
      });

      assertEqual(3, result);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _executeTransaction
////////////////////////////////////////////////////////////////////////////////

    testExecuteTransaction2 : function () {
      var result = internal.db._executeTransaction({
        collections: { },
        action: "function () { return params.v1[0] - params.v1[1]; }",
        params: {
          "v1": [ 10, 4 ],
        }
      });

      assertEqual(6, result);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _listDatabases function
////////////////////////////////////////////////////////////////////////////////

    testListDatabases : function () {
      var actual, n;

      assertEqual("_system", internal.db._name());

      actual = internal.db._listDatabases();
      assertTrue(Array.isArray(actual));
      n = actual.length;
      assertTrue(n > 0);
      assertTrue(function () {
        for (var i = 0; i < actual.length; ++i) {
          if (actual[i] === "_system") {
            return true;
          }
        }
        return false;
      }());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");

      actual = internal.db._listDatabases();
      assertTrue(Array.isArray(actual));
      assertEqual(n + 1, actual.length);
      assertTrue(function () {
        for (var i = 0; i < actual.length; ++i) {
          if (actual[i] === "UnitTestsDatabase0") {
            return true;
          }
        }
        return false;
      }());

      internal.db._dropDatabase("UnitTestsDatabase0");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabase : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      try {
        internal.db._dropDatabase("UnitTestsDatabase1");
      }
      catch (err2) {
      }

      assertTrue(internal.db._createDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._createDatabase("UnitTestsDatabase1"));

      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._dropDatabase("UnitTestsDatabase1"));
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseInvalidName : function () {
      assertEqual("_system", internal.db._name());

      [ "", " ", "-", "0", "99999", ":::", "fox::", "test!" ].forEach (function (d) {
        try {
          internal.db._createDatabase(d);
          fail();
        }
        catch (err) {
          assertEqual(ERRORS.ERROR_ARANGO_DATABASE_NAME_INVALID.code, err.errorNum);
        }
      });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseNonSystem : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");
      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());

      // creation of new databases should fail here
      try {
        internal.db._createDatabase("UnitTestsDatabase1");
        fail();
      }
      catch (err2) {
        assertEqual(ERRORS.ERROR_ARANGO_USE_SYSTEM_DATABASE.code, err2.errorNum);
      }

      // removing a database should fail here
      try {
        internal.db._dropDatabase("UnitTestsDatabase1");
        fail();
      }
      catch (err3) {
        assertEqual(ERRORS.ERROR_ARANGO_USE_SYSTEM_DATABASE.code, err3.errorNum);
      }

      internal.db._useDatabase("_system");
      internal.db._dropDatabase("UnitTestsDatabase0");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseDuplicate : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");

      try {
        internal.db._createDatabase("UnitTestsDatabase0");
        fail();
      }
      catch (err2) {
        assertEqual(ERRORS.ERROR_ARANGO_DUPLICATE_NAME.code, err2.errorNum);
      }

      internal.db._dropDatabase("UnitTestsDatabase0");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _createDatabase function
////////////////////////////////////////////////////////////////////////////////

    testCreateDatabaseCase : function () {
      assertEqual("_system", internal.db._name());

      var getCollections = function () {
        var result = [ ];

        internal.db._collections().forEach(function (c) {
          if (c.name()[0] !== '_') {
            result.push(c.name());
          }
        });
        result.sort();

        return result;
      };

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      try {
        internal.db._dropDatabase("UNITTESTSDATABASE0");
      }
      catch (err2) {
      }

      assertTrue(internal.db._createDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._createDatabase("UNITTESTSDATABASE0"));

      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());
      var c1 = internal.db._create("test1");
      assertEqual([ "test1" ], getCollections());
      c1.save({ "_key": "foo" });
      assertEqual(1, internal.db._collection("test1").count());
      assertEqual(1, c1.count());

      internal.db._useDatabase("UNITTESTSDATABASE0");
      assertEqual("UNITTESTSDATABASE0", internal.db._name());
      var c2 = internal.db._create("test1");
      assertEqual([ "test1" ], getCollections());
      c2.save({ "_key": "foo" });
      c2.save({ "_key": "bar" });
      c2.save({ "_key": "baz" });
      assertEqual(3, internal.db._collection("test1").count());
      assertEqual(3, c2.count());

      c1.remove("foo");
      assertEqual(0, c1.count());
      assertEqual(3, c2.count());
      assertEqual(3, internal.db._collection("test1").count());

      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual(0, c1.count());
      assertEqual(3, c2.count());
      assertEqual(0, internal.db._collection("test1").count());
      c1.drop();
      c1 = null;

      internal.db._useDatabase("UNITTESTSDATABASE0");
      assertEqual(3, internal.db._collection("test1").count());
      assertEqual(3, c2.count());
      c2.remove("foo");
      assertEqual(2, internal.db._collection("test1").count());
      assertEqual(2, c2.count());

      internal.db._useDatabase("_system");
      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));
      assertTrue(internal.db._dropDatabase("UNITTESTSDATABASE0"));
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _useDatabase function
////////////////////////////////////////////////////////////////////////////////

    testUseDatabase : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      internal.db._createDatabase("UnitTestsDatabase0");
      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());

      internal.db._useDatabase("UnitTestsDatabase0");
      assertEqual("UnitTestsDatabase0", internal.db._name());

      internal.db._useDatabase("_system");
      assertEqual("_system", internal.db._name());

      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));

      try {
        internal.db._useDatabase("UnitTestsDatabase0");
        fail();
      }
      catch (err2) {
        assertTrue(err2.errorNum === ERRORS.ERROR_ARANGO_DATABASE_NOT_FOUND.code ||
                   err2.errorNum === ERRORS.ERROR_HTTP_NOT_FOUND.code);
      }

      assertEqual("_system", internal.db._name());

      try {
        internal.db._useDatabase("THISDATABASEDOESNOTEXIST");
        fail();
      }
      catch (err3) {
        assertTrue(err3.errorNum === ERRORS.ERROR_ARANGO_DATABASE_NOT_FOUND.code ||
                   err3.errorNum === ERRORS.ERROR_HTTP_NOT_FOUND.code);
      }
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test _dropDatabase function
////////////////////////////////////////////////////////////////////////////////

    testDropDatabase : function () {
      assertEqual("_system", internal.db._name());

      try {
        internal.db._dropDatabase("UnitTestsDatabase0");
      }
      catch (err1) {
      }

      var isContained = function (name) {
        var l = internal.db._listDatabases();
        for (var i = 0; i < l.length; ++i) {
          if (l[i] === name) {
            return true;
          }
        }
        return false;
      };

      internal.db._createDatabase("UnitTestsDatabase0");
      assertTrue(isContained("UnitTestsDatabase0"));
      assertTrue(isContained("_system"));

      assertTrue(internal.db._dropDatabase("UnitTestsDatabase0"));
      assertFalse(isContained("UnitTestsDatabase0"));
      assertTrue(isContained("_system"));
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test collection cache in the face of collection deletion
////////////////////////////////////////////////////////////////////////////////

    testCollectionsCache1 : function () {
      var db = internal.db;
      var name = "UnitTestsCollectionCache";

      db._drop(name);

      db._create(name);

      db[name].save({ _key: "test", value: 1 });
      var cid = db[name]._id;
      assertEqual(name, db[name].name());
      assertEqual(1, db[name].count());
      assertEqual(1, db[name].document("test").value);

      // remove the collection and re-create a new one with the same name
      db._drop(name);

      db._create(name);
      db[name].save({ _key: "foo", value: 1 });
      db[name].save({ _key: "test", value: 2 });

      assertNotEqual(cid, db[name]._id);
      assertEqual(name, db[name].name());
      assertEqual(2, db[name].count());
      assertEqual(1, db[name].document("foo").value);
      assertEqual(2, db[name].document("test").value);

      db._drop(name);

      try {
        db[name].save({ _key: "foo", value: 1 });
        fail();
      }
      catch (err) {
        // cannot call method ... of undefined
        assertMatch(/^Cannot call method.*of undefined/, err.message);
      }
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test collection cache in the face of database changes
////////////////////////////////////////////////////////////////////////////////

    testCollectionsCache2 : function () {
      var db = internal.db;
      var name = "UnitTestsCollectionCache";

      assertTrue("_system", db._name());

      db._drop(name);
      db._create(name);

      db[name].save({ _key: "foo", value: 1 });
      var cid = db[name]._id;
      assertEqual(name, db[name].name());
      assertEqual(1, db[name].count());

      // switch the database
      db._createDatabase("UnitTestsDatabase0");
      db._useDatabase("UnitTestsDatabase0");

      // collection should not yet exist in other database
      try {
        db[name].save({ _key: "foo", value: 1 });
        fail();
      }
      catch (err) {
        // cannot call method ... of undefined
        assertMatch(/^Cannot call method.*of undefined/, err.message);
      }

      db._create(name);
      assertNotEqual(cid, db[name]._id);
      assertEqual(name, db[name].name());
      assertEqual(0, db[name].count());

      db[name].save({ _key: "foo", value: 1 });
      db[name].save({ _key: "bar", value: 1 });
      assertEqual(2, db[name].count());

      db._useDatabase("_system");
      assertEqual(1, db[name].count());

      db._dropDatabase("UnitTestsDatabase0");
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                              main
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////

jsunity.run(DatabaseSuite);

return jsunity.done();

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

<|endoftext|>


<commit_before>zr.controller('TeamManagementController', ['$scope', 'teamResources', 'zrdb', function($scope, teamResources, zrdb) {
	$scope.teams = teamResources.data.rows;
	$scope.currentTeam = null;
	$scope.isLead = true;
	$scope.newmem = {
		email: ''
	};
	$scope.countries = ['United States', 'Austria', 'Belgium', 'Czech Republic', 'Denmark', 'Finland', 'France', 'Germany', 'Greece', 'Ireland', 'Italy', 'Luxembourg', 'Netherlands', 'Norway', 'Poland', 'Portugal', 'Romania', 'Spain', 'Sweden', 'Switzerland', 'United Kingdom'];
	$scope.states = ["", "AK", "AL", "AR", "AS", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", "FM", "GA", "GU", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MH", "MI", "MN", "MO", "MP", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "PR", "PW", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VI", "VT", "WA", "WI", "WV", "WY"];

	$scope.setTeam = function(team) {
		$scope.currentTeam = team;
	};
	if($scope.teams && $scope.teams.length !== 0) {
		$scope.setTeam($scope.teams[0]);
	}

	var ms = $scope.currentTeam.tournamentsTeammembershipCollection; //Short name!

	//For editing the basic team info
	$scope.setData = function() {
		zrdb.putResource('team', $scope.currentTeam.id, $scope.currentTeam);
	};
	$scope.deleteMember = function(m) {
		zrdb.deleteResource('teammembership', m.id, function() {
			var index = ms.indexOf(m);
			ms.splice(index, 1);
		});
	}
	$scope.addMember = function() {
		var resource = {
			'inviteAccepted': false,
			'isLead': false,
			'teamId': $scope.currentTeam.id,
			'email': $scope.newmem.email,
			'tournamentId': 17 //TODO: Separate rosters for different tournaments
		};
		zrdb.addResource('teammembership', resource, function() {
			zrdb.getSingleResource('team', $scope.currentTeam.id, true).then(function(data) {
				$scope.$apply(function() {
					ms = data.tournamentsTeammembershipCollection;
				});
			})
		});
		$scope.newEmail = '';
	}
}]);
<commit_msg>Team management<commit_after>zr.controller('TeamManagementController', ['$scope', 'teamResources', 'zrdb', '$timeout', function($scope, teamResources, zrdb, $timeout) {
	$scope.teams = teamResources.data.rows;
	$scope.currentTeam = null;
	$scope.isLead = true;
	$scope.newmem = {
		email: ''
	};
	$scope.countries = ['United States', 'Austria', 'Belgium', 'Czech Republic', 'Denmark', 'Finland', 'France', 'Germany', 'Greece', 'Ireland', 'Italy', 'Luxembourg', 'Netherlands', 'Norway', 'Poland', 'Portugal', 'Romania', 'Spain', 'Sweden', 'Switzerland', 'United Kingdom'];
	$scope.states = ["", "AK", "AL", "AR", "AS", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", "FM", "GA", "GU", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MH", "MI", "MN", "MO", "MP", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "PR", "PW", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VI", "VT", "WA", "WI", "WV", "WY"];

	$scope.setTeam = function(team) {
		$scope.currentTeam = team;
	};
	if($scope.teams && $scope.teams.length !== 0) {
		$scope.setTeam($scope.teams[0]);
	}

	var ms = $scope.currentTeam.tournamentsTeammembershipCollection; //Short name!

	//For editing the basic team info
	$scope.setData = function() {
		zrdb.putResource('team', $scope.currentTeam.id, $scope.currentTeam);
	};
	$scope.deleteMember = function(m) {
		zrdb.deleteResource('teammembership', m.id, function() {
			var index = ms.indexOf(m);
			ms.splice(index, 1);
		});
	}
	$scope.addMember = function() {
		var resource = {
			'inviteAccepted': false,
			'isLead': false,
			'teamId': $scope.currentTeam.id,
			'email': $scope.newmem.email,
			'tournamentId': 17 //TODO: Separate rosters for different tournaments
		};
		zrdb.addResource('teammembership', resource, function() {
			zrdb.getSingleResource('team', $scope.currentTeam.id, true).then(function(data) {
				$timeout(function() {
					ms = data.tournamentsTeammembershipCollection;
				});
			})
		});
		$scope.newEmail = '';
	}
}]);
<|endoftext|>


<commit_before>define(
[
  'jQuery',
  'color-thief'
],
function($, ColorThief) { 'use strict';

var myUpdateBackgroundFactory = function(appSettings) {
  var thief = new ColorThief();

  return function(scope, element, attrs) {
    scope.$watch(attrs.dLoad, function(value) {
      element.on('load', function() {
        var color = null;

        try {
          color = thief.getColor(element.get(0));
        } catch(e) {}

        var backgrounds = [];

        if (appSettings.showThumbnails) {
          backgrounds.push(
            'url(\'http://api.snapito.com/web/sapuk-363c81e6-0e5e082b-73e5544a-71f3-4f05fc39-3/250x188?url=' +
              encodeURIComponent(scope.bookmark.url) +
              '&delay=1\')'
          );
        }

        backgrounds.push(color ? 'rgb(' + color.join(',') + ')' : 'white');

        var thumbnail = $('.thumbnail-loading', element.parent().parent().parent());
        thumbnail
          .removeClass('thumbnail-loading')
          .addClass('thumbnail')
          .css('background', backgrounds.join(', '));
      });
    });
  };
};

return [
  'appSettings',
  myUpdateBackgroundFactory
];

});<commit_msg>added Snapito api parameter<commit_after>define(
[
  'jQuery',
  'color-thief'
],
function($, ColorThief) { 'use strict';

var myUpdateBackgroundFactory = function(appSettings) {
  var thief = new ColorThief();

  return function(scope, element, attrs) {
    scope.$watch(attrs.dLoad, function(value) {
      element.on('load', function() {
        var color = null;

        try {
          color = thief.getColor(element.get(0));
        } catch(e) {}

        var backgrounds = [];

        if (appSettings.showThumbnails) {
          backgrounds.push(
            'url(\'http://api.snapito.com/web/sapuk-363c81e6-0e5e082b-73e5544a-71f3-4f05fc39-3/250x188?url=' +
              encodeURIComponent(scope.bookmark.url) +
              '&delay=1&freshness=-1\')'
          );
        }

        backgrounds.push(color ? 'rgb(' + color.join(',') + ')' : 'white');

        var thumbnail = $('.thumbnail-loading', element.parent().parent().parent());
        thumbnail
          .removeClass('thumbnail-loading')
          .addClass('thumbnail')
          .css('background', backgrounds.join(', '));
      });
    });
  };
};

return [
  'appSettings',
  myUpdateBackgroundFactory
];

});<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 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.
 */

CLASS({
  name: 'MultiDAO',
  package: 'foam.navigator.dao',
  extendsModel: 'AbstractDAO',

  requires: [
    'EasyDAO',
    'foam.navigator.BrowserConfig',
    'foam.navigator.dao.ModelIDDecoratorDAO',
    'foam.navigator.dao.IDConfig'
  ],

  imports: [
    'console'
  ],

  properties: [
    {
      name: 'models',
      model_: 'StringArrayProperty',
      factory: function() { return []; }
    },
    {
      name: 'configDAO',
      model_: 'DAOProperty',
      documentation: multiline(function() {/*
        A DAO of objects that must each have o.dao (a DAO) and o.model (a
        model).
      */}),
      factory: function() {
        return this.EasyDAO.create({
          model: this.BrowserConfig,
          daoType: 'IDB',
          seqNo: true,
          cache: true
        });
      }
    },
    {
      name: 'daos',
      factory: function() { return {}; }
    },
    {
      name: 'idDecoratorConfig',
      factory: function() { return this.IDConfig.create(); }
    },
    {
      name: 'listeners_',
      model_: 'ArrayProperty',
      factory: function() { return []; }
    }
  ],

    methods: [
      {
        name: 'init',
        code: function() {
          this.SUPER();
          this.configDAO.pipe({
            put: function(config) {
              this.buildDAO(config);
            }.bind(this)
          });
        }
      },
      {
        name: 'put',
        code: function(obj, opt_sink) {
          var model = obj.model_;
          var name = model.package ?
              model.package + '.' + model.name : model.name;
          if ( ! this.daos[name] ) {
            var msg = 'Model: "' + name + '" unknown to MultiDAO';
            this.console.warn(msg);
            opt_sink && opt_sink.error(msg);
          } else {
            this.daos[name].put(obj, opt_sink);
          }
        }
      },
      {
        name: 'remove',
        code: function(id, opt_sink) {
          var modelName = this.idDecoratorConfig.getModelName(id);
          this.daos[modelName].remove(id, opt_sink);
        }
      },
      {
        name: 'removeAll',
        code: function(sink, options) {
          var proxySink = {
            remove: sink && sink.remove,
            error: sink && sink.error
          };
          var self = this;
          return apar.apply(null, this.models.map(function(modelName) {
            return self.daos[modelName].aseq(function(ret, dao) {
              dao.removeAll(proxySink, options)(ret);
            });
          })).aseq(function(ret) {
            sink && sink.eof && sink.eof();
            ret && ret(sink);
          });
        }
      },
      {
        name: 'find',
        code: function(id, sink) {
          var modelName = this.idDecoratorConfig.getModelName(id);
          if ( ! this.dao[modelName] ) {
            sink.error('Unknown model name prefix in ID: ' + id);
            return;
          }
          this.dao[modelName](function(dao) {
            dao.find(id, sink);
          });
        }
      },
      {
        name: 'select',
        todo: 'Need proper options support',
        code: function(sink, options) {
          var proxySink = {
            put: function(o) {
              sink && sink.put && sink.put(o);
            },
            error: function() {
              sink && sink.error && sink.error.apply(this, arguments);
            }
          };
          var self = this;
          return apar.apply(null, this.models.map(function(modelName) {
            return self.daos[modelName].aseq(function(ret, dao) {
              dao.select(proxySink, options)(ret);
            });
          })).aseq(function(ret) {
            sink && sink.eof && sink.eof();
            ret && ret.call(null, sink);
          });
        }
      },
      {
        name: 'update',
        code: function(expr) {
          throw 'update() not supported on MultiDAO (yet)';
        }
      },
      {
        name: 'listen',
        code: function(sink) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].listen(sink);
          }.bind(this));
          this.listeners_.push(sink);
        }
      },
      {
        name: 'pipe',
        code: function(sink) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].pipe(sink);
          }.bind(this));
        }
      },
      {
        name: 'unlisten',
        code: function(sink) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].unlisten(sink);
          }.bind(this));
          this.listeners_ = this.listeners_.filter(function(listener) {
            return listener !== sink;
          }.bind(this));
        }
      },
      {
        name: 'limit',
        todo: 'This is an alright approximation, but we can probably do better',
        code: function(count) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].limit(count);
          }.bind(this));
        }
      },
      {
        name: 'buildDAO',
        code: function(config) {
          var model = config.model;
          var modelName = model.package ?
              model.package + '.' + model.name : model.name;
          var decoratedConfigDAO = this.ModelIDDecoratorDAO.create({
            config: this.idDecoratorConfig,
            delegate: config.dao
          });
          this.addListenersToDAO(decoratedConfigDAO);
          this.daos[modelName] = decoratedConfigDAO;
          return decoratedConfigDAO;
        }
      },
      {
        name: 'addListenersToDAO',
        code: function(dao) {
          this.listeners_.forEach(function(listener) {
            dao.listen(listener);
          }.bind(this));
        }
      }
    ]
  });
<commit_msg>MultiDAO: Fix a bug where this.models was not being populated as the configs are walked.<commit_after>/**
 * @license
 * Copyright 2015 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.
 */

CLASS({
  name: 'MultiDAO',
  package: 'foam.navigator.dao',
  extendsModel: 'AbstractDAO',

  requires: [
    'EasyDAO',
    'foam.navigator.BrowserConfig',
    'foam.navigator.dao.ModelIDDecoratorDAO',
    'foam.navigator.dao.IDConfig'
  ],

  imports: [
    'console'
  ],

  properties: [
    {
      name: 'models',
      model_: 'StringArrayProperty',
      factory: function() { return []; }
    },
    {
      name: 'configDAO',
      model_: 'DAOProperty',
      documentation: multiline(function() {/*
        A DAO of objects that must each have o.dao (a DAO) and o.model (a
        model).
      */}),
      factory: function() {
        return this.EasyDAO.create({
          model: this.BrowserConfig,
          daoType: 'IDB',
          seqNo: true,
          cache: true
        });
      }
    },
    {
      name: 'daos',
      factory: function() { return {}; }
    },
    {
      name: 'idDecoratorConfig',
      factory: function() { return this.IDConfig.create(); }
    },
    {
      name: 'listeners_',
      model_: 'ArrayProperty',
      factory: function() { return []; }
    }
  ],

    methods: [
      {
        name: 'init',
        code: function() {
          this.SUPER();
          this.configDAO.pipe({
            put: function(config) {
              this.buildDAO(config);
            }.bind(this)
          });
        }
      },
      {
        name: 'put',
        code: function(obj, opt_sink) {
          var model = obj.model_;
          var name = model.package ?
              model.package + '.' + model.name : model.name;
          if ( ! this.daos[name] ) {
            var msg = 'Model: "' + name + '" unknown to MultiDAO';
            this.console.warn(msg);
            opt_sink && opt_sink.error(msg);
          } else {
            this.daos[name].put(obj, opt_sink);
          }
        }
      },
      {
        name: 'remove',
        code: function(id, opt_sink) {
          var modelName = this.idDecoratorConfig.getModelName(id);
          this.daos[modelName].remove(id, opt_sink);
        }
      },
      {
        name: 'removeAll',
        code: function(sink, options) {
          var proxySink = {
            remove: sink && sink.remove,
            error: sink && sink.error
          };
          var self = this;
          return apar.apply(null, this.models.map(function(modelName) {
            return self.daos[modelName].aseq(function(ret, dao) {
              dao.removeAll(proxySink, options)(ret);
            });
          })).aseq(function(ret) {
            sink && sink.eof && sink.eof();
            ret && ret(sink);
          });
        }
      },
      {
        name: 'find',
        code: function(id, sink) {
          var modelName = this.idDecoratorConfig.getModelName(id);
          if ( ! this.dao[modelName] ) {
            sink.error('Unknown model name prefix in ID: ' + id);
            return;
          }
          this.dao[modelName](function(dao) {
            dao.find(id, sink);
          });
        }
      },
      {
        name: 'select',
        todo: 'Need proper options support',
        code: function(sink, options) {
          var proxySink = {
            put: function(o) {
              sink && sink.put && sink.put(o);
            },
            error: function() {
              sink && sink.error && sink.error.apply(this, arguments);
            }
          };
          var self = this;
          return apar.apply(null, this.models.map(function(modelName) {
            return self.daos[modelName].aseq(function(ret, dao) {
              dao.select(proxySink, options)(ret);
            });
          })).aseq(function(ret) {
            sink && sink.eof && sink.eof();
            ret && ret.call(null, sink);
          });
        }
      },
      {
        name: 'update',
        code: function(expr) {
          throw 'update() not supported on MultiDAO (yet)';
        }
      },
      {
        name: 'listen',
        code: function(sink) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].listen(sink);
          }.bind(this));
          this.listeners_.push(sink);
        }
      },
      {
        name: 'pipe',
        code: function(sink) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].pipe(sink);
          }.bind(this));
        }
      },
      {
        name: 'unlisten',
        code: function(sink) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].unlisten(sink);
          }.bind(this));
          this.listeners_ = this.listeners_.filter(function(listener) {
            return listener !== sink;
          }.bind(this));
        }
      },
      {
        name: 'limit',
        todo: 'This is an alright approximation, but we can probably do better',
        code: function(count) {
          this.models.forEach(function(modelName) {
            this.daos[modelName].limit(count);
          }.bind(this));
        }
      },
      {
        name: 'buildDAO',
        code: function(config) {
          var model = config.model;
          var modelName = model.package ?
              model.package + '.' + model.name : model.name;
          var decoratedConfigDAO = this.ModelIDDecoratorDAO.create({
            config: this.idDecoratorConfig,
            delegate: config.dao
          });
          this.addListenersToDAO(decoratedConfigDAO);
          this.daos[modelName] = decoratedConfigDAO;
          this.models.push(modelName);
          return decoratedConfigDAO;
        }
      },
      {
        name: 'addListenersToDAO',
        code: function(dao) {
          this.listeners_.forEach(function(listener) {
            dao.listen(listener);
          }.bind(this));
        }
      }
    ]
  });
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 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.
 */

CLASS({
  package: 'foam.ui.md',
  name: 'UpdateDetailView',
  extendsModel: 'foam.ui.md.DetailView',

  requires: [
    'foam.ui.PopupChoiceView',
    'foam.ui.md.Toolbar',
    'foam.ui.md.ToolbarAction'
  ],

  imports: [
    'dao',
    'stack'
  ],
  exports: [
    'toolbar$'
  ],

  properties: [
    {
      name: 'title',
      dynamicValue: function() {
        return (this.data && this.data.id ? 'Edit' : 'New') +
            (this.model ? ' ' + this.model.label : '');
      }
    },
    {
      name: 'rawData',
      documentation: 'The uncloned original input data.',
      postSet: function(old, nu) {
        if ( old ) old.removeListener(this.rawUpdate);
        if ( nu ) nu.addListener(this.rawUpdate);
      }
    },
    {
      name: 'originalData',
      documentation: 'A clone of the input data, for comparison with edits.'
    },
    {
      name: 'data',
      preSet: function(_, v) {
        if ( ! v ) return undefined;
        this.rawData = v;
        return v.deepClone();
      },
      postSet: function(_, data) {
        if ( ! data ) return;
        this.originalData = data.deepClone();
        if ( data && data.model_ ) this.model = data.model_;
        var self = this;
        data.addPropertyListener(null, function(o, topic) {
          var prop = o.model_.getProperty(topic[1]);
          if ( prop.transient ) return;
          self.version++;
          self.rawData = '';
        });
      }
    },
    {
      name: 'immutable',
      documentation: 'Set to true if the view should never switch to ' +
          'X-and-check mode, even when there are changes.',
      defaultValue: false
    },
    {
      name: 'liveEdit',
      documentation: "Propagate edits immediately, and don't show the save button",
      defaultValue: false
    },
    {
      name: 'exitOnSave',
      documentation: "If true, saving will also exit the view.",
      defaultValue: false
    },
    {
      // Version of the data which changes whenever any property of the data is updated.
      // Used to help trigger isEnabled / isAvailable in Actions.
      model_: 'IntProperty',
      name: 'version'
    },
    {
      model_: 'BooleanProperty',
      name: 'showModelActions',
      defaultValue: true
    },
    {
      model_: 'BooleanProperty',
      name: 'outstandingChanges',
      hidden: true,
      dynamicValue: function() {
        this.version; this.immutable;
        return ! this.immutable && ! this.originalData.equals(this.data);
      },
      postSet: function(old,nu) {
        if ( nu && this.liveEdit ) {
          this.save();
        }
      }
    },
    {
      type: 'foam.ui.md.Toolbar',
      name: 'toolbar',
      lazyFactory: function() {
        return this.Toolbar.create({
          data$: this.data$,
          title$: this.title$
        }, this.Y);
      },
      postSet: function(old, nu) {
        if ( old === nu ) return;
        if ( old ) {
          old.removeLeftActions(this.leftActions_);
          old.removeRightActions(this.rightActions_);
        }
        if ( nu ) {
          nu.addLeftActions(this.leftActions_);
          nu.addRightActions(this.rightActions_);
        }
      }
    },
    {
      model_: 'ViewFactoryProperty',
      name: 'innerView',
      defaultValue: 'foam.ui.md.DetailView'
    },
    {
      name: 'className',
      defaultValue: 'md-update-detail-view'
    },
    {
      model_: 'ArrayProperty',
      name: 'leftActions_',
      lazyFactory: function() {
        var myModel = this.model_;
        return [
          this.ToolbarAction.create({
            data: this,
            action: myModel.getAction('back')
          }, this.Y),
          this.ToolbarAction.create({
            data: this,
            action: myModel.getAction('reset')
          }, this.Y)
        ];
      },
      postSet: function(old, nu) {
        var toolbar = this.toolbar;
        if ( old === nu || ! toolbar ) return;
        if ( old ) toolbar.removeLeftActions(old);
        if ( nu ) toolbar.addLeftActions(nu);
      }
    },
    {
      model_: 'ArrayProperty',
      name: 'rightActions_',
      lazyFactory: function() {
        return [
          this.ToolbarAction.create({
            data: this,
            action: this.model_.getAction('save')
          }, this.Y)
        ];
      },
      postSet: function(old, nu) {
        var toolbar = this.toolbar;
        if ( old === nu || ! toolbar ) return;
        if ( old ) toolbar.removeRightActions(old);
        if ( nu ) toolbar.addRightActions(nu);
      }
    }
  ],

  actions: [
    {
      name: 'back',
      help:  'Go back',
      priority: 0,
      order: 0.0,
      iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAPUlEQVQ4y2NgGLbgf8P/BtKU////+78WacpDSFMeSlPlYaQo/0OacjyAcg1wJ4WTGmHDS4sWaVrqhm/mBQAoLpX9t+4i2wAAAABJRU5ErkJggg==',
      ligature: 'arrow_back',
      isAvailable: function() { return ! this.outstandingChanges; },
      action: function() { this.stack.popView(); }
    },
    {
      name: 'save',
      help:  'Save updates',
      priority: 0,
      order: 0,
      iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAUElEQVQ4jWNgGAW4wH9d0pRH///zv4E05f+J1jB0lP9n+b/0fzgJpv8PBUr++R9BgmP+N4C1RJLgdqiWKBK8CtVCUsiAtBCvHKqFFOUjAwAATIhwjZSqeJcAAAAASUVORK5CYII=',
      ligature: 'check',
      isAvailable: function() { return this.outstandingChanges; },
      action: function() {
        var self = this;
        var obj  = this.data;

        this.dao.put(obj, {
          put: function() {
            self.originalData = obj.deepClone();

            if (self.exitOnSave && ! self.liveEdit) {
              self.stack.popView();
            }
          },
          error: function() {
            console.error('Error saving', arguments);
          }
        });
      }
    },
    {
      name: 'reset',
      priority: 0,
      order: 1.0,
      help: 'Reset form (cancel update)',
      iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAdklEQVQ4y+WTuQ3AIBAEaQKK8NN/BEUArmccgGyj43MMIZo5TqtFqbUPJxYtbg2OvS44IJQKhguwdUETSiXjXr77KhGICRjihWKm8Dw3KXP4Z5VZ/Lfw7B5kyD1cy5C7uAx5iJcht6vhRTUi4OrC0Szftvi/vAFNdbZ2Dp661QAAAABJRU5ErkJggg==',
      ligature: 'close',
      isAvailable: function() { return this.outstandingChanges; },
      action: function() { this.data = this.originalData.deepClone(); }
    }
  ],

  listeners: [
    {
      name: 'rawUpdate',
      code: function() {
        // If this listener fires, the raw data updated and the user hasn't
        // changed anything.
        this.data = this.rawData;
      }
    }
  ],

  templates: [
    function CSS() {/*
      .md-update-detail-view {
        display: flex;
        flex-direction: column;
        height: 100%;
        width: 100%;
      }
      .md-update-detail-view-body {
        overflow-x: hidden;
        overflow-y: auto;
        //width: 100%;
        display: flex;

      }
    */},
    function toHTML() {/*
      <div id="<%= this.id %>" <%= this.cssClassAttr() %>>
        %%toolbar

          <%= this.innerView({ data$: this.data$ }, this.Y) %>

    */}
  ]
});
<commit_msg>MD UpdateDetailView: live edit mode: back always available, commit and reset never available<commit_after>/**
 * @license
 * Copyright 2015 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.
 */

CLASS({
  package: 'foam.ui.md',
  name: 'UpdateDetailView',
  extendsModel: 'foam.ui.md.DetailView',

  requires: [
    'foam.ui.PopupChoiceView',
    'foam.ui.md.Toolbar',
    'foam.ui.md.ToolbarAction'
  ],

  imports: [
    'dao',
    'stack'
  ],
  exports: [
    'toolbar$'
  ],

  properties: [
    {
      name: 'title',
      dynamicValue: function() {
        return (this.data && this.data.id ? 'Edit' : 'New') +
            (this.model ? ' ' + this.model.label : '');
      }
    },
    {
      name: 'rawData',
      documentation: 'The uncloned original input data.',
      postSet: function(old, nu) {
        if ( old ) old.removeListener(this.rawUpdate);
        if ( nu ) nu.addListener(this.rawUpdate);
      }
    },
    {
      name: 'originalData',
      documentation: 'A clone of the input data, for comparison with edits.'
    },
    {
      name: 'data',
      preSet: function(_, v) {
        if ( ! v ) return undefined;
        this.rawData = v;
        return v.deepClone();
      },
      postSet: function(_, data) {
        if ( ! data ) return;
        this.originalData = data.deepClone();
        if ( data && data.model_ ) this.model = data.model_;
        var self = this;
        data.addPropertyListener(null, function(o, topic) {
          var prop = o.model_.getProperty(topic[1]);
          if ( prop.transient ) return;
          self.version++;
          self.rawData = '';
        });
      }
    },
    {
      name: 'immutable',
      documentation: 'Set to true if the view should never switch to ' +
          'X-and-check mode, even when there are changes.',
      defaultValue: false
    },
    {
      name: 'liveEdit',
      documentation: "Propagate edits immediately, and don't show the save button",
      defaultValue: false
    },
    {
      name: 'exitOnSave',
      documentation: "If true, saving will also exit the view.",
      defaultValue: false
    },
    {
      // Version of the data which changes whenever any property of the data is updated.
      // Used to help trigger isEnabled / isAvailable in Actions.
      model_: 'IntProperty',
      name: 'version'
    },
    {
      model_: 'BooleanProperty',
      name: 'showModelActions',
      defaultValue: true
    },
    {
      model_: 'BooleanProperty',
      name: 'outstandingChanges',
      hidden: true,
      dynamicValue: function() {
        this.version; this.immutable;
        return ! this.immutable && ! this.originalData.equals(this.data);
      },
      postSet: function(old,nu) {
        if ( nu && this.liveEdit ) {
          this.save();
        }
      }
    },
    {
      type: 'foam.ui.md.Toolbar',
      name: 'toolbar',
      lazyFactory: function() {
        return this.Toolbar.create({
          data$: this.data$,
          title$: this.title$
        }, this.Y);
      },
      postSet: function(old, nu) {
        if ( old === nu ) return;
        if ( old ) {
          old.removeLeftActions(this.leftActions_);
          old.removeRightActions(this.rightActions_);
        }
        if ( nu ) {
          nu.addLeftActions(this.leftActions_);
          nu.addRightActions(this.rightActions_);
        }
      }
    },
    {
      model_: 'ViewFactoryProperty',
      name: 'innerView',
      defaultValue: 'foam.ui.md.DetailView'
    },
    {
      name: 'className',
      defaultValue: 'md-update-detail-view'
    },
    {
      model_: 'ArrayProperty',
      name: 'leftActions_',
      lazyFactory: function() {
        var myModel = this.model_;
        return [
          this.ToolbarAction.create({
            data: this,
            action: myModel.getAction('back')
          }, this.Y),
          this.ToolbarAction.create({
            data: this,
            action: myModel.getAction('reset')
          }, this.Y)
        ];
      },
      postSet: function(old, nu) {
        var toolbar = this.toolbar;
        if ( old === nu || ! toolbar ) return;
        if ( old ) toolbar.removeLeftActions(old);
        if ( nu ) toolbar.addLeftActions(nu);
      }
    },
    {
      model_: 'ArrayProperty',
      name: 'rightActions_',
      lazyFactory: function() {
        return [
          this.ToolbarAction.create({
            data: this,
            action: this.model_.getAction('save')
          }, this.Y)
        ];
      },
      postSet: function(old, nu) {
        var toolbar = this.toolbar;
        if ( old === nu || ! toolbar ) return;
        if ( old ) toolbar.removeRightActions(old);
        if ( nu ) toolbar.addRightActions(nu);
      }
    }
  ],

  actions: [
    {
      name: 'back',
      help:  'Go back',
      priority: 0,
      order: 0.0,
      iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAPUlEQVQ4y2NgGLbgf8P/BtKU////+78WacpDSFMeSlPlYaQo/0OacjyAcg1wJ4WTGmHDS4sWaVrqhm/mBQAoLpX9t+4i2wAAAABJRU5ErkJggg==',
      ligature: 'arrow_back',
      isAvailable: function() { return this.liveEdit || ! this.outstandingChanges; },
      action: function() { this.stack.popView(); }
    },
    {
      name: 'save',
      help:  'Save updates',
      priority: 0,
      order: 0,
      iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAUElEQVQ4jWNgGAW4wH9d0pRH///zv4E05f+J1jB0lP9n+b/0fzgJpv8PBUr++R9BgmP+N4C1RJLgdqiWKBK8CtVCUsiAtBCvHKqFFOUjAwAATIhwjZSqeJcAAAAASUVORK5CYII=',
      ligature: 'check',
      isAvailable: function() { return  ! this.liveEdit && this.outstandingChanges; },
      action: function() {
        var self = this;
        var obj  = this.data;

        this.dao.put(obj, {
          put: function() {
            self.originalData = obj.deepClone();

            if (self.exitOnSave && ! self.liveEdit) {
              self.stack.popView();
            }
          },
          error: function() {
            console.error('Error saving', arguments);
          }
        });
      }
    },
    {
      name: 'reset',
      priority: 0,
      order: 1.0,
      help: 'Reset form (cancel update)',
      iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAdklEQVQ4y+WTuQ3AIBAEaQKK8NN/BEUArmccgGyj43MMIZo5TqtFqbUPJxYtbg2OvS44IJQKhguwdUETSiXjXr77KhGICRjihWKm8Dw3KXP4Z5VZ/Lfw7B5kyD1cy5C7uAx5iJcht6vhRTUi4OrC0Szftvi/vAFNdbZ2Dp661QAAAABJRU5ErkJggg==',
      ligature: 'close',
      isAvailable: function() { return  ! this.liveEdit && this.outstandingChanges; },
      action: function() { this.data = this.originalData.deepClone(); }
    }
  ],

  listeners: [
    {
      name: 'rawUpdate',
      code: function() {
        // If this listener fires, the raw data updated and the user hasn't
        // changed anything.
        this.data = this.rawData;
      }
    }
  ],

  templates: [
    function CSS() {/*
      .md-update-detail-view {
        display: flex;
        flex-direction: column;
        height: 100%;
        width: 100%;
      }
      .md-update-detail-view-body {
        overflow-x: hidden;
        overflow-y: auto;
        //width: 100%;
        display: flex;

      }
    */},
    function toHTML() {/*
      <div id="<%= this.id %>" <%= this.cssClassAttr() %>>
        %%toolbar

          <%= this.innerView({ data$: this.data$ }, this.Y) %>

    */}
  ]
});
<|endoftext|>