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

View File

@ -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._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version';
this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter');
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'),

View File

@ -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"
}); });

View File

@ -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) {
@ -217,7 +221,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
match = tagRegEx.exec(aLabel); match = tagRegEx.exec(aLabel);
while (match != null) { while (match != null) {
result[match[1]] = true; result[match[1]] = true;
match = tagRegEx.exec(aLabel); match = tagRegEx.exec(aLabel);
} }
return result; return result;
@ -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'),
//function (aValue) { console.log("Record.revertChanges - 2"); return aValue; },
MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.method(this, 'directLogins'),
//function (aValue) { console.log("Record.revertChanges - 3"); return aValue; },
MochiKit.Base.values, MochiKit.Base.values,
//function (aValue) { console.log("Record.revertChanges - 4"); return aValue; },
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')), 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) 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,
@ -1173,10 +1185,11 @@ Clipperz.PM.DataModel.Record.defaultCardInfo = {
}; };
Clipperz.PM.DataModel.Record.defaultSearchField = '_searchableContent'; 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) {

View File

@ -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]));
} }
} }

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});
}, },

View File

@ -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>
*/
} }
//========================================================================= //=========================================================================

View File

@ -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'];

View File

@ -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 () {
@ -1322,7 +1337,27 @@ console.log("SET USER", aUser);
hasKeyboard: function () { hasKeyboard: function () {
return this._hasKeyboard; return this._hasKeyboard;
}, },
//============================================================================
'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) {