offline copy link and better feedback when saving

Added offline copy link (still rough UI) and improved feedback when performing tasks that would eventually save data (long operation)
This commit is contained in:
Giulio Cesare Solaroli
2015-01-02 10:13:04 +01:00
parent 88f9bc2cdf
commit 132af87411
8 changed files with 180 additions and 145 deletions
@@ -22,12 +22,12 @@ refer to http://www.clipperz.com.
*/ */
"use strict"; "use strict";
Clipperz.Base.module('Clipperz.PM.DataModel');
try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) { try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.PM.DataModel.EncryptedRemoteObject depends on Clipperz.KeyValueObjectStore!"; throw "Clipperz.PM.DataModel.EncryptedRemoteObject depends on Clipperz.KeyValueObjectStore!";
} }
Clipperz.Base.module('Clipperz.PM.DataModel');
//if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } //if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
//if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
@@ -46,21 +46,19 @@ Clipperz.PM.DataModel.EncryptedRemoteObject = function(args) {
this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction || null; this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction || null;
this._remoteData = args.remoteData || null; this._remoteData = args.remoteData || null;
// this._remoteData = args.remoteData ? Clipperz.Base.deepClone(args.remoteData) : null;
if ((!this._isBrandNew) && ((this._retrieveRemoteDataFunction == null) && (this._remoteData == null))) { if ((!this._isBrandNew) && ((this._retrieveRemoteDataFunction == null) && (this._remoteData == null))) {
Clipperz.Base.exception.raise('MandatoryParameter'); Clipperz.Base.exception.raise('MandatoryParameter');
} }
this._encryptedDataKeypath = args.encryptedDataKeypath || 'data';
this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter'); this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version';
this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version'; //Clipperz.Base.exception.raise('MandatoryParameter');
this._transientState = null; this._transientState = null;
this._deferredLocks = {}; this._deferredLocks = {};
if (this._isBrandNew == true) { if (this._isBrandNew == true) {
this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [1]'}*/); this._objectDataStore = new Clipperz.KeyValueObjectStore();
} else { } else {
this._objectDataStore = null; this._objectDataStore = null;
} }
@@ -111,7 +109,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'transientState': function () { 'transientState': function () {
if (this._transientState == null) { if (this._transientState == null) {
this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.transientState [2]'}*/); this._transientState = new Clipperz.KeyValueObjectStore();
} }
return this._transientState; return this._transientState;
@@ -166,6 +164,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
'hasLoadedRemoteData': function () { 'hasLoadedRemoteData': function () {
//console.log("EncryptedRemoteObject.hasLoadedRemoteData", this._remoteData);
return (this._remoteData != null); return (this._remoteData != null);
}, },
@@ -237,7 +236,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'decryptedDataStore': function () { 'decryptedDataStore': function () {
if (this._decryptedDataStore == null) { if (this._decryptedDataStore == null) {
this._decryptedDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.decryptedDataStore [3]'}*/); this._decryptedDataStore = new Clipperz.KeyValueObjectStore();
}; };
return this._decryptedDataStore; return this._decryptedDataStore;
@@ -343,7 +342,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
if (this._objectDataStore == null) { if (this._objectDataStore == null) {
//console.log("EncryptedRemoteObject._getObjectDataStore", this._reference); //console.log("EncryptedRemoteObject._getObjectDataStore", this._reference);
this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [4]'}*/); this._objectDataStore = new Clipperz.KeyValueObjectStore();
innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore <inner deferred>", {trace:false}); innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore <inner deferred>", {trace:false});
innerDeferredResult.addMethod(this, 'getDecryptedData'); innerDeferredResult.addMethod(this, 'getDecryptedData');
@@ -434,7 +433,6 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'commitTransientState': function () { 'commitTransientState': function () {
var deferredResult; var deferredResult;
// if (this.transientState().getValue('__prepareRemoteData') == true) {
if (this.transientState().getValue('packedRemoteData') != null) { if (this.transientState().getValue('packedRemoteData') != null) {
deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [ deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [
MochiKit.Base.bind(function (someData) { MochiKit.Base.bind(function (someData) {
@@ -463,6 +461,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
'revertChanges': function () { 'revertChanges': function () {
//console.log("> EncryptedRemoveObject.revertChanges", this.toString(), this.hasInitiatedObjectDataStore());
if (this.hasInitiatedObjectDataStore()) { if (this.hasInitiatedObjectDataStore()) {
this._objectDataStore.removeAllData(); this._objectDataStore.removeAllData();
this._objectDataStore = null; this._objectDataStore = null;
@@ -523,7 +522,6 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'prepareRemoteDataWithKey': function (aKey) { 'prepareRemoteDataWithKey': function (aKey) {
return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [ return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [
// MochiKit.Base.method(this.transientState(), 'setValue', '__prepareRemoteData', true),
MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.method(this, '_getObjectDataStore'),
MochiKit.Base.methodcaller('values'), MochiKit.Base.methodcaller('values'),
MochiKit.Base.method(this, 'packData'), MochiKit.Base.method(this, 'packData'),
@@ -21,6 +21,9 @@ refer to http://www.clipperz.com.
*/ */
"use strict";
Clipperz.Base.module('Clipperz.PM.DataModel');
try { if (typeof(Clipperz.PM.DataModel.Record) == 'undefined') { throw ""; }} catch (e) { try { if (typeof(Clipperz.PM.DataModel.Record) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.PM.DataModel.Record.Version depends on Clipperz.PM.DataModel.Record!"; throw "Clipperz.PM.DataModel.Record.Version depends on Clipperz.PM.DataModel.Record!";
} }
@@ -29,7 +32,7 @@ Clipperz.PM.DataModel.Record.Version = function(args) {
Clipperz.PM.DataModel.Record.Version.superclass.constructor.apply(this, arguments); Clipperz.PM.DataModel.Record.Version.superclass.constructor.apply(this, arguments);
this._getVersionFunction = args.getVersion || Clipperz.Base.exception.raise('MandatoryParameter'); this._getVersionFunction = args.getVersion || Clipperz.Base.exception.raise('MandatoryParameter');
this._fields = null; // this._fields = null;
return this; return this;
} }
@@ -43,9 +46,9 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version, Clipperz.PM.DataModel
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
'reference': function () { // 'reference': function () {
return this._reference; // return this._reference;
}, // },
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/* /*
@@ -128,13 +131,13 @@ console.log("Record.Version.hasPendingChanges");
deferredResult.addCallback(MochiKit.Base.bind(function () { deferredResult.addCallback(MochiKit.Base.bind(function () {
var innerDeferredResult; var innerDeferredResult;
if (this._fields == null) { // if (this._fields == null) {
innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false}); innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false});
innerDeferredResult.addMethod(this, 'getValue', 'fields'); innerDeferredResult.addMethod(this, 'getValue', 'fields');
innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) { innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) {
var reference; var reference;
var result = {};
this._fields = {}; // this._fields = {};
for (reference in someObjectData) { for (reference in someObjectData) {
var recordVersionField; var recordVersionField;
@@ -144,15 +147,17 @@ console.log("Record.Version.hasPendingChanges");
'reference': reference 'reference': reference
}); });
this._fields[reference] = recordVersionField; // this._fields[reference] = recordVersionField;
result[reference] = recordVersionField;
} }
return this._fields; // return this._fields;
return result;
}, this)); }, this));
innerDeferredResult.callback(); innerDeferredResult.callback();
} else { // } else {
innerDeferredResult = MochiKit.Async.succeed(this._fields); // innerDeferredResult = MochiKit.Async.succeed(this._fields);
} // }
return innerDeferredResult; return innerDeferredResult;
}, this)); }, this));
@@ -182,10 +187,9 @@ console.log("Record.Version.hasPendingChanges");
MochiKit.Base.methodcaller('values'), MochiKit.Base.methodcaller('values'),
Clipperz.Base.serializeJSON, Clipperz.Base.serializeJSON,
MochiKit.Base.bind(function () { this._fields[newField.reference()] = newField; }, this), // MochiKit.Base.bind(function () { this._fields[newField.reference()] = newField; }, this),
MochiKit.Base.method(newField, 'setLabel', someParameters['label']), MochiKit.Base.method(newField, 'setLabel', someParameters['label']),
MochiKit.Base.method(newField, 'setValue', someParameters['value']), MochiKit.Base.method(newField, 'setValue', someParameters['value']),
// MochiKit.Base.method(newField, 'setIsHidden', someParameters['isHidden']),
MochiKit.Base.method(newField, 'setIsHidden', someParameters['hidden']), MochiKit.Base.method(newField, 'setIsHidden', someParameters['hidden']),
MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.method(this, '_getObjectDataStore'),
@@ -201,39 +205,12 @@ console.log("Record.Version.hasPendingChanges");
'removeField': function (aField) { 'removeField': function (aField) {
return Clipperz.Async.callbacks("Record.Version.removeField", [ return Clipperz.Async.callbacks("Record.Version.removeField", [
MochiKit.Base.method(this, 'fields'), MochiKit.Base.method(this, 'fields'),
MochiKit.Base.bind(function () { delete this._fields[aField.reference()]; }, this), // MochiKit.Base.bind(function () { delete this._fields[aField.reference()]; }, this),
MochiKit.Base.method(this, 'removeValue', 'fields' + '.' + aField.reference()) MochiKit.Base.method(this, 'removeValue', 'fields' + '.' + aField.reference())
], {trace:false}); ], {trace:false});
}, },
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/*
'sortFieldReference': function (someSortedFieldReferences) {
},
*/
//=========================================================================
/*
'directLogins': function () {
return MochiKit.Base.values(this._directLogins);
},
'addDirectLogin': function (aDirectLogin) {
this._directLogins[aDirectLogin.reference()] = aDirectLogin;
},
*/
//=========================================================================
/*
'updateValues': function (anotherVersion) {
return Clipperz.Async.callbacks("Record.Version.updateValue", [
MochiKit.Base.partial(MochiKit.Async.succeed, this)
], {trace:false});
},
*/
//=========================================================================
'setRemoteData': function (aValue) { 'setRemoteData': function (aValue) {
this._remoteData = aValue; this._remoteData = aValue;
@@ -241,7 +218,7 @@ console.log("Record.Version.hasPendingChanges");
return aValue; return aValue;
}, },
//========================================================================= //-------------------------------------------------------------------------
'getVersionFunction': function () { 'getVersionFunction': function () {
return this._getVersionFunction; return this._getVersionFunction;
@@ -276,9 +253,10 @@ console.log("Record.Version.hasPendingChanges");
//========================================================================= //=========================================================================
'revertChanges': function () { 'revertChanges': function () {
//console.log("Record.Version.revertChanges", this.reference(), this.transientState()['originalReference']);
this.setReference(this.transientState()['originalReference']); this.setReference(this.transientState()['originalReference']);
Clipperz.PM.DataModel.Record.Version.superclass.revertChanges.apply(this, arguments); Clipperz.PM.DataModel.Record.Version.superclass.revertChanges.apply(this, arguments);
this._fields = null; // this._fields = null;
}, },
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -313,15 +291,15 @@ console.log("Record.Version.hasPendingChanges");
}, },
//========================================================================= //=========================================================================
/*
'deleteAllCleanTextData': function () { 'deleteAllCleanTextData': function () {
this._fields = null; // this._fields = null;
return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments); return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments);
}, },
'hasAnyCleanTextData': function () { 'hasAnyCleanTextData': function () {
// return Clipperz.PM.DataModel.Record.Version.superclass.hasAnyCleanTextData.apply(this, arguments); return Clipperz.PM.DataModel.Record.Version.superclass.hasAnyCleanTextData.apply(this, arguments);
/ *
var deferredResult; var deferredResult;
deferredResult = new Clipperz.Async.Deferred("Record.Version.hasAnyCleanTextData", {trace:false}); deferredResult = new Clipperz.Async.Deferred("Record.Version.hasAnyCleanTextData", {trace:false});
@@ -335,8 +313,9 @@ console.log("Record.Version.hasPendingChanges");
deferredResult.callback(); deferredResult.callback();
return deferredResult; return deferredResult;
* /
}, },
*/
//========================================================================= //=========================================================================
__syntaxFix__: "syntax fix" __syntaxFix__: "syntax fix"
}); });
@@ -77,9 +77,9 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
'reference': function () { // 'reference': function () {
return this._reference; // return this._reference;
}, // },
//========================================================================= //=========================================================================
@@ -171,6 +171,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
return new RegExp('^\\s+|\\s+$', 'g'); return new RegExp('^\\s+|\\s+$', 'g');
}, },
// 'tagCleanupRegExp': function () {
// return new RegExp('\\' + Clipperz.PM.DataModel.Record.tagSpace, 'g');
// },
//............................................................................ //............................................................................
'filterOutTags': function (aValue) { 'filterOutTags': function (aValue) {
@@ -232,10 +236,12 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
}, },
'addTag': function (aNewTag) { 'addTag': function (aNewTag) {
// var tag = aNewTag.replace(/\s/g, Clipperz.PM.DataModel.Record.tagSpace);
//console.log("TAG", aNewTag, tag);
return Clipperz.Async.callbacks("Record.addTag", [ return Clipperz.Async.callbacks("Record.addTag", [
MochiKit.Base.method(this, 'fullLabel'), MochiKit.Base.method(this, 'fullLabel'),
MochiKit.Base.method(this, 'extractTagsFromFullLabel'), MochiKit.Base.method(this, 'extractTagsFromFullLabel'),
function (someTags) { someTags[aNewTag] = true; /* console.log("UPDATED TAGS", someTags); */ return someTags; }, function (someTags) { someTags[aNewTag] = true; return someTags; },
MochiKit.Base.method(this, 'updateTags') MochiKit.Base.method(this, 'updateTags')
], {trace:false}); ], {trace:false});
}, },
@@ -631,12 +637,18 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
var deferredResult; var deferredResult;
var transientStateKey; var transientStateKey;
if (typeof(aVersionReference) == 'undefined') {
console.log("ERROR; getVersionKey aVersionReference is undefined");
}
transientStateKey = 'versionKeys' + '.' + aVersionReference; transientStateKey = 'versionKeys' + '.' + aVersionReference;
if (this.transientState().getValue(transientStateKey) != null) { if (this.transientState().getValue(transientStateKey) != null) {
deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey)); deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey));
} else { } else {
deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [ deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [
//MochiKit.Base.bind(function () {console.log("VERSION REFERENCE", aVersionReference, this.currentVersionReference()); }, this),
MochiKit.Base.method(this, 'getVersions'), MochiKit.Base.method(this, 'getVersions'),
//function (aValue) { console.log("VERSIONs", aValue); return aValue; },
MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()), MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()),
Clipperz.Async.deferredIf("getVersionKey for current version", [ Clipperz.Async.deferredIf("getVersionKey for current version", [
MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), MochiKit.Base.method(this, 'getCurrentRecordVersionKey'),
@@ -758,7 +770,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) { 'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) {
return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [ return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [
MochiKit.Base.method(this, 'getCurrentRecordVersion'), MochiKit.Base.method(this, 'getCurrentRecordVersion'),
MochiKit.Base.methodcaller(aMethodName, someValues) MochiKit.Base.methodcaller(aMethodName, someValues),
], {trace:false}); ], {trace:false});
}, },
@@ -833,26 +845,18 @@ deferredResult.addCallback(function (aValue) { console.log("Record.hasPendingCha
'hasPendingChanges': function () { 'hasPendingChanges': function () {
var deferredResult; var deferredResult;
// var recordReference = this.reference(); var recordReference = this.reference();
var self = this; // var self = this;
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false}); deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false});
deferredResult.collectResults({ deferredResult.collectResults({
'super': [ 'super': [
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this), MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this),
// MochiKit.Base.method(this, 'hasInitiatedObjectDataStore'),
// Clipperz.Async.deferredIf("Record.hasPendingChanges - hasInitiatedObjectDataStore", [
// MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this),
// ], [
// MochiKit.Base.partial(MochiKit.Async.succeed, false),
// ]),
], ],
'currentVersion': [ 'currentVersion': [
// MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges')
MochiKit.Base.method(this, 'hasInitiatedObjectDataStore'), MochiKit.Base.method(this, 'hasInitiatedObjectDataStore'),
Clipperz.Async.deferredIf("Record.hasPendingChanges - hasInitiatedObjectDataStore", [ Clipperz.Async.deferredIf("Record.hasPendingChanges - hasInitiatedObjectDataStore", [
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges'),
], [ ], [
MochiKit.Base.partial(MochiKit.Async.succeed, false), MochiKit.Base.partial(MochiKit.Async.succeed, false),
]), ]),
@@ -939,39 +943,47 @@ console.log("Record.hasPendingChanges RESULT", result);
'revertChanges': function () { 'revertChanges': function () {
var deferredResult; var deferredResult;
var recordReference = this.reference(); // var recordReference = this.reference();
if (this.isBrandNew() == false) { if (this.isBrandNew() == false) {
/* /* */
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false}); deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false});
deferredResult.addMethod(this, 'hasPendingChanges'); deferredResult.addMethod(this, 'hasPendingChanges');
deferredResult.addCallback(function (aValue) { //deferredResult.addCallback(function (aValue) {
if (recordReference == 'd620764a656bfd4e1d3758500d5db72e460a0cf729d56ed1a7755b5725c50045') { // if (recordReference == 'd620764a656bfd4e1d3758500d5db72e460a0cf729d56ed1a7755b5725c50045') {
console.log("Record.revertChanges - hasPendingChanges", aValue); // console.log("Record.revertChanges - hasPendingChanges", aValue);
} // }
// return aValue; // return aValue;
return true; // return true;
}); //});
deferredResult.addIf([ deferredResult.addIf([
//function (aValue) { console.log("Record.revertChanges - 1"); return aValue; },
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'), MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
MochiKit.Base.method(this, 'directLogins'), //function (aValue) { console.log("Record.revertChanges - 2"); return aValue; },
MochiKit.Base.values,
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')),
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this) MochiKit.Base.method(this, 'directLogins'),
//function (aValue) { console.log("Record.revertChanges - 3"); return aValue; },
MochiKit.Base.values,
//function (aValue) { console.log("Record.revertChanges - 4"); return aValue; },
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')),
//function (aValue) { console.log("Record.revertChanges - 5"); return aValue; },
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this),
//function (aValue) { console.log("Record.revertChanges - 6"); return aValue; },
], [ ], [
MochiKit.Async.succeed MochiKit.Async.succeed
]); ]);
deferredResult.callback(); deferredResult.callback();
*/ /* * /
deferredResult = Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.revertChanges", [ deferredResult = Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.revertChanges", [
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.method(this, 'directLogins'),
MochiKit.Base.values, MochiKit.Base.values,
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')), MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')),
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this) MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this),
], {trace:false}); ], {trace:false});
/ * */
} else { } else {
// this.deleteAllCleanTextData(); // this.deleteAllCleanTextData();
deferredResult = MochiKit.Async.succeed(); deferredResult = MochiKit.Async.succeed();
@@ -1115,7 +1127,7 @@ deferredResult.addCallback(function (aValue) {
}, },
//function (aValue) { console.log("Sorted Keys", aValue); return aValue; }, //function (aValue) { console.log("Sorted Keys", aValue); return aValue; },
MochiKit.Base.partial(MochiKit.Base.map, function (aReference) { return currentFieldValues[aReference]; }), MochiKit.Base.partial(MochiKit.Base.map, function (aReference) { return currentFieldValues[aReference]; }),
function (aValue) { console.log("Sorted Field values", aValue); return aValue; }, //function (aValue) { console.log("Sorted Field values", aValue); return aValue; },
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addField')), MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addField')),
Clipperz.Async.collectAll, Clipperz.Async.collectAll,
], [ ], [
@@ -1147,7 +1159,7 @@ function (aValue) { console.log("Sorted Field values", aValue); return aValue; }
Clipperz.Async.collectAll, Clipperz.Async.collectAll,
MochiKit.Base.method(aRecord, 'directLogins'), MochiKit.Base.values, MochiKit.Base.method(aRecord, 'directLogins'), MochiKit.Base.values,
function (aValue) { console.log("-> DirectLogin Values", aValue); return aValue; }, //function (aValue) { console.log("-> DirectLogin Values", aValue); return aValue; },
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addDirectLogin')), MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addDirectLogin')),
//function (aValue) { console.log("-> DirectLogin Values", aValue); return aValue; }, //function (aValue) { console.log("-> DirectLogin Values", aValue); return aValue; },
// Clipperz.Async.collectAll, // Clipperz.Async.collectAll,
@@ -1175,8 +1187,9 @@ Clipperz.PM.DataModel.Record.defaultSearchField = '_searchableContent';
Clipperz.PM.DataModel.Record.tagChar = '\uE009'; Clipperz.PM.DataModel.Record.tagChar = '\uE009';
Clipperz.PM.DataModel.Record.specialTagChar = '\uE010'; Clipperz.PM.DataModel.Record.specialTagChar = '\uE010';
//Clipperz.PM.DataModel.Record.tagSpace = '\uE011';
Clipperz.PM.DataModel.Record.specialTagsConstructor = function (aTag) { Clipperz.PM.DataModel.Record.specialTagsConstructor = function (aTag) {
return Clipperz.PM.DataModel.Record.specialTagChar + aTag; return Clipperz.PM.DataModel.Record.specialTagChar + aTag; //.replace(/\s/g, Clipperz.PM.DataModel.Record.tagSpace);
} }
Clipperz.PM.DataModel.Record.archivedTag = Clipperz.PM.DataModel.Record.specialTagsConstructor('ARCH'); Clipperz.PM.DataModel.Record.archivedTag = Clipperz.PM.DataModel.Record.specialTagsConstructor('ARCH');
Clipperz.PM.DataModel.Record.regExpForTag = function (aTag) { Clipperz.PM.DataModel.Record.regExpForTag = function (aTag) {
@@ -227,7 +227,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
this._records[reference] = record; this._records[reference] = record;
} else { } else {
Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference])); Clipperz.log("SKIPPING record " + reference + " as there are no stats associated - " + Clipperz.Base.serializeJSON(someData['records'][reference]));
} }
} }
+11 -12
View File
@@ -547,11 +547,12 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
], {trace:false}); ], {trace:false});
}, },
'getRecordsInfo': function (someInfo, shouldIncludeArchivedCards) { 'getRecordsInfo': function (someInfo /*, shouldIncludeArchivedCards */) {
return Clipperz.Async.callbacks("User.getRecordsInfo", [ return Clipperz.Async.callbacks("User.getRecordsInfo", [
MochiKit.Base.method(this, 'getRecords'), MochiKit.Base.method(this, 'getRecords'),
MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", someInfo, {trace:false})), MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", someInfo, {trace:false})),
Clipperz.Async.collectAll, Clipperz.Async.collectAll,
/*
function (aResult) { function (aResult) {
var result; var result;
@@ -563,7 +564,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
return result; return result;
} }
*/
], {trace:false}); ], {trace:false});
}, },
@@ -665,21 +666,15 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
var user = this; var user = this;
return Clipperz.Async.callbacks("User.cloneRecord", [ return Clipperz.Async.callbacks("User.cloneRecord", [
// MochiKit.Base.method(this, 'createNewRecord'),
// MochiKit.Base.methodcaller('setUpWithRecord', aRecord),
// function (aValue) { result = aValue; return aValue; },
// MochiKit.Base.method(this, 'saveChanges'),
// function () { return result; }
MochiKit.Base.method(this, 'hasPendingChanges'), MochiKit.Base.method(this, 'hasPendingChanges'),
Clipperz.Async.deferredIf("User has pending changes", [ Clipperz.Async.deferredIf("User has pending changes", [
MochiKit.Async.fail MochiKit.Async.fail
], [ ], [
MochiKit.Base.method(user, 'createNewRecord'), MochiKit.Base.method(user, 'createNewRecord'),
MochiKit.Base.methodcaller('setUpWithRecord', aRecord), MochiKit.Base.methodcaller('setUpWithRecord', aRecord),
function (aValue) { result = aValue; return aValue; }, // function (aValue) { result = aValue; return aValue; },
MochiKit.Base.method(user, 'saveChanges'), // MochiKit.Base.method(user, 'saveChanges'),
function () { return result; } // function () { return result; }
]) ])
], {trace:false}); ], {trace:false});
}, },
@@ -781,9 +776,13 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
'revertChanges': function () { 'revertChanges': function () {
return Clipperz.Async.callbacks("User.revertChanges", [ return Clipperz.Async.callbacks("User.revertChanges", [
//function (aValue) { console.log("User.revertChanges - 1"); return aValue; },
MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'), MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'),
//function (aValue) { console.log("User.revertChanges - 2"); return aValue; },
MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'), MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'),
MochiKit.Base.method(this, 'resetTransientState', false) //function (aValue) { console.log("User.revertChanges - 3"); return aValue; },
MochiKit.Base.method(this, 'resetTransientState', false),
//function (aValue) { console.log("User.revertChanges - 4"); return aValue; },
], {trace:false}); ], {trace:false});
}, },
@@ -21,6 +21,7 @@ refer to http://www.clipperz.com.
*/ */
"use strict";
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels'); Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({
@@ -30,6 +31,10 @@ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel'); MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel');
}, },
handleDownloadOfflineCopyLink: function (anEvent) {
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'downloadOfflineCopy');
},
//========================================================================= //=========================================================================
render: function () { render: function () {
@@ -45,33 +50,39 @@ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({
Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler}) Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler})
]) ])
]), ]),
React.DOM.h2({}, "Extra features")
React.DOM.div({}, [
React.DOM.ul({}, [
React.DOM.li({}, [
React.DOM.h1({}, "Account"),
]),
React.DOM.li({}, [
React.DOM.h1({}, "Data"),
React.DOM.ul({}, [
React.DOM.li({}, [
React.DOM.h2({}, "Offline copy"),
React.DOM.div({}, [
React.DOM.p({}, "With just one click you can dump all your encrypted data from Clipperz servers to your hard disk and create a read-only offline version of Clipperz to be used when you are not connected to the Internet."),
React.DOM.a({'onClick':this.handleDownloadOfflineCopyLink}, "Download")
])
]),
React.DOM.li({}, [
React.DOM.h2({}, "Sharing"),
]),
React.DOM.li({}, [
React.DOM.h2({}, "Import"),
]),
React.DOM.li({}, [
React.DOM.h2({}, "Export"),
])
])
]),
React.DOM.li({}, [
React.DOM.h1({}, "Tools"),
])
])
])
]); ]);
/*
<div id="extraFeaturesPanel" class="panel extraFeatures">
<div class="warnings">
<ul>
<li>Synchronize local data</li>
</ul>
</div>
<ul>
<li>Account</li>
<li>Subscription</li>
</ul>
<ul>
<li>Local Data</li>
<li>OTP</li>
</ul>
<div class="donation">
<a>Make a donation</a>
</div>
</div>
*/
} }
//========================================================================= //=========================================================================
@@ -60,7 +60,7 @@ Clipperz.PM.UI.Components.Selections = React.createClass({
var filterType; var filterType;
var filterValue; var filterValue;
console.log("SELECTIONS PROPS", this.props); //console.log("SELECTIONS PROPS", this.props);
tagInfo = this.props['tags'] ? this.props['tags'] : {}; tagInfo = this.props['tags'] ? this.props['tags'] : {};
tags = MochiKit.Base.filter(Clipperz.PM.DataModel.Record.isRegularTag, MochiKit.Base.keys(tagInfo)).sort(Clipperz.Base.caseInsensitiveCompare); tags = MochiKit.Base.filter(Clipperz.PM.DataModel.Record.isRegularTag, MochiKit.Base.keys(tagInfo)).sort(Clipperz.Base.caseInsensitiveCompare);
archivedCardsCount = this.props['archivedCardsCount']; archivedCardsCount = this.props['archivedCardsCount'];
@@ -73,6 +73,7 @@ Clipperz.PM.UI.MainController = function() {
'showArchivedCards', 'hideArchivedCards', 'showArchivedCards', 'hideArchivedCards',
'goBackToMainPage', 'goBackToMainPage',
'maskClick', 'maskClick',
'downloadOfflineCopy',
]); ]);
// MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChange_handler'); // MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChange_handler');
@@ -636,6 +637,7 @@ console.log("SET USER", aUser);
var deferredResult; var deferredResult;
deferredResult = new Clipperz.Async.Deferred('MainController.refreshUI', {trace:false}); deferredResult = new Clipperz.Async.Deferred('MainController.refreshUI', {trace:false});
deferredResult.addMethod(this, 'resetRecordsInfo'),
deferredResult.addMethod(this, 'refreshSelectedCards'); deferredResult.addMethod(this, 'refreshSelectedCards');
deferredResult.addMethod(this, 'renderTags'); deferredResult.addMethod(this, 'renderTags');
@@ -1034,9 +1036,12 @@ console.log("SET USER", aUser);
// }, // },
saveChanges: function () { saveChanges: function () {
// TODO: handle errors while savings
return Clipperz.Async.callbacks("MainController.saveChanges", [ return Clipperz.Async.callbacks("MainController.saveChanges", [
MochiKit.Base.method(this.overlay(), 'show', "saving …", true),
MochiKit.Base.method(this.user(), 'saveChanges'), MochiKit.Base.method(this.user(), 'saveChanges'),
MochiKit.Base.method(this, 'resetRecordsInfo'), // MochiKit.Base.method(this, 'resetRecordsInfo'),
MochiKit.Base.method(this.overlay(), 'done', "saved", 1),
], {trace:false}); ], {trace:false});
}, },
@@ -1046,11 +1051,11 @@ console.log("SET USER", aUser);
return Clipperz.Async.callbacks("MainController.saveCardEdits_handler", [ return Clipperz.Async.callbacks("MainController.saveCardEdits_handler", [
MochiKit.Base.method(currentPage, 'setProps', {'showGlobalMask':true}), MochiKit.Base.method(currentPage, 'setProps', {'showGlobalMask':true}),
MochiKit.Base.method(this.overlay(), 'show', "saving …", true), // MochiKit.Base.method(this.overlay(), 'show', "saving …", true),
MochiKit.Base.method(this, 'saveChanges'), MochiKit.Base.method(this, 'saveChanges'),
MochiKit.Base.method(currentPage, 'setProps', {'mode':'view', 'showGlobalMask':false}), MochiKit.Base.method(currentPage, 'setProps', {'mode':'view', 'showGlobalMask':false}),
MochiKit.Base.method(this, 'refreshUI', aRecordReference), MochiKit.Base.method(this, 'refreshUI', aRecordReference),
MochiKit.Base.method(this.overlay(), 'done', "saved", 1), // MochiKit.Base.method(this.overlay(), 'done', "saved", 1),
], {trace:false}); ], {trace:false});
}, },
@@ -1160,16 +1165,26 @@ console.log("SET USER", aUser);
}, },
cloneCard_handler: function (anEvent) { cloneCard_handler: function (anEvent) {
var cardInfo;
//console.log("CLONE CARD", anEvent['reference']); //console.log("CLONE CARD", anEvent['reference']);
return Clipperz.Async.callbacks("MainController.cloneCard_handler", [ return Clipperz.Async.callbacks("MainController.cloneCard_handler", [
MochiKit.Base.method(this.user(), 'getRecord', anEvent['reference']), MochiKit.Base.method(this.user(), 'getRecord', anEvent['reference']),
MochiKit.Base.method(this.user(), 'cloneRecord'), MochiKit.Base.method(this.user(), 'cloneRecord'),
MochiKit.Base.methodcaller('reference'), Clipperz.Async.collectResults("MainController.cloneCard_handler <card info>", {
'label': MochiKit.Base.methodcaller('label'),
'reference': MochiKit.Base.methodcaller('reference')
}, {trace:false}),
function (aValue) { cardInfo = aValue; return aValue; },
MochiKit.Base.method(this, 'saveChanges'),
function (aValue) {
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'cardSelected', cardInfo);
},
function (aValue) { return cardInfo['reference']; },
MochiKit.Base.method(this, 'refreshUI'), MochiKit.Base.method(this, 'refreshUI'),
// MochiKit.Base.bind(function () { ], {trace:true});
// this.pages()[this.currentPage()].setProps({'mode': 'edit'});
// }, this),
], {trace:false});
}, },
enterEditMode: function () { enterEditMode: function () {
@@ -1324,6 +1339,26 @@ console.log("SET USER", aUser);
}, },
//============================================================================ //============================================================================
'downloadOfflineCopy_handler': function (anEvent) {
var downloadHref;
var deferredResult;
var newWindow;
downloadHref = window.location.href.replace(/\/[^\/]*$/,'') + Clipperz_dumpUrl;
newWindow = window.open("", "");
deferredResult = new Clipperz.Async.Deferred("AppController.handleDownloadOfflineCopy", {trace:false});
deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'echo', {'echo':"echo"});
deferredResult.addCallback(function(aWindow) {
aWindow.location.href = downloadHref;
}, newWindow);
deferredResult.callback();
return deferredResult;
},
//============================================================================
/* /*
wrongAppVersion: function (anError) { wrongAppVersion: function (anError) {
// this.pages()['errorPage'].setProps({message:anError.message}); // this.pages()['errorPage'].setProps({message:anError.message});