summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz/PM/UI
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/UI
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/UI') (more/less context) (show whitespace changes)
-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.js2
-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.js124
7 files changed, 324 insertions, 39 deletions
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
@@ -28,108 +28,161 @@ Clipperz.PM.UI.Components.CardDetail = React.createClass({
28 // searchDelay: 0.3 28 // searchDelay: 0.3
29 } 29 }
30 }, 30 },
31 31
32 propTypes: { 32 propTypes: {
33 card: React.PropTypes.object.isRequired 33 card: React.PropTypes.object.isRequired
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
54 for (var i = 0; i < rows.length; i++) { 81 for (var i = 0; i < rows.length; i++) {
55 if (i > 0) { 82 if (i > 0) {
56 result.push(React.DOM.br()); 83 result.push(React.DOM.br());
57 } 84 }
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'])}, [
94 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])), 147 React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])),
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'}, [
130 /* 183 /*
131 // React.DOM.a({className:'cancel'}, "cancel"), 184 // React.DOM.a({className:'cancel'}, "cancel"),
132 // React.DOM.a({className:'save'}, "save") 185 // React.DOM.a({className:'save'}, "save")
133 186
134 React.DOM.a({className:'cancel button'}, "failed"), 187 React.DOM.a({className:'cancel button'}, "failed"),
135 React.DOM.a({className:'save button'}, "done") 188 React.DOM.a({className:'save button'}, "done")
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
@@ -88,29 +88,36 @@ console.log("focusOnSearchField", this.refs['searchField']);
88 React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText}) 88 React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText})
89 ]) 89 ])
90 ]); 90 ]);
91 } else { 91 } else {
92 result = null; 92 result = null;
93 } 93 }
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 },
111 118
112 handleClickOnCardDetail: function (aRecordReference, anEvent) { 119 handleClickOnCardDetail: function (aRecordReference, anEvent) {
113 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference); 120 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference);
114 }, 121 },
115 122
116 cardListItems: function () { 123 cardListItems: function () {
@@ -137,25 +144,25 @@ console.log("focusOnSearchField", this.refs['searchField']);
137// 144//
138 // newState[refName] = event.target.value; 145 // newState[refName] = event.target.value;
139 // this.setState(newState); 146 // this.setState(newState);
140 }, 147 },
141 148
142 //========================================================================= 149 //=========================================================================
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 ]);
158 } 165 }
159 166
160 //========================================================================= 167 //=========================================================================
161}); 168});
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
@@ -83,25 +83,25 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
83 var result; 83 var result;
84 84
85 return( 85 return(
86 ((this.state['username'] != '') && (this.state['passphrase'] != '')) 86 ((this.state['username'] != '') && (this.state['passphrase'] != ''))
87 || 87 ||
88 (this.state['pin'] != '') 88 (this.state['pin'] != '')
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
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
@@ -85,27 +85,28 @@ Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, {
85 85
86 'completed': function (aFunctionToShowResult, aMessage, aDelayBeforeHiding) { 86 'completed': function (aFunctionToShowResult, aMessage, aDelayBeforeHiding) {
87 var delay = aDelayBeforeHiding || this.defaultDelay(); 87 var delay = aDelayBeforeHiding || this.defaultDelay();
88 88
89 this.hideSpinner(); 89 this.hideSpinner();
90 MochiKit.Base.bind(aFunctionToShowResult, this)(); 90 MochiKit.Base.bind(aFunctionToShowResult, this)();
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
106 'showDoneIcon': function () { 107 'showDoneIcon': function () {
107 MochiKit.Style.showElement(this.getElement('done')); 108 MochiKit.Style.showElement(this.getElement('done'));
108 }, 109 },
109 110
110 'showFailIcon': function () { 111 'showFailIcon': function () {
111 MochiKit.Style.showElement(this.getElement('failed')); 112 MochiKit.Style.showElement(this.getElement('failed'));
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
@@ -17,43 +17,45 @@ refer to http://www.clipperz.com.
17 See the GNU Affero General Public License for more details. 17 See the GNU Affero General Public License for more details.
18 18
19* You should have received a copy of the GNU Affero General Public 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/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
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
54 toString: function () { 56 toString: function () {
55 return "Clipperz.PM.UI.MainController"; 57 return "Clipperz.PM.UI.MainController";
56 }, 58 },
57 59
58 //========================================================================= 60 //=========================================================================
59 61
@@ -64,103 +66,161 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
64 loginForm: function () { 66 loginForm: function () {
65 return this._loginForm; 67 return this._loginForm;
66 }, 68 },
67 69
68 registrationWizard: function () { 70 registrationWizard: function () {
69 return this._registrationWizard; 71 return this._registrationWizard;
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
86 return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS'; 90 return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS';
87 }, 91 },
88 92
89 //========================================================================= 93 //=========================================================================
90 94
91 pages: function () { 95 pages: function () {
92 return this._pages; 96 return this._pages;
93 }, 97 },
94 98
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 }
145 this.overlay().done("", 0.5); 205 this.overlay().done("", 0.5);
146 }, 206 },
147 207
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;
161 varregistrationPage; 221 varregistrationPage;
162 222
163 currentPage = this.currentPage(); 223 currentPage = this.currentPage();
164 registrationPage = this.pages()['registrationPage']; 224 registrationPage = this.pages()['registrationPage'];
165 this.setCurrentPage('loginPage'); 225 this.setCurrentPage('loginPage');
166 registrationPage.setProps({}); 226 registrationPage.setProps({});
@@ -314,71 +374,84 @@ MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
314 }, 374 },
315 375
316 searchCards: function (someParameters) { 376 searchCards: function (someParameters) {
317//console.log("SEARCH CARDS", someParameters); 377//console.log("SEARCH CARDS", someParameters);
318 this.setFilter(someParameters); 378 this.setFilter(someParameters);
319 this.showRecordList(); 379 this.showRecordList();
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});
343 }, this)); 405 }, this));
344 deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true); 406 deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true);
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";
379 452
380 if (anError['isPermanent'] === true) { 453 if (anError['isPermanent'] === true) {
381 this.pages()['errorPage'].setProps({message:anError.message}); 454 this.pages()['errorPage'].setProps({message:anError.message});
382 this.moveInPage(this.currentPage(), 'errorPage'); 455 this.moveInPage(this.currentPage(), 'errorPage');
383 errorMessage = "failure"; 456 errorMessage = "failure";
384 } else { 457 } else {
@@ -471,21 +544,40 @@ console.log("SHOULD EXIT APP");
471//console.log("ADDED ITEM TO HISTORY"); 544//console.log("ADDED ITEM TO HISTORY");
472 } else { 545 } else {
473//console.log("Skip HISTORY"); 546//console.log("Skip HISTORY");
474 } 547 }
475 }, 548 },
476 549
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*/
489 //========================================================================= 581 //=========================================================================
490 __syntaxFix__: "syntax fix" 582 __syntaxFix__: "syntax fix"
491}); 583});