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";
Clipperz.Base.module('Clipperz.PM.DataModel');
try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) {
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.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
@ -46,21 +46,19 @@ Clipperz.PM.DataModel.EncryptedRemoteObject = function(args) {
this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction || 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))) {
Clipperz.Base.exception.raise('MandatoryParameter');
}
this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter');
this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version'; //Clipperz.Base.exception.raise('MandatoryParameter');
this._encryptedDataKeypath = args.encryptedDataKeypath || 'data';
this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version';
this._transientState = null;
this._deferredLocks = {};
if (this._isBrandNew == true) {
this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [1]'}*/);
this._objectDataStore = new Clipperz.KeyValueObjectStore();
} else {
this._objectDataStore = null;
}
@ -111,7 +109,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'transientState': function () {
if (this._transientState == null) {
this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.transientState [2]'}*/);
this._transientState = new Clipperz.KeyValueObjectStore();
}
return this._transientState;
@ -166,6 +164,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
//-------------------------------------------------------------------------
'hasLoadedRemoteData': function () {
//console.log("EncryptedRemoteObject.hasLoadedRemoteData", this._remoteData);
return (this._remoteData != null);
},
@ -237,7 +236,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'decryptedDataStore': function () {
if (this._decryptedDataStore == null) {
this._decryptedDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.decryptedDataStore [3]'}*/);
this._decryptedDataStore = new Clipperz.KeyValueObjectStore();
};
return this._decryptedDataStore;
@ -343,7 +342,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
if (this._objectDataStore == null) {
//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.addMethod(this, 'getDecryptedData');
@ -434,7 +433,6 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'commitTransientState': function () {
var deferredResult;
// if (this.transientState().getValue('__prepareRemoteData') == true) {
if (this.transientState().getValue('packedRemoteData') != null) {
deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [
MochiKit.Base.bind(function (someData) {
@ -463,6 +461,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
//-------------------------------------------------------------------------
'revertChanges': function () {
//console.log("> EncryptedRemoveObject.revertChanges", this.toString(), this.hasInitiatedObjectDataStore());
if (this.hasInitiatedObjectDataStore()) {
this._objectDataStore.removeAllData();
this._objectDataStore = null;
@ -523,7 +522,6 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul
'prepareRemoteDataWithKey': function (aKey) {
return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [
// MochiKit.Base.method(this.transientState(), 'setValue', '__prepareRemoteData', true),
MochiKit.Base.method(this, '_getObjectDataStore'),
MochiKit.Base.methodcaller('values'),
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) {
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);
this._getVersionFunction = args.getVersion || Clipperz.Base.exception.raise('MandatoryParameter');
this._fields = null;
// this._fields = null;
return this;
}
@ -43,9 +46,9 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version, Clipperz.PM.DataModel
//-------------------------------------------------------------------------
'reference': function () {
return this._reference;
},
// 'reference': function () {
// return this._reference;
// },
//-------------------------------------------------------------------------
/*
@ -128,13 +131,13 @@ console.log("Record.Version.hasPendingChanges");
deferredResult.addCallback(MochiKit.Base.bind(function () {
var innerDeferredResult;
if (this._fields == null) {
// if (this._fields == null) {
innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false});
innerDeferredResult.addMethod(this, 'getValue', 'fields');
innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) {
var reference;
this._fields = {};
var result = {};
// this._fields = {};
for (reference in someObjectData) {
var recordVersionField;
@ -144,15 +147,17 @@ console.log("Record.Version.hasPendingChanges");
'reference': reference
});
this._fields[reference] = recordVersionField;
// this._fields[reference] = recordVersionField;
result[reference] = recordVersionField;
}
return this._fields;
// return this._fields;
return result;
}, this));
innerDeferredResult.callback();
} else {
innerDeferredResult = MochiKit.Async.succeed(this._fields);
}
// } else {
// innerDeferredResult = MochiKit.Async.succeed(this._fields);
// }
return innerDeferredResult;
}, this));
@ -182,10 +187,9 @@ console.log("Record.Version.hasPendingChanges");
MochiKit.Base.methodcaller('values'),
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, 'setValue', someParameters['value']),
// MochiKit.Base.method(newField, 'setIsHidden', someParameters['isHidden']),
MochiKit.Base.method(newField, 'setIsHidden', someParameters['hidden']),
MochiKit.Base.method(this, '_getObjectDataStore'),
@ -201,39 +205,12 @@ console.log("Record.Version.hasPendingChanges");
'removeField': function (aField) {
return Clipperz.Async.callbacks("Record.Version.removeField", [
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())
], {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) {
this._remoteData = aValue;
@ -241,7 +218,7 @@ console.log("Record.Version.hasPendingChanges");
return aValue;
},
//=========================================================================
//-------------------------------------------------------------------------
'getVersionFunction': function () {
return this._getVersionFunction;
@ -276,9 +253,10 @@ console.log("Record.Version.hasPendingChanges");
//=========================================================================
'revertChanges': function () {
//console.log("Record.Version.revertChanges", this.reference(), this.transientState()['originalReference']);
this.setReference(this.transientState()['originalReference']);
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 () {
this._fields = null;
// this._fields = null;
return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments);
},
'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;
deferredResult = new Clipperz.Async.Deferred("Record.Version.hasAnyCleanTextData", {trace:false});
@ -335,8 +313,9 @@ console.log("Record.Version.hasPendingChanges");
deferredResult.callback();
return deferredResult;
* /
},
*/
//=========================================================================
__syntaxFix__: "syntax fix"
});

View File

@ -77,9 +77,9 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
//-------------------------------------------------------------------------
'reference': function () {
return this._reference;
},
// 'reference': function () {
// return this._reference;
// },
//=========================================================================
@ -171,6 +171,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
return new RegExp('^\\s+|\\s+$', 'g');
},
// 'tagCleanupRegExp': function () {
// return new RegExp('\\' + Clipperz.PM.DataModel.Record.tagSpace, 'g');
// },
//............................................................................
'filterOutTags': function (aValue) {
@ -217,7 +221,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
match = tagRegEx.exec(aLabel);
while (match != null) {
result[match[1]] = true;
match = tagRegEx.exec(aLabel);
match = tagRegEx.exec(aLabel);
}
return result;
@ -232,10 +236,12 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
},
'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", [
MochiKit.Base.method(this, 'fullLabel'),
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')
], {trace:false});
},
@ -631,12 +637,18 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
var deferredResult;
var transientStateKey;
if (typeof(aVersionReference) == 'undefined') {
console.log("ERROR; getVersionKey aVersionReference is undefined");
}
transientStateKey = 'versionKeys' + '.' + aVersionReference;
if (this.transientState().getValue(transientStateKey) != null) {
deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey));
} else {
deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [
//MochiKit.Base.bind(function () {console.log("VERSION REFERENCE", aVersionReference, this.currentVersionReference()); }, this),
MochiKit.Base.method(this, 'getVersions'),
//function (aValue) { console.log("VERSIONs", aValue); return aValue; },
MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()),
Clipperz.Async.deferredIf("getVersionKey for current version", [
MochiKit.Base.method(this, 'getCurrentRecordVersionKey'),
@ -758,7 +770,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) {
return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [
MochiKit.Base.method(this, 'getCurrentRecordVersion'),
MochiKit.Base.methodcaller(aMethodName, someValues)
MochiKit.Base.methodcaller(aMethodName, someValues),
], {trace:false});
},
@ -833,26 +845,18 @@ deferredResult.addCallback(function (aValue) { console.log("Record.hasPendingCha
'hasPendingChanges': function () {
var deferredResult;
// var recordReference = this.reference();
var self = this;
var recordReference = this.reference();
// var self = this;
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false});
deferredResult.collectResults({
'super': [
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': [
// MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges')
MochiKit.Base.method(this, '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),
]),
@ -939,39 +943,47 @@ console.log("Record.hasPendingChanges RESULT", result);
'revertChanges': function () {
var deferredResult;
var recordReference = this.reference();
// var recordReference = this.reference();
if (this.isBrandNew() == false) {
/*
/* */
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false});
deferredResult.addMethod(this, 'hasPendingChanges');
deferredResult.addCallback(function (aValue) {
if (recordReference == 'd620764a656bfd4e1d3758500d5db72e460a0cf729d56ed1a7755b5725c50045') {
console.log("Record.revertChanges - hasPendingChanges", aValue);
}
//deferredResult.addCallback(function (aValue) {
// if (recordReference == 'd620764a656bfd4e1d3758500d5db72e460a0cf729d56ed1a7755b5725c50045') {
// console.log("Record.revertChanges - hasPendingChanges", aValue);
// }
// return aValue;
return true;
});
// return true;
//});
deferredResult.addIf([
//function (aValue) { console.log("Record.revertChanges - 1"); return aValue; },
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
MochiKit.Base.method(this, 'directLogins'),
MochiKit.Base.values,
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')),
//function (aValue) { console.log("Record.revertChanges - 2"); return aValue; },
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
]);
deferredResult.callback();
*/
/* * /
deferredResult = Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.revertChanges", [
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
MochiKit.Base.method(this, 'directLogins'),
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, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this),
], {trace:false});
/ * */
} else {
// this.deleteAllCleanTextData();
deferredResult = MochiKit.Async.succeed();
@ -1115,7 +1127,7 @@ deferredResult.addCallback(function (aValue) {
},
//function (aValue) { console.log("Sorted Keys", aValue); return aValue; },
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')),
Clipperz.Async.collectAll,
], [
@ -1147,7 +1159,7 @@ function (aValue) { console.log("Sorted Field values", aValue); return aValue; }
Clipperz.Async.collectAll,
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')),
//function (aValue) { console.log("-> DirectLogin Values", aValue); return aValue; },
// Clipperz.Async.collectAll,
@ -1173,10 +1185,11 @@ Clipperz.PM.DataModel.Record.defaultCardInfo = {
};
Clipperz.PM.DataModel.Record.defaultSearchField = '_searchableContent';
Clipperz.PM.DataModel.Record.tagChar = '\uE009';
Clipperz.PM.DataModel.Record.specialTagChar = '\uE010';
Clipperz.PM.DataModel.Record.tagChar = '\uE009';
Clipperz.PM.DataModel.Record.specialTagChar = '\uE010';
//Clipperz.PM.DataModel.Record.tagSpace = '\uE011';
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.regExpForTag = function (aTag) {

View File

@ -227,7 +227,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
this._records[reference] = record;
} 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});
},
'getRecordsInfo': function (someInfo, shouldIncludeArchivedCards) {
'getRecordsInfo': function (someInfo /*, shouldIncludeArchivedCards */) {
return Clipperz.Async.callbacks("User.getRecordsInfo", [
MochiKit.Base.method(this, 'getRecords'),
MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", someInfo, {trace:false})),
Clipperz.Async.collectAll,
/*
function (aResult) {
var result;
@ -563,7 +564,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
return result;
}
*/
], {trace:false});
},
@ -665,21 +666,15 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
var user = this;
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'),
Clipperz.Async.deferredIf("User has pending changes", [
MochiKit.Async.fail
], [
MochiKit.Base.method(user, 'createNewRecord'),
MochiKit.Base.methodcaller('setUpWithRecord', aRecord),
function (aValue) { result = aValue; return aValue; },
MochiKit.Base.method(user, 'saveChanges'),
function () { return result; }
// function (aValue) { result = aValue; return aValue; },
// MochiKit.Base.method(user, 'saveChanges'),
// function () { return result; }
])
], {trace:false});
},
@ -781,9 +776,13 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
'revertChanges': function () {
return Clipperz.Async.callbacks("User.revertChanges", [
//function (aValue) { console.log("User.revertChanges - 1"); return aValue; },
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, '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});
},

View File

@ -21,6 +21,7 @@ refer to http://www.clipperz.com.
*/
"use strict";
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
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');
},
handleDownloadOfflineCopyLink: function (anEvent) {
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'downloadOfflineCopy');
},
//=========================================================================
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})
])
]),
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 filterValue;
console.log("SELECTIONS PROPS", this.props);
//console.log("SELECTIONS PROPS", this.props);
tagInfo = this.props['tags'] ? this.props['tags'] : {};
tags = MochiKit.Base.filter(Clipperz.PM.DataModel.Record.isRegularTag, MochiKit.Base.keys(tagInfo)).sort(Clipperz.Base.caseInsensitiveCompare);
archivedCardsCount = this.props['archivedCardsCount'];

View File

@ -73,6 +73,7 @@ Clipperz.PM.UI.MainController = function() {
'showArchivedCards', 'hideArchivedCards',
'goBackToMainPage',
'maskClick',
'downloadOfflineCopy',
]);
// MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChange_handler');
@ -636,6 +637,7 @@ console.log("SET USER", aUser);
var deferredResult;
deferredResult = new Clipperz.Async.Deferred('MainController.refreshUI', {trace:false});
deferredResult.addMethod(this, 'resetRecordsInfo'),
deferredResult.addMethod(this, 'refreshSelectedCards');
deferredResult.addMethod(this, 'renderTags');
@ -1034,9 +1036,12 @@ console.log("SET USER", aUser);
// },
saveChanges: function () {
// TODO: handle errors while savings
return Clipperz.Async.callbacks("MainController.saveChanges", [
MochiKit.Base.method(this.overlay(), 'show', "saving …", true),
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});
},
@ -1046,11 +1051,11 @@ console.log("SET USER", aUser);
return Clipperz.Async.callbacks("MainController.saveCardEdits_handler", [
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(currentPage, 'setProps', {'mode':'view', 'showGlobalMask':false}),
MochiKit.Base.method(this, 'refreshUI', aRecordReference),
MochiKit.Base.method(this.overlay(), 'done', "saved", 1),
// MochiKit.Base.method(this.overlay(), 'done', "saved", 1),
], {trace:false});
},
@ -1160,16 +1165,26 @@ console.log("SET USER", aUser);
},
cloneCard_handler: function (anEvent) {
var cardInfo;
//console.log("CLONE CARD", anEvent['reference']);
return Clipperz.Async.callbacks("MainController.cloneCard_handler", [
MochiKit.Base.method(this.user(), 'getRecord', anEvent['reference']),
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.bind(function () {
// this.pages()[this.currentPage()].setProps({'mode': 'edit'});
// }, this),
], {trace:false});
], {trace:true});
},
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) {
// this.pages()['errorPage'].setProps({message:anError.message});