summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz/PM
authorGiulio Cesare Solaroli <giulio.cesare@clipperz.com>2013-10-02 07:59:30 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@clipperz.com>2013-10-02 07:59:30 (UTC)
commit1180b7b195157aaeb4f0d5380e0c886bbd06c2e2 (patch) (unidiff)
tree709e33a09d9325d382aabaf0a0828e20ebdb96db /frontend/delta/js/Clipperz/PM
parent20bea94ab6b91c85b171dcf86baba0a64169d508 (diff)
downloadclipperz-1180b7b195157aaeb4f0d5380e0c886bbd06c2e2.zip
clipperz-1180b7b195157aaeb4f0d5380e0c886bbd06c2e2.tar.gz
clipperz-1180b7b195157aaeb4f0d5380e0c886bbd06c2e2.tar.bz2
Updated /delta
Switched from less to scss. Still no build script to update the final CSS, though. Added preliminary support for storing account data on browser's local storage for offline viewing. No public backend currently support this feature.
Diffstat (limited to 'frontend/delta/js/Clipperz/PM') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/DevicePreferences.js90
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy.js1
-rwxr-xr-xfrontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js4
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js4
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js85
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/CardList.js13
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/Checkbox.js44
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js6
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js7
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/Components/PreferencePage.js88
-rw-r--r--frontend/delta/js/Clipperz/PM/UI/MainController.js130
11 files changed, 425 insertions, 47 deletions
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DevicePreferences.js b/frontend/delta/js/Clipperz/PM/DataModel/DevicePreferences.js
new file mode 100644
index 0000000..ff3b33f
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/DevicePreferences.js
@@ -0,0 +1,90 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.DataModel.DevicePreferences = function (args) {
25 args = args || {};
26
27 this._data = null;
28
29 Clipperz.PM.DataModel.DevicePreferences.superclass.constructor.apply(this, arguments);
30
31 return this;
32}
33
34Clipperz.Base.extend(Clipperz.PM.DataModel.DevicePreferences, Object, {
35
36 toString: function () {
37 return "Clipperz.PM.DataModel.DevicePreferences";
38 },
39
40 //-------------------------------------------------------------------------
41
42 shouldStoreDataLocally: function () {
43 return (localStorage.getItem('shouldStoreDataLocally') === 'true');
44 },
45
46 setShouldStoreDataLocally: function (aValue) {
47 localStorage.setItem('shouldStoreDataLocally', aValue);
48 },
49
50 //-------------------------------------------------------------------------
51
52 setAccountDataWityResponse: function (aResponse) {
53 localStorage.setItem('clipperz_dump_data', aResponse['data']);
54 localStorage.setItem('clipperz_dump_version',aResponse['version']);
55 localStorage.setItem('clipperz_dump_date', new Date());
56
57 this._data = null;
58 },
59
60 accountData: function () {
61 if (this._data == null) {
62 vardata;
63
64 data = localStorage.getItem('clipperz_dump_data');
65 if (data != null) {
66 this._data = JSON.parse(data);
67 }
68 }
69
70 return this._data;
71 },
72
73 latestDownload: function () {
74 varresult;
75 vardate;
76
77 date = localStorage.getItem('clipperz_dump_date');
78 if (date != null) {
79 result = new Date(date);
80 } else {
81 result = null;
82 }
83
84 return result;
85 },
86
87 //=========================================================================
88 __syntaxFix__: "syntax fix"
89});
90
diff --git a/frontend/delta/js/Clipperz/PM/Proxy.js b/frontend/delta/js/Clipperz/PM/Proxy.js
index 2ac684a..71c784f 100644
--- a/frontend/delta/js/Clipperz/PM/Proxy.js
+++ b/frontend/delta/js/Clipperz/PM/Proxy.js
@@ -149,12 +149,13 @@ Clipperz.PM.Proxy.prototype = MochiKit.Base.update(null, {
149 throw Clipperz.Base.exception.AbstractMethod; 149 throw Clipperz.Base.exception.AbstractMethod;
150 }, 150 },
151 151
152 'sendMessage': function (aFunctionName, someParameters) { 152 'sendMessage': function (aFunctionName, someParameters) {
153 var deferredResult; 153 var deferredResult;
154 154
155console.log("PROXY.sendMessage", aFunctionName, someParameters);
155 //TODO: read actual application version for a property set at build time 156 //TODO: read actual application version for a property set at build time
156 deferredResult = new Clipperz.Async.Deferred("Proxy.sendMessage", {trace:false}); 157 deferredResult = new Clipperz.Async.Deferred("Proxy.sendMessage", {trace:false});
157 deferredResult.addMethod(this, '_sendMessage', aFunctionName, 'fake-app-version'); 158 deferredResult.addMethod(this, '_sendMessage', aFunctionName, 'fake-app-version');
158 deferredResult.addErrback(MochiKit.Base.method(this, 'handleError')); 159 deferredResult.addErrback(MochiKit.Base.method(this, 'handleError'));
159 deferredResult.callback(someParameters); 160 deferredResult.callback(someParameters);
160 161
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
index 1638d99..6deee3d 100755
--- a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
@@ -54,14 +54,14 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.JSON, Clipperz.PM.Proxy, {
54 54
55 parameters = { 55 parameters = {
56 method: aFunctionName, 56 method: aFunctionName,
57 version: aVersion, 57 version: aVersion,
58 parameters: Clipperz.Base.serializeJSON(someParameters) 58 parameters: Clipperz.Base.serializeJSON(someParameters)
59 }; 59 };
60 60console.log("PROXY.JSON._sendMessage", parameters);
61 deferredResult = new Clipperz.Async.Deferred("Proxy.JSON.sendMessage", {trace:false}); 61 deferredResult = new Clipperz.Async.Deferred("Proxy.JSON._sendMessage", {trace:false});
62 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestSent'); 62 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestSent');
63 deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), { 63 deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), {
64 method:'POST', 64 method:'POST',
65 sendContent:MochiKit.Base.queryString(parameters), 65 sendContent:MochiKit.Base.queryString(parameters),
66 headers:{"Content-Type":"application/x-www-form-urlencoded"} 66 headers:{"Content-Type":"application/x-www-form-urlencoded"}
67 }); 67 });
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
index a3c238c..3f16f70 100644
--- a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
@@ -27,13 +27,15 @@ try { if (typeof(Clipperz.PM.Proxy.Offline.DataStore) == 'undefined') { throw ""
27 27
28//============================================================================= 28//=============================================================================
29 29
30Clipperz.PM.Proxy.Offline.LocalStorageDataStore = function(args) { 30Clipperz.PM.Proxy.Offline.LocalStorageDataStore = function(args) {
31 args = args || {}; 31 args = args || {};
32 32
33 this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null); 33 //this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
34 this._data = JSON.parse(localStorage.getItem('clipperz_dump_data'));
35
34 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly); 36 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
35 this._shouldPayTolls = args.shouldPayTolls || false; 37 this._shouldPayTolls = args.shouldPayTolls || false;
36 38
37 this._tolls = {}; 39 this._tolls = {};
38 this._currentStaticConnection = null; 40 this._currentStaticConnection = null;
39 41
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js b/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
index df514a2..12ddce3 100644
--- a/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
@@ -34,20 +34,47 @@ Clipperz.PM.UI.Components.CardDetail = React.createClass({
34 }, 34 },
35 35
36 getInitialState: function () { 36 getInitialState: function () {
37 return { 37 return {
38 // showSearch: false, 38 // showSearch: false,
39 // searchTimer: null, 39 // searchTimer: null,
40 unmaskedFields: new Clipperz.Set(),
40 starred: false 41 starred: false
41 }; 42 };
42 }, 43 },
43 44
44 handleDirectLoginClick: function (aDirectLoginReference, anEvent) { 45 handleDirectLoginClick: function (aDirectLoginReference, anEvent) {
45 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference}); 46 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference});
46 }, 47 },
47 48
49 toggleFieldVisibility: function (aField, anEvent) {
50 var unmaskedFields;
51 var fieldReference;
52
53 unmaskedFields = this.state['unmaskedFields'];
54 fieldReference = aField['reference']
55 if (unmaskedFields.contains(fieldReference)) {
56 unmaskedFields.remove(fieldReference)
57 } else {
58 unmaskedFields.add(fieldReference)
59 }
60
61 this.setState({'unmaskedFields': unmaskedFields});
62 },
63
64 handleGoAction: function (aField, anEvent) {
65 var newWindow;
66
67 newWindow = MochiKit.DOM.currentWindow().open(aField['value'], '_blank');
68 newWindow.focus();
69 },
70
71 handleEmailAction: function (aField, anEvent) {
72 MochiKit.DOM.currentWindow().location = 'mailto:' + aField['value'];
73 },
74
48 //========================================================================= 75 //=========================================================================
49 76
50 normalizeFieldValue: function (aValue) { 77 normalizeFieldValue: function (aValue) {
51 varresult = []; 78 varresult = [];
52 varrows = aValue.split('\n'); 79 varrows = aValue.split('\n');
53 80
@@ -58,36 +85,62 @@ Clipperz.PM.UI.Components.CardDetail = React.createClass({
58 result.push(rows[i].replace(/[\s]/g, '\u00A0')); 85 result.push(rows[i].replace(/[\s]/g, '\u00A0'));
59 } 86 }
60 87
61 return result; 88 return result;
62 }, 89 },
63 90
64 renderField: function (aField) { 91 renderFieldActionButton: function (aField) {
65//console.log("FIELD", aField); 92 // varactionLabel;
66 varactionLabel; 93 var result;
67 94
68 if (aField['actionType'] == 'URL') { 95 if (aField['actionType'] == 'URL') {
69 actionLabel = "go"; 96 result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleGoAction', aField)}, [
97 React.DOM.a({className:aField['actionType']}, "go")
98 ]);
70 } else if (aField['actionType'] == 'PASSWORD') { 99 } else if (aField['actionType'] == 'PASSWORD') {
71 actionLabel = "locked"; 100 var icon;
101
102 if (this.state['unmaskedFields'].contains(aField['reference'])) {
103 icon = "unlocked";
104 } else {
105 icon = "locked";
106 }
107 result =React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'toggleFieldVisibility', aField)}, [
108 React.DOM.a({className:aField['actionType']}, icon)
109 ]);
72 } else if (aField['actionType'] == 'EMAIL') { 110 } else if (aField['actionType'] == 'EMAIL') {
73 actionLabel = "email"; 111 result =React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleEmailAction', aField)}, [
112 React.DOM.a({className:aField['actionType']}, "email")
113 ]);
74 } else { 114 } else {
75 actionLabel = ""; 115 result = null;
116 }
117
118 return result;
119 },
120
121 renderField: function (aField) {
122//console.log("FIELD", aField);
123 var fieldExtraClass;
124
125 fieldExtraClass = aField['actionType'];
126 if (this.state['unmaskedFields'].contains(aField['reference'])) {
127 fieldExtraClass = fieldExtraClass + ' unlocked';
76 } 128 }
77 129
78 returnReact.DOM.div({className:'listItem ' + aField['actionType']}, [ 130 returnReact.DOM.div({className:'listItem ' + fieldExtraClass, key:aField['reference']}, [
79 React.DOM.div({className:'fieldWrapper'}, [ 131 React.DOM.div({className:'fieldWrapper'}, [
80 React.DOM.div({className:'fieldInnerWrapper'}, [ 132 React.DOM.div({className:'fieldInnerWrapper'}, [
81 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])), 133 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])),
82 React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + aField['actionType']}, this.normalizeFieldValue(aField['value']))) 134 React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + fieldExtraClass}, this.normalizeFieldValue(aField['value'])))
83 ]) 135 ])
84 ]), 136 ]),
85 React.DOM.div({className:'actionWrapper'}, [ 137 this.renderFieldActionButton(aField)
86 React.DOM.div({className:aField['actionType']}, actionLabel) 138 // React.DOM.div({className:'actionWrapper'}, [
87 ]) 139 // React.DOM.div({className:aField['actionType']}, actionLabel)
140 // ])
88 ]); 141 ]);
89 }, 142 },
90 143
91 renderDirectLogin: function (aDirectLogin) { 144 renderDirectLogin: function (aDirectLogin) {
92//console.log("DIRECT LOGIN", aDirectLogin); 145//console.log("DIRECT LOGIN", aDirectLogin);
93 returnReact.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [ 146 returnReact.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [
@@ -95,35 +148,35 @@ Clipperz.PM.UI.Components.CardDetail = React.createClass({
95 React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})), 148 React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})),
96 React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go")) 149 React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go"))
97 ]); 150 ]);
98 }, 151 },
99 152
100 handleBackClick: function (anEvent) { 153 handleBackClick: function (anEvent) {
101 window.history.back(); 154 // window.history.back();
155 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
102 }, 156 },
103 157
104 handleStarClick: function (anEvent) { 158 handleStarClick: function (anEvent) {
105 this.setState({starred: !this.state['starred']}); 159 this.setState({starred: !this.state['starred']});
106 }, 160 },
107 161
108 //========================================================================= 162 //=========================================================================
109 163
110 render: function () { 164 render: function () {
111 var card = this.props.card; 165 var card = this.props.card;
112 var starredStatus = (this.state['starred'] ? "starred" : "unstarred"); 166 // var starredStatus = (this.state['starred'] ? "starred" : "unstarred");
113 167
114 if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) { 168 if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) {
115 card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] }) 169 card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] })
116 } 170 }
117 171
118 returnReact.DOM.div({className:'cardDetail'}, [ 172 returnReact.DOM.div({className:'cardDetail'}, [
119 React.DOM.div({className:'header'}, [ 173 React.DOM.div({className:'header'}, [
120 React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)), 174 React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)),
121 // React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title + ' ' + card.title + ' ' + card.title + ' ' + card.title)),
122 React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")), 175 React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
123 React.DOM.div({className:'starWrapper'}, React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus)) 176 // React.DOM.div({className:'starWrapper'}, React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus))
124 ]), 177 ]),
125 React.DOM.div({className:'content'}, [ 178 React.DOM.div({className:'content'}, [
126 card.fields ? React.DOM.div({className:'fields'}, MochiKit.Base.map(this.renderField, card.fields)) : null, 179 card.fields ? React.DOM.div({className:'fields'}, MochiKit.Base.map(this.renderField, card.fields)) : null,
127 card.directLogins ? React.DOM.div({className:'directLogins'}, MochiKit.Base.map(this.renderDirectLogin,card.directLogins)): null 180 card.directLogins ? React.DOM.div({className:'directLogins'}, MochiKit.Base.map(this.renderDirectLogin,card.directLogins)): null
128 ]), 181 ]),
129 React.DOM.div({className:'footer'}, [ 182 React.DOM.div({className:'footer'}, [
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js b/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
index 66d20f1..5a44a4a 100644
--- a/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
@@ -94,17 +94,24 @@ console.log("focusOnSearchField", this.refs['searchField']);
94 94
95 return result; 95 return result;
96 }, 96 },
97 97
98 //========================================================================= 98 //=========================================================================
99 99
100 showPreferences: function (anEvent) {
101 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showPreferences', anEvent);
102 },
103
104 //=========================================================================
105
100 cardItem: function (aRecordReference) { 106 cardItem: function (aRecordReference) {
101 varreference = aRecordReference['_reference']; 107 varreference = aRecordReference['_reference'];
102 varselectedCard = (reference == this.props.selectedCard); 108 varselectedCard = (reference == this.props.selectedCard);
103 109
104 returnReact.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [ 110 //TODO: verify if it is possible to put the onClick handler on the container 'div', instead of adding it to each 'div' item.
111 returnReact.DOM.div({className:'listItem', key:reference, onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [
105 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)), 112 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)),
106 // React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)), 113 // React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)),
107 React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')), 114 React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')),
108 React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail"))) 115 React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail")))
109 ]); 116 ]);
110 }, 117 },
@@ -143,15 +150,15 @@ console.log("focusOnSearchField", this.refs['searchField']);
143 150
144 render: function() { 151 render: function() {
145 returnReact.DOM.div(null, [ 152 returnReact.DOM.div(null, [
146 React.DOM.div({className:'header'}, [ 153 React.DOM.div({className:'header'}, [
147 React.DOM.a({className:'account'}, 'clipperz'), 154 React.DOM.a({className:'account'}, 'clipperz'),
148 React.DOM.div({className:'features'}, [ 155 React.DOM.div({className:'features'}, [
149 React.DOM.a({className:'addCard'}, 'add'), 156 // React.DOM.a({className:'addCard'}, 'add'),
150 React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'), 157 React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'),
151 React.DOM.a({className:'settings'}, 'settings') 158 React.DOM.a({className:'settings', onClick:this.showPreferences}, 'settings')
152 ]), 159 ]),
153 // this.searchBox() 160 // this.searchBox()
154 ]), 161 ]),
155 this.searchBox(), 162 this.searchBox(),
156 React.DOM.div({className:'content cardList'}, this.cardListItems()), 163 React.DOM.div({className:'content cardList'}, this.cardListItems()),
157 ]); 164 ]);
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/Checkbox.js b/frontend/delta/js/Clipperz/PM/UI/Components/Checkbox.js
new file mode 100644
index 0000000..9538063
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/Checkbox.js
@@ -0,0 +1,44 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.Checkbox = React.createClass({
25 //http://development.tobypitman.com/iphoneCheckboxes/iphoneCheckboxes2.html
26
27 propTypes: {
28 'checked': React.PropTypes.bool.isRequired,
29 'id': React.PropTypes.string.isRequired,
30 'eventHandler':React.PropTypes.func.isRequired
31 },
32
33 //=========================================================================
34
35 render: function () {
36 returnReact.DOM.div({className:'checkbox', onClick:this.props['eventHandler']}, [
37 React.DOM.input({name:this.props['id'], id:this.props['id'], value:this.props['id'], type:'checkbox', checked:this.props['checked']}),
38 React.DOM.label({className:'check', 'for':this.props['id']}),
39 React.DOM.label({className:'info', 'for':this.props['id']}, "enable local storage")
40 ]);
41 }
42
43 //=========================================================================
44});
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js b/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
index 2b5b4a4..801549f 100644
--- a/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
@@ -89,20 +89,20 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
89 ) && !this.props['disabled']; 89 ) && !this.props['disabled'];
90 }, 90 },
91 91
92 92
93 loginForm: function () { 93 loginForm: function () {
94 registrationLink =React.DOM.div({'className':'registrationLink'}, [ 94 registrationLink =React.DOM.div({'className':'registrationLink'}, [
95 React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Need an account") 95 React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up")
96 ]); 96 ]);
97 returnReact.DOM.div({'className':'loginForm credentials'},[ 97 returnReact.DOM.div({'className':'loginForm credentials'},[
98 React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [ 98 React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [
99 React.DOM.div(null,[ 99 React.DOM.div(null,[
100 React.DOM.label({'for':'name'}, "username"), 100 React.DOM.label({'for' :'name'}, "username"),
101 React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}), 101 React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
102 React.DOM.label({'for':'passphrase'}, "passphrase"), 102 React.DOM.label({'for' :'passphrase'}, "passphrase"),
103 React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'}) 103 React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
104 ]), 104 ]),
105 React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login") 105 React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
106 ]), 106 ]),
107 this.props.isNewUserRegistrationAvailable ? registrationLink : null 107 this.props.isNewUserRegistrationAvailable ? registrationLink : null
108 ]); 108 ]);
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js b/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
index cc4a06c..cb5f81a 100644
--- a/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
@@ -91,15 +91,16 @@ Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, {
91 this.setMessage(aMessage); 91 this.setMessage(aMessage);
92 92
93 MochiKit.Async.callLater(delay, MochiKit.Base.bind(this.hide, this)) 93 MochiKit.Async.callLater(delay, MochiKit.Base.bind(this.hide, this))
94 }, 94 },
95 95
96 'hide': function () { 96 'hide': function () {
97 MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-show'); 97 var element = this.element();
98 MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-hide'); 98 MochiKit.DOM.removeElementClass(element, 'ios-overlay-show');
99 MochiKit.Async.callLater(1, MochiKit.Style.hideElement, this.element()); 99 MochiKit.DOM.addElementClass(element, 'ios-overlay-hide');
100 MochiKit.Async.callLater(1, MochiKit.Style.hideElement, element);
100 }, 101 },
101 102
102 'hideSpinner': function () { 103 'hideSpinner': function () {
103 MochiKit.Style.hideElement(this.getElement('spinner')); 104 MochiKit.Style.hideElement(this.getElement('spinner'));
104 }, 105 },
105 106
diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/PreferencePage.js b/frontend/delta/js/Clipperz/PM/UI/Components/PreferencePage.js
new file mode 100644
index 0000000..822acc2
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/UI/Components/PreferencePage.js
@@ -0,0 +1,88 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.PM.UI.Components.PreferencePage = React.createClass({
25
26 getDefaultProps: function () {
27 return {
28 }
29 },
30
31 propTypes: {
32 // card: React.PropTypes.object.isRequired
33 // checked: React.PropTypes.boolean.isRequired
34 },
35
36 getInitialState: function () {
37 // return {
38 // shouldStoreDataLocally: false
39 // };
40 },
41
42 handleBackClick: function (anEvent) {
43 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
44 },
45
46 toggleShouldStoreDataLocally: function (anEvent) {
47 // this.setState({shouldStoreDataLocally: !this.state['shouldStoreDataLocally']});
48 Clipperz.PM.DataModel.devicePreferences.setShouldStoreDataLocally(!Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally());
49 this.setState({});
50 },
51
52 shouldStoreDataLocally: function () {
53 return Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally();
54 },
55
56 syncNow: function (anEvent) {
57 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'synchronizeLocalData');
58 },
59
60 //=========================================================================
61
62 render: function () {
63 returnReact.DOM.div({className:'preferences'}, [
64 React.DOM.div({className:'header'}, [
65 React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, "Preferences")),
66 React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
67 ]),
68 React.DOM.div({className:'content'}, [
69 React.DOM.form(null, [
70 React.DOM.div({className:'section'}, [
71 React.DOM.h4(null, "Local storage"),
72 React.DOM.p(null, "Store you account data locally for offline viewing"),
73 new Clipperz.PM.UI.Components.Checkbox({'id':'shouldStoreLocally_checkbox', 'checked':this.shouldStoreDataLocally(), 'eventHandler':this.toggleShouldStoreDataLocally}),
74 this.shouldStoreDataLocally() ? React.DOM.div({className:'syncInfo'}, [
75 // React.DOM.h5(null, "data were never synchronized before"),
76 React.DOM.a({className:'button', onClick:this.syncNow}, "Sync now")
77 ]) : null
78 ])
79 ])
80 ]),
81 React.DOM.div({className:'footer'}, [
82
83 ])
84 ]);
85 }
86
87 //=========================================================================
88});
diff --git a/frontend/delta/js/Clipperz/PM/UI/MainController.js b/frontend/delta/js/Clipperz/PM/UI/MainController.js
index da7540e..20ff041 100644
--- a/frontend/delta/js/Clipperz/PM/UI/MainController.js
+++ b/frontend/delta/js/Clipperz/PM/UI/MainController.js
@@ -23,31 +23,33 @@ refer to http://www.clipperz.com.
23 23
24Clipperz.Base.module('Clipperz.PM.UI'); 24Clipperz.Base.module('Clipperz.PM.UI');
25 25
26Clipperz.PM.UI.MainController = function() { 26Clipperz.PM.UI.MainController = function() {
27 var pages; 27 var pages;
28 28
29 this._proxy = null; 29 // this._proxy = null;
30 this._user = null; 30 this._user = null;
31 this._filter= ''; 31 this._filter= '';
32 32
33 //this._currentPage = 'loadingPage'; 33 //this._currentPage = 'loadingPage';
34 34
35 this._pageStack = ['loadingPage']; 35 this._pageStack = ['loadingPage'];
36 this._overlay = new Clipperz.PM.UI.Components.Overlay(); 36 this._overlay = new Clipperz.PM.UI.Components.Overlay();
37 pages = { 37 pages = {
38 'loginPage': new Clipperz.PM.UI.Components.LoginForm(), 38 'loginPage': new Clipperz.PM.UI.Components.LoginForm(),
39 'registrationPage':new Clipperz.PM.UI.Components.RegistrationWizard(), 39 'registrationPage':new Clipperz.PM.UI.Components.RegistrationWizard(),
40 'cardListPage': new Clipperz.PM.UI.Components.CardList(), 40 'cardListPage': new Clipperz.PM.UI.Components.CardList(),
41 'cardDetailPage':new Clipperz.PM.UI.Components.CardDetail({card: {}}), 41 'cardDetailPage':new Clipperz.PM.UI.Components.CardDetail({card: {}}),
42 'preferencePage':new Clipperz.PM.UI.Components.PreferencePage(),
42 'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''}) 43 'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''})
43 }; 44 };
44 45
45 MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages)); 46 MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages));
46 this._pages = pages; 47 this._pages = pages;
47 this.registerForNotificationCenterEvents(); 48 this.registerForNotificationCenterEvents();
49 MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChangeHandler');
48 50
49 return this; 51 return this;
50} 52}
51 53
52MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, { 54MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
53 55
@@ -70,16 +72,18 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
70 }, 72 },
71 73
72 //========================================================================= 74 //=========================================================================
73 75
74 isOnline: function() { 76 isOnline: function() {
75 return navigator.onLine; 77 return navigator.onLine;
78 // return false;
76 }, 79 },
77 80
78 hasLocalData: function() { 81 hasLocalData: function() {
79 return false; 82 // return false;
83 return (Clipperz.PM.DataModel.devicePreferences.accountData() != null);
80 }, 84 },
81 85
82 loginMode: function () { 86 loginMode: function () {
83 //PIN is set using this command: 87 //PIN is set using this command:
84 //Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'}); 88 //Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'});
85 89
@@ -95,50 +99,106 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
95 pageStack: function () { 99 pageStack: function () {
96 return this._pageStack; 100 return this._pageStack;
97 }, 101 },
98 102
99 //========================================================================= 103 //=========================================================================
100 104
105 showOfflineError: function () {
106console.log("THE BROWSER IS OFFLINE");
107 },
108
101 selectInitialProxy: function () { 109 selectInitialProxy: function () {
102 if (this.isOnline()) { 110 if (this.isOnline()) {
103 this._proxy = Clipperz.PM.Proxy.defaultProxy; 111 // this._proxy = Clipperz.PM.Proxy.defaultProxy;
104 } else { 112 } else {
105 if (this.hasLocalData()) { 113 if (this.hasLocalData()) {
106 this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false}); 114 // this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false});
115 Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false});
107 } else { 116 } else {
108 this.showOfflineError(); 117 this.showOfflineError();
109 } 118 }
110 } 119 }
111 }, 120 },
112 121
113 proxy: function () { 122 //proxy: function () {
114 return this._proxy; 123 // return this._proxy;
115 }, 124 //},
116 125
117 //========================================================================= 126 //=========================================================================
118 127
119 registerForNotificationCenterEvents: function () { 128 registerForNotificationCenterEvents: function () {
120 var events= ['doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack', 'showRecord', 'searchCards', 'runDirectLogin']; 129 var events= [
130 'doLogin',
131 'registerNewUser',
132 'showRegistrationForm',
133 'goBack',
134 'showRecord',
135 'searchCards',
136 'showPreferences',
137 'runDirectLogin',
138 'synchronizeLocalData'
139 ];
121 var self= this; 140 var self= this;
122 141
123 MochiKit.Base.map(function (anEvent) { 142 MochiKit.Base.map(function (anEvent) {
124 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent)); 143 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent));
125 }, events); 144 }, events);
126 145
127 // MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack')); 146 // MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack'));
128 MochiKit.Signal.connect(window, 'onbeforeunload',MochiKit.Base.method(this, 'shouldExitApp')); 147 MochiKit.Signal.connect(window, 'onbeforeunload',MochiKit.Base.method(this, 'shouldExitApp'));
129 }, 148 },
130 149
131 //------------------------------------------------------------------------- 150 //-------------------------------------------------------------------------
132 151
152 selectionChangeHandler: function (anEvent) {
153 varselection;
154 varselectionRange;
155 varselectionNode;
156 varvalueElement;
157 //other hints: http://www.bearpanther.com/2013/05/27/easy-text-selection-in-mobile-safari/
158 //SELECTION: https://developer.mozilla.org/en-US/docs/Web/API/Selection
159 //RANGE: https://developer.mozilla.org/en-US/docs/Web/API/Range
160 //NODE TYPES: https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeType
161
162 selection = MochiKit.DOM.currentWindow().getSelection();
163//console.log("-- selection", selection);
164 selectionRange = selection.getRangeAt(0);
165 selectionNode = selectionRange.startContainer.childNodes[selectionRange.startOffset];
166//console.log("-- selectionNode", selectionNode);
167
168 if (selectionNode != undefined) {
169 valueElement = MochiKit.DOM.getFirstElementByTagAndClassName('*', 'value', selectionNode);
170//console.log("-- valueElement", valueElement);
171 }
172
173 if ((valueElement != null) && (valueElement != selectionNode)) {
174 var range;
175 range = MochiKit.DOM.currentDocument().createRange();
176 range.selectNodeContents(valueElement);
177 selection.removeAllRanges();
178 selection.addRange(range);
179
180 anEvent.preventDefault();
181 anEvent.stopPropagation();
182
183//console.log("updated selection", MochiKit.DOM.currentWindow().getSelection());
184 }
185//console.log("-----------");
186 },
187
188 //-------------------------------------------------------------------------
189
133 run: function (parameters) { 190 run: function (parameters) {
134 var shouldShowRegistrationForm; 191 var shouldShowRegistrationForm;
192 varcanRegisterNewUsers;
193
194 canRegisterNewUsers = Clipperz.PM.Proxy.defaultProxy.canRegisterNewUsers();
135 195
136 this.selectInitialProxy(); 196 this.selectInitialProxy();
137 shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && this.proxy().canRegisterNewUsers(); 197 shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && canRegisterNewUsers;
138 this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()}); 198 this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':canRegisterNewUsers});
139 199
140 if (shouldShowRegistrationForm) { 200 if (shouldShowRegistrationForm) {
141 this.showRegistrationForm(); 201 this.showRegistrationForm();
142 } else { 202 } else {
143 this.showLoginForm(); 203 this.showLoginForm();
144 } 204 }
@@ -148,13 +208,13 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
148 //------------------------------------------------------------------------- 208 //-------------------------------------------------------------------------
149 209
150 showLoginForm: function () { 210 showLoginForm: function () {
151 varloginFormPage; 211 varloginFormPage;
152 212
153 loginFormPage = this.pages()['loginPage']; 213 loginFormPage = this.pages()['loginPage'];
154 loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()}); 214 loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':Clipperz.PM.Proxy.defaultProxy.canRegisterNewUsers()});
155 this.moveInPage(this.currentPage(), 'loginPage'); 215 this.moveInPage(this.currentPage(), 'loginPage');
156 MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus')); 216 MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus'));
157 }, 217 },
158 218
159 showRegistrationForm: function () { 219 showRegistrationForm: function () {
160 var currentPage; 220 var currentPage;
@@ -199,15 +259,15 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
199 deferredResult.addMethod(this, 'runApplication'); 259 deferredResult.addMethod(this, 'runApplication');
200 deferredResult.addMethod(this.overlay(), 'done', "", 1); 260 deferredResult.addMethod(this.overlay(), 'done', "", 1);
201 deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); 261 deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
202 deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) { 262 deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) {
203 if (anError['isPermanent'] != true) { 263 if (anError['isPermanent'] != true) {
204 this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()}); 264 this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()});
205 this.pages()['loginPage'].setInitialFocus(); 265 this.pages()['loginPage'].setInitialFocus();
206 } 266 }
207 return anError; 267 return anError;
208 }, this, event)) 268 }, this, event))
209 deferredResult.callback(); 269 deferredResult.callback();
210 270
211 return deferredResult; 271 return deferredResult;
212 }, 272 },
213 273
@@ -320,23 +380,25 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
320 }, 380 },
321 381
322 //========================================================================= 382 //=========================================================================
323 383
324 runApplication: function () { 384 runApplication: function () {
325 MochiKit.Signal.connect(window, 'onpopstate',MochiKit.Base.method(this, 'historyGoBack')); 385 MochiKit.Signal.connect(window, 'onpopstate',MochiKit.Base.method(this, 'historyGoBack'));
386 /// TODO: remove this TEST HACK
326 this.moveInPage(this.currentPage(), 'cardListPage'); 387 this.moveInPage(this.currentPage(), 'cardListPage');
327 return this.showRecordList(); 388 return this.showRecordList();
389
390 // this.moveInPage(this.currentPage(), 'preferencePage');
328 }, 391 },
329 392
330 showRecord: function (aRecordReference) { 393 showRecord: function (aRecordReference) {
331//console.log("Show Record", aRecordReference); 394//console.log("Show Record", aRecordReference);
332 vardeferredResult; 395 vardeferredResult;
333 396
334 this.pages()['cardListPage'].setProps({selectedCard:aRecordReference}); 397 this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
335 deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false}); 398 deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false});
336 // deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']);
337 deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); 399 deferredResult.addMethod(this.user(), 'getRecord', aRecordReference);
338 deferredResult.addMethodcaller('content'); 400 deferredResult.addMethodcaller('content');
339 deferredResult.addCallback(MochiKit.Base.bind(function (aCard) { 401 deferredResult.addCallback(MochiKit.Base.bind(function (aCard) {
340//console.log("CARD DETAILS", aCard); 402//console.log("CARD DETAILS", aCard);
341 this.pages()['cardDetailPage'].setProps({card: aCard}); 403 this.pages()['cardDetailPage'].setProps({card: aCard});
342 this.pages()['cardListPage'].setProps({selectedCard: null}); 404 this.pages()['cardListPage'].setProps({selectedCard: null});
@@ -345,34 +407,45 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
345 deferredResult.callback(); 407 deferredResult.callback();
346 408
347 return deferredResult; 409 return deferredResult;
348 }, 410 },
349 411
350 runDirectLogin: function (someParameters) { 412 runDirectLogin: function (someParameters) {
351console.log("RUN DIRECT LOGIN", someParameters); 413//console.log("RUN DIRECT LOGIN", someParameters);
352 vardeferredResult; 414 vardeferredResult;
353 415
354 // this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
355 deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false}); 416 deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false});
356 // deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']);
357 deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']); 417 deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']);
358 deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']); 418 deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']);
359 deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin); 419 deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin);
360 deferredResult.callback(); 420 deferredResult.callback();
361 421
362 return deferredResult; 422 return deferredResult;
363 }, 423 },
364 424
365 shouldExitApp: function (anEvent) { 425 shouldExitApp: function (anEvent) {
366console.log("SHOULD EXIT APP"); 426//console.log("SHOULD EXIT APP");
367 anEvent.preventDefault(); 427 anEvent.preventDefault();
368 anEvent.stopPropagation(); 428 anEvent.stopPropagation();
369 }, 429 },
370 430
371 //========================================================================= 431 //=========================================================================
372 432
433 showPreferences: function (anEvent) {
434 vardeferredResult;
435
436 this.pages()['preferencePage'].setProps({});
437 deferredResult = new Clipperz.Async.Deferred('MainController.showPreferences', {trace:false});
438 deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'preferencePage', true);
439 deferredResult.callback();
440
441 return deferredResult;
442 },
443
444 //=========================================================================
445
373 genericErrorHandler: function (anEvent, anError) { 446 genericErrorHandler: function (anEvent, anError) {
374 var errorMessage; 447 var errorMessage;
375 varresult; 448 varresult;
376 449
377 result = anError; 450 result = anError;
378 errorMessage = "login failed"; 451 errorMessage = "login failed";
@@ -477,12 +550,31 @@ console.log("SHOULD EXIT APP");
477 moveOutPage: function (fromPage, toPage) { 550 moveOutPage: function (fromPage, toPage) {
478 this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT'); 551 this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT');
479 this.setCurrentPage(toPage); 552 this.setCurrentPage(toPage);
480 }, 553 },
481 554
482 //========================================================================= 555 //=========================================================================
556
557 synchronizeLocalData: function (anEvent) {
558 vardeferredResult;
559
560 deferredResult = new Clipperz.Async.Deferred('MainController.synchronizeLocalData', {trace:true});
561 // deferredResult.addMethod(this.proxy(), 'message', 'downloadAccountData', {});
562 deferredResult.addMethod(this.user().connection(), 'message', 'downloadAccountData', {});
563 deferredResult.addCallback(function (aResult) {
564 Clipperz.PM.DataModel.devicePreferences.setAccountDataWityResponse(aResult);
565 // localStorage.setItem('clipperz_dump_data', aResult['data']);
566 // localStorage.setItem('clipperz_dump_version', aResult['version']);
567 // localStorage.setItem('clipperz_dump_date', new Date());
568 })
569 deferredResult.callback();
570
571 return deferredResult;
572 },
573
574 //=========================================================================
483/* 575/*
484 wrongAppVersion: function (anError) { 576 wrongAppVersion: function (anError) {
485 // this.pages()['errorPage'].setProps({message:anError.message}); 577 // this.pages()['errorPage'].setProps({message:anError.message});
486 // this.moveInPage('errorPage', this.currentPage()); 578 // this.moveInPage('errorPage', this.currentPage());
487 }, 579 },
488*/ 580*/