mirror of
http://git.whoc.org.uk/git/password-manager.git
synced 2025-10-30 02:47:36 +01:00
Interim synchronization with internal repository
This is an intermir commit to share what is going on with the development of the new /delta version.
This commit is contained in:
56
frontend/delta/js/Clipperz/PM/UI/Components/AccountStatus.js
Normal file
56
frontend/delta/js/Clipperz/PM/UI/Components/AccountStatus.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.AccountStatus = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
'currentSubscriptionType': React.PropTypes.oneOf(['EARLY_ADOPTER', 'FRIEND', 'FAN', 'DEVOTEE', 'PATRON', 'TRIAL', 'TRIAL_EXPIRED', 'PAYMENT_FAILED_2', 'EXPIRED', 'PAYMENT_FAILED', 'VERIFYING_PAYMENT', 'VERIFYING_PAYMENT_2']).isRequired,
|
||||
'expirationDate': React.PropTypes.string.isRequired,
|
||||
'featureSet': React.PropTypes.oneOf(['TRIAL', 'EXPIRED', 'FULL']).isRequired,
|
||||
'isExpired': React.PropTypes.bool.isRequired,
|
||||
'isExpiring': React.PropTypes.bool.isRequired,
|
||||
'paymentVerificationPending': React.PropTypes.bool.isRequired,
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
//console.log("AccountStatus props", this.props);
|
||||
var classes = {
|
||||
'accountStatus': true,
|
||||
'isExpiring': this.props['isExpiring'],
|
||||
'isExpired': this.props['isExpired'],
|
||||
};
|
||||
|
||||
classes[this.props['featureSet']] = true;
|
||||
|
||||
return React.DOM.div({'className':React.addons.classSet(classes)}, [
|
||||
React.DOM.span({'className': 'level'}, this.props['featureSet']),
|
||||
React.DOM.span({'className': 'expirationDate'}, this.props['expirationDate'])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
53
frontend/delta/js/Clipperz/PM/UI/Components/Button.js
Normal file
53
frontend/delta/js/Clipperz/PM/UI/Components/Button.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Button = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
'eventName': React.PropTypes.string.isRequired,
|
||||
'label': React.PropTypes.string.isRequired,
|
||||
'handler': React.PropTypes.func.isRequired,
|
||||
'className': React.PropTypes.string
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var classes = {
|
||||
'button': true
|
||||
};
|
||||
if (typeof(this.props['className']) != 'undefined') {
|
||||
classes[this.props['className']] = true;
|
||||
};
|
||||
|
||||
return React.DOM.div({className:React.addons.classSet(classes), onClick:this.props['handler']}, [
|
||||
React.DOM.div({className:this.props['eventName']}, [
|
||||
React.DOM.h3({className:'label'}, this.props['label'])
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.CardDetail = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
// searchDelay: 0.3
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
card: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
// showSearch: false,
|
||||
// searchTimer: null,
|
||||
unmaskedFields: new Clipperz.Set(),
|
||||
starred: false
|
||||
};
|
||||
},
|
||||
|
||||
handleDirectLoginClick: function (aDirectLoginReference, anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference});
|
||||
},
|
||||
|
||||
toggleFieldVisibility: function (aField, anEvent) {
|
||||
var unmaskedFields;
|
||||
var fieldReference;
|
||||
|
||||
unmaskedFields = this.state['unmaskedFields'];
|
||||
fieldReference = aField['reference']
|
||||
if (unmaskedFields.contains(fieldReference)) {
|
||||
unmaskedFields.remove(fieldReference)
|
||||
} else {
|
||||
unmaskedFields.add(fieldReference)
|
||||
}
|
||||
|
||||
this.setState({'unmaskedFields': unmaskedFields});
|
||||
},
|
||||
|
||||
handleGoAction: function (aField, anEvent) {
|
||||
var newWindow;
|
||||
|
||||
newWindow = MochiKit.DOM.currentWindow().open(aField['value'], '_blank');
|
||||
newWindow.focus();
|
||||
},
|
||||
|
||||
handleEmailAction: function (aField, anEvent) {
|
||||
MochiKit.DOM.currentWindow().location = 'mailto:' + aField['value'];
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
normalizeFieldValue: function (aValue) {
|
||||
var result = [];
|
||||
var rows = aValue.split('\n');
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
if (i > 0) {
|
||||
result.push(React.DOM.br());
|
||||
}
|
||||
result.push(rows[i].replace(/[\s]/g, '\u00A0'));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderFieldActionButton: function (aField) {
|
||||
// var actionLabel;
|
||||
var result;
|
||||
|
||||
if (aField['actionType'] == 'URL') {
|
||||
result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleGoAction', aField)}, [
|
||||
React.DOM.a({className:aField['actionType']}, "go")
|
||||
]);
|
||||
} else if (aField['actionType'] == 'PASSWORD') {
|
||||
var icon;
|
||||
|
||||
if (this.state['unmaskedFields'].contains(aField['reference'])) {
|
||||
icon = "unlocked";
|
||||
} else {
|
||||
icon = "locked";
|
||||
}
|
||||
result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'toggleFieldVisibility', aField)}, [
|
||||
React.DOM.a({className:aField['actionType']}, icon)
|
||||
]);
|
||||
} else if (aField['actionType'] == 'EMAIL') {
|
||||
result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleEmailAction', aField)}, [
|
||||
React.DOM.a({className:aField['actionType']}, "email")
|
||||
]);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderField: function (aField) {
|
||||
//console.log("FIELD", aField);
|
||||
var fieldExtraClass;
|
||||
|
||||
fieldExtraClass = aField['actionType'];
|
||||
if (this.state['unmaskedFields'].contains(aField['reference'])) {
|
||||
fieldExtraClass = fieldExtraClass + ' unlocked';
|
||||
}
|
||||
|
||||
return React.DOM.div({className:'listItem ' + fieldExtraClass, key:aField['reference']}, [
|
||||
React.DOM.div({className:'fieldWrapper'}, [
|
||||
React.DOM.div({className:'fieldInnerWrapper'}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])),
|
||||
React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + fieldExtraClass}, this.normalizeFieldValue(aField['value'])))
|
||||
])
|
||||
]),
|
||||
this.renderFieldActionButton(aField)
|
||||
// React.DOM.div({className:'actionWrapper'}, [
|
||||
// React.DOM.div({className:aField['actionType']}, actionLabel)
|
||||
// ])
|
||||
]);
|
||||
},
|
||||
|
||||
renderDirectLogin: function (aDirectLogin) {
|
||||
//console.log("DIRECT LOGIN", aDirectLogin);
|
||||
return React.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])),
|
||||
React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})),
|
||||
React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go"))
|
||||
]);
|
||||
},
|
||||
|
||||
handleBackClick: function (anEvent) {
|
||||
// window.history.back();
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
|
||||
},
|
||||
|
||||
handleStarClick: function (anEvent) {
|
||||
this.setState({starred: !this.state['starred']});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var card = this.props.card;
|
||||
// var starredStatus = (this.state['starred'] ? "starred" : "unstarred");
|
||||
|
||||
if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) {
|
||||
card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] })
|
||||
}
|
||||
|
||||
return React.DOM.div({className:'cardDetail'}, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)),
|
||||
React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
|
||||
// React.DOM.div({className:'starWrapper'}, React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus))
|
||||
]),
|
||||
React.DOM.div({className:'content'}, [
|
||||
card.fields ? React.DOM.div({className:'fields'}, MochiKit.Base.map(this.renderField, card.fields)) : null,
|
||||
card.directLogins ? React.DOM.div({className:'directLogins'}, MochiKit.Base.map(this.renderDirectLogin, card.directLogins)): null
|
||||
]),
|
||||
React.DOM.div({className:'footer'}, [
|
||||
/*
|
||||
// React.DOM.a({className:'cancel'}, "cancel"),
|
||||
// React.DOM.a({className:'save'}, "save")
|
||||
|
||||
React.DOM.a({className:'cancel button'}, "failed"),
|
||||
React.DOM.a({className:'save button'}, "done")
|
||||
*/
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.CardList = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
selectedCard: null,
|
||||
searchDelay: 0.3
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
searchDelay: React.PropTypes.number
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
showSearch: false,
|
||||
searchTimer: null,
|
||||
searchText: '',
|
||||
// passphrase: '',
|
||||
// pin: ''
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
toggleSearch: function (anEvent) {
|
||||
var showSearchBox;
|
||||
|
||||
showSearchBox = !this.state.showSearch;
|
||||
|
||||
this.setState({showSearch: showSearchBox});
|
||||
|
||||
if (showSearchBox) {
|
||||
MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, 'focusOnSearchField'));
|
||||
}
|
||||
},
|
||||
|
||||
updateSearchText: function (anEvent) {
|
||||
var searchText;
|
||||
|
||||
searchText = anEvent.target.value;
|
||||
//console.log(">>> updateSearchText", searchText);
|
||||
|
||||
if ((this.state['searchTimer'] != null) && (searchText != this.state['searchText'])) {
|
||||
this.state['searchTimer'].cancel();
|
||||
}
|
||||
|
||||
if (searchText != this.state['searchText']) {
|
||||
this.state['searchText'] = searchText;
|
||||
this.state['searchTimer'] = MochiKit.Async.callLater(this.props['searchDelay'], MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'searchCards', searchText);
|
||||
}
|
||||
},
|
||||
|
||||
focusOnSearchField: function () {
|
||||
console.log("focusOnSearchField", this.refs['searchField']);
|
||||
this.refs['searchField'].getDOMNode.focus();
|
||||
},
|
||||
|
||||
searchBox: function () {
|
||||
var result;
|
||||
|
||||
if (this.state.showSearch) {
|
||||
result = React.DOM.div({className:'searchBox'}, [
|
||||
React.DOM.div(null, [
|
||||
React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText})
|
||||
])
|
||||
]);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
showPreferences: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showPreferences', anEvent);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
cardItem: function (aRecordReference) {
|
||||
var reference = aRecordReference['_reference'];
|
||||
var selectedCard = (reference == this.props.selectedCard);
|
||||
|
||||
// TODO: verify if it is possible to put the onClick handler on the container 'div', instead of adding it to each 'div' item.
|
||||
return React.DOM.div({className:'listItem', key:reference, onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)),
|
||||
// React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)),
|
||||
React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')),
|
||||
React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail")))
|
||||
]);
|
||||
},
|
||||
|
||||
handleClickOnCardDetail: function (aRecordReference, anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference);
|
||||
},
|
||||
|
||||
cardListItems: function () {
|
||||
var list;
|
||||
var result;
|
||||
|
||||
list = this.props['cardList'];
|
||||
|
||||
if (typeof(list) != 'undefined') {
|
||||
result = MochiKit.Base.map(MochiKit.Base.method(this, 'cardItem'), list);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleChange: function (anEvent) {
|
||||
// var refs = this.refs;
|
||||
// var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
// var newState = {};
|
||||
//
|
||||
// newState[refName] = event.target.value;
|
||||
// this.setState(newState);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.a({className:'account'}, 'clipperz'),
|
||||
React.DOM.div({className:'features'}, [
|
||||
// React.DOM.a({className:'addCard'}, 'add'),
|
||||
React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'),
|
||||
React.DOM.a({className:'settings', onClick:this.showPreferences}, 'settings')
|
||||
]),
|
||||
// this.searchBox()
|
||||
]),
|
||||
this.searchBox(),
|
||||
React.DOM.div({className:'content cardList'}, this.cardListItems()),
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
101
frontend/delta/js/Clipperz/PM/UI/Components/CardToolbar.js
Normal file
101
frontend/delta/js/Clipperz/PM/UI/Components/CardToolbar.js
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.CardToolbar = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
// 'style': React.PropTypes.oneOf(['extra-short', 'narrow', 'wide', 'extra-wide']).isRequired,
|
||||
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
|
||||
'enableSidePanels': React.PropTypes.bool.isRequired,
|
||||
'accountStatus': React.PropTypes.object.isRequired,
|
||||
'messageBox': React.PropTypes.object.isRequired,
|
||||
'filter': React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
selectionToggleHandler: function (anEvent) {
|
||||
//console.log("selectionToggleHandler");
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSelectionPanel');
|
||||
|
||||
},
|
||||
|
||||
settingsToggleHandler: function (anEvent) {
|
||||
//console.log("settingsToggleHandler");
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel');
|
||||
},
|
||||
|
||||
//============================================================================
|
||||
|
||||
renderWithSidePanels: function () {
|
||||
return [
|
||||
React.DOM.div({className:'selectionToggle'}, [
|
||||
Clipperz.PM.UI.Components.Button({eventName:'selectionToggleButton', label:"tags", handler:this.selectionToggleHandler})
|
||||
]),
|
||||
this.renderWithoutSidePanels(),
|
||||
React.DOM.div({className:'settingsToggle'}, [
|
||||
Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler})
|
||||
])
|
||||
];
|
||||
},
|
||||
|
||||
renderWithoutSidePanels: function () {
|
||||
var result;
|
||||
|
||||
if (this.props['filter']) {
|
||||
if (this.props['filter']['type'] == 'RECENT') {
|
||||
result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo recent'}, "recent")])];
|
||||
} else if (this.props['filter']['type'] == 'TAG') {
|
||||
result = [React.DOM.div({className:'clipperz'}, [
|
||||
React.DOM.span({className:'logo tag'}, "tag"),
|
||||
React.DOM.span({className:'value'}, this.props['filter']['value'])
|
||||
])];
|
||||
} else if (this.props['filter']['type'] == 'SEARCH') {
|
||||
result = [React.DOM.div({className:'clipperz'}, [
|
||||
React.DOM.span({className:'logo search'}, "search"),
|
||||
React.DOM.span({className:'value'}, this.props['filter']['value'])
|
||||
])];
|
||||
} else {
|
||||
result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo clipperz'}, "clipperz")])];
|
||||
}
|
||||
} else {
|
||||
result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo clipperz'}, "clipperz")])];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
//console.log("CardToolbar props", this.props);
|
||||
return React.DOM.div({className:'cardToolbar ' + this.props['style']}, [
|
||||
// React.DOM.div({className:'header'}, this.props['enableSidePanels'] ? this.renderWithSidePanels() : this.renderWithoutSidePanels()),
|
||||
React.DOM.header({}, this.props['enableSidePanels'] ? this.renderWithSidePanels() : this.renderWithoutSidePanels()),
|
||||
Clipperz.PM.UI.Components.AccountStatus(this.props['accountStatus']),
|
||||
Clipperz.PM.UI.Components.MessageBox(this.props['messageBox']),
|
||||
]);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
});
|
||||
66
frontend/delta/js/Clipperz/PM/UI/Components/Cards/List.js
Normal file
66
frontend/delta/js/Clipperz/PM/UI/Components/Cards/List.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.List = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
propTypes: {
|
||||
'cards': React.PropTypes.array,
|
||||
'selectedCard': React.PropTypes.string
|
||||
},
|
||||
|
||||
handleClick: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'cardSelected', {'reference':anEvent.currentTarget.dataset.reference, 'label':anEvent.currentTarget.dataset.label});
|
||||
},
|
||||
|
||||
renderItem: function (anItem) {
|
||||
var classes = {
|
||||
'selected': this.props['selectedCard'] ? this.props['selectedCard']['_reference'] == anItem['_reference'] : false
|
||||
};
|
||||
|
||||
return React.DOM.li({'className':React.addons.classSet(classes), 'onClick': this.handleClick, 'key':anItem['_reference'], 'data-reference':anItem['_reference'], 'data-label':anItem['label']}, [
|
||||
React.DOM.span({'className':'favicon'}, [ React.DOM.img({src:anItem['favicon']})]),
|
||||
React.DOM.span({'className':'label'}, anItem['label']),
|
||||
// React.DOM.span({'className':'action'}, 'show detail')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var cards = this.props['cards'] ? this.props['cards'] : [];
|
||||
var classes = {
|
||||
'cardList': true,
|
||||
'loadingCard': this.props['selectedCard'] && this.props['selectedCard']['_reference'] && this.props['selectedCard']['loading']
|
||||
};
|
||||
classes[this.props['style']] = true;
|
||||
|
||||
return React.DOM.div({'key':'cardList', 'className':React.addons.classSet(classes)}, [
|
||||
React.DOM.ul({}, MochiKit.Base.map(this.renderItem, cards))
|
||||
]);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
133
frontend/delta/js/Clipperz/PM/UI/Components/Cards/Toolbar.js
Normal file
133
frontend/delta/js/Clipperz/PM/UI/Components/Cards/Toolbar.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.Toolbar = React.createClass({
|
||||
|
||||
//============================================================================
|
||||
|
||||
propTypes: {
|
||||
// 'label': React.PropTypes.string.isRequired,
|
||||
// 'loading': React.PropTypes.bool,
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
getInitialState: function() {
|
||||
return {'showCommandMenu': false };
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
commands: function () {
|
||||
return {
|
||||
'delete': {
|
||||
'label': "delete",
|
||||
'broadcastEvent': 'deleteCard'
|
||||
},
|
||||
'archive': {
|
||||
'label': "archive",
|
||||
'broadcastEvent': 'archiveCard'
|
||||
},
|
||||
// 'share': {
|
||||
// 'label': "share",
|
||||
// 'broadcastEvent': 'shareCard'
|
||||
// },
|
||||
'edit': {
|
||||
'label': "edit",
|
||||
'broadcastEvent': 'editCard'
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
exit: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBackToMainPage', {'reference':this.props['_reference']});
|
||||
},
|
||||
|
||||
toggleMenu: function (anEvent) {
|
||||
this.setState({'showCommandMenu': !this.state['showCommandMenu'] });
|
||||
},
|
||||
|
||||
selectCommandItem: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, anEvent.target.dataset['broadcastEvent'], {'reference':this.props['_reference']});
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderCommands: function () {
|
||||
var commandHandler = this.selectCommandItem;
|
||||
|
||||
return React.DOM.ul({}, MochiKit.Base.map(function (aCommand) {
|
||||
return React.DOM.li({}, [React.DOM.span({'onClick':commandHandler, 'data-broadcast-event':aCommand['broadcastEvent']}, aCommand['label'])]);
|
||||
}, MochiKit.Base.values(this.commands())));
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderNarrow: function () {
|
||||
return [
|
||||
React.DOM.div({}, [
|
||||
React.DOM.div({'className':'back', 'onClick': this.exit}, 'back'),
|
||||
React.DOM.div({'className':'cardMenuOptions', 'onClick':this.toggleMenu}, 'commands'),
|
||||
React.DOM.div({'className':React.addons.classSet({'commandMenu':true, 'show':this.state['showCommandMenu']})}, [
|
||||
React.DOM.div({'className':'commandMenuMask', 'onClick':this.toggleMenu}),
|
||||
React.DOM.div({'className':'commandMenu'}, this.renderCommands())
|
||||
])
|
||||
])
|
||||
]
|
||||
},
|
||||
|
||||
renderOther: function () {
|
||||
return [this.renderCommands()];
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLayout: function (aLayout) {
|
||||
var result;
|
||||
|
||||
if (aLayout == 'narrow') {
|
||||
result = this.renderNarrow();
|
||||
} else {
|
||||
result = this.renderOther();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var style = this.props['style'];
|
||||
var classes = {
|
||||
'cardDetailToolbar': true,
|
||||
};
|
||||
classes[style] = true;
|
||||
|
||||
return React.DOM.div({'className':React.addons.classSet(classes)}, this.renderLayout(style));
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
161
frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js
Normal file
161
frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.View = React.createClass({
|
||||
|
||||
//============================================================================
|
||||
|
||||
propTypes: {
|
||||
'label': React.PropTypes.string.isRequired,
|
||||
'loading': React.PropTypes.bool,
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderEmpty: function () {
|
||||
return React.DOM.h4({}, "EMPTY");
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLoading: function () {
|
||||
return React.DOM.div({className:'loading'},[
|
||||
this.renderLabel(),
|
||||
React.DOM.h5({className:'message'}, "loading")
|
||||
/*
|
||||
React.DOM.div({className:'overlay'}, [
|
||||
React.DOM.div({className:'spinner'}, [
|
||||
React.DOM.div({className:'bar01'}),
|
||||
React.DOM.div({className:'bar02'}),
|
||||
React.DOM.div({className:'bar03'}),
|
||||
React.DOM.div({className:'bar04'}),
|
||||
React.DOM.div({className:'bar05'}),
|
||||
React.DOM.div({className:'bar06'}),
|
||||
React.DOM.div({className:'bar07'}),
|
||||
React.DOM.div({className:'bar08'}),
|
||||
React.DOM.div({className:'bar09'}),
|
||||
React.DOM.div({className:'bar10'}),
|
||||
React.DOM.div({className:'bar11'}),
|
||||
React.DOM.div({className:'bar12'})
|
||||
])
|
||||
])
|
||||
*/
|
||||
]);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLabel: function (aLabel) {
|
||||
return React.DOM.h3({'className':'cardLabel'}, aLabel);
|
||||
},
|
||||
|
||||
renderNotes: function (someNotes) {
|
||||
return React.DOM.div({'className':'cardNotes'}, someNotes);
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderTag: function (aTag) {
|
||||
return React.DOM.div({'className':'cardTag'}, aTag);
|
||||
},
|
||||
|
||||
renderTags: function (someTags) {
|
||||
return React.DOM.div({'className':'cardTags'}, MochiKit.Base.map(this.renderTag, someTags));
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderField: function (aField) {
|
||||
var cardFieldClasses = {};
|
||||
var cardFieldValueClasses = {};
|
||||
|
||||
cardFieldClasses['cardField'] = true;
|
||||
cardFieldClasses[aField['actionType']] = true;
|
||||
cardFieldClasses['hidden'] = aField['isHidden'];
|
||||
|
||||
cardFieldValueClasses['fieldValue'] = true;
|
||||
cardFieldValueClasses[aField['actionType']] = true;
|
||||
cardFieldValueClasses['hidden'] = aField['isHidden'];
|
||||
|
||||
return React.DOM.div({'className':React.addons.classSet(cardFieldClasses)}, [
|
||||
React.DOM.div({'className':'fieldValues'}, [
|
||||
React.DOM.div({'className':'fieldLabel'}, aField['label']),
|
||||
React.DOM.div({'className':React.addons.classSet(cardFieldValueClasses)}, aField['value']),
|
||||
]),
|
||||
React.DOM.div({'className':'fieldAction action'}, aField['actionType'].toLowerCase())
|
||||
]);
|
||||
},
|
||||
|
||||
renderFields: function (someFields) {
|
||||
return React.DOM.div({'className':'cardFields'}, MochiKit.Base.map(this.renderField, someFields));
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderDirectLogin: function (aDirectLogin) {
|
||||
return React.DOM.div({'className':'cardDirectLogin'}, [
|
||||
React.DOM.span({'className':'directLoginLabel'}, aDirectLogin['label']),
|
||||
React.DOM.div({'className':'directLoginAction action'}, 'DIRECT LOGIN')
|
||||
]);
|
||||
},
|
||||
|
||||
renderDirectLogins: function (someDirectLogins) {
|
||||
return React.DOM.div({'className':'cardDirectLogins'}, MochiKit.Base.map(this.renderDirectLogin, someDirectLogins));
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderCard: function () {
|
||||
return React.DOM.div({'className':'view'},[
|
||||
Clipperz.PM.UI.Components.Cards.Toolbar(this.props),
|
||||
React.DOM.div({'className':'content'}, [
|
||||
this.renderLabel(this.props['label']),
|
||||
this.renderTags(this.props['tags']),
|
||||
this.renderNotes(this.props['notes']),
|
||||
this.renderFields(this.props['fields']),
|
||||
this.renderDirectLogins(this.props['directLogins'])
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
render: function () {
|
||||
var result;
|
||||
|
||||
if (this.props['loading'] == true) {
|
||||
result = this.renderLoading();
|
||||
} else if (this.props['label']) {
|
||||
result = this.renderCard();
|
||||
} else {
|
||||
result = this.renderEmpty();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -21,6 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Checkbox = React.createClass({
|
||||
// http://development.tobypitman.com/iphoneCheckboxes/iphoneCheckboxes2.html
|
||||
|
||||
|
||||
40
frontend/delta/js/Clipperz/PM/UI/Components/ExpiredPanel.js
Normal file
40
frontend/delta/js/Clipperz/PM/UI/Components/ExpiredPanel.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.ExpiredPanel = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
// featureSet: React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']).isRequired,
|
||||
// 'level': React.PropTypes.oneOf(['hide', 'info', 'warning', 'error']).isRequired
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
return React.DOM.div({className:'expiredPanel'}, "EXPIRED PANEL");
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
47
frontend/delta/js/Clipperz/PM/UI/Components/MessageBox.js
Normal file
47
frontend/delta/js/Clipperz/PM/UI/Components/MessageBox.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.MessageBox = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
'level': React.PropTypes.oneOf(['HIDE', 'INFO', 'WARNING', 'ERROR']).isRequired,
|
||||
'message': React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
level: 'HIDE',
|
||||
message: ''
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
return React.DOM.div({className:'messageBox ' + this.props['level']}, this.props['message']);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -21,13 +21,13 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.PageTemplate = React.createClass({
|
||||
render: function() {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({'className': 'header'}, [
|
||||
React.DOM.h1(null, "clipperz")
|
||||
]),
|
||||
React.DOM.div({'className': 'content'}, this.props.innerComponent)
|
||||
])
|
||||
}
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.CardDetailPage = React.createClass({
|
||||
|
||||
render: function () {
|
||||
// return React.DOM.header({'className':''})
|
||||
return Clipperz.PM.UI.Components.Cards.View(this.props['selectedCard']);
|
||||
|
||||
},
|
||||
});
|
||||
@@ -21,11 +21,13 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.ErrorPage = React.createClass({
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.ErrorPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
// template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
@@ -36,11 +38,11 @@ Clipperz.PM.UI.Components.ErrorPage = React.createClass({
|
||||
},
|
||||
|
||||
|
||||
_render: function () {
|
||||
render: function () {
|
||||
return React.DOM.div({className:'error-message'}, this.props.message);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return new this.props.template({'innerComponent': this._render()});
|
||||
}
|
||||
// render: function () {
|
||||
// return new this.props.template({'innerComponent': this._render()});
|
||||
// }
|
||||
});
|
||||
@@ -21,24 +21,26 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.LoginPage = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.oneOf(['CREDENTIALS','PIN']).isRequired,
|
||||
isNewUserRegistrationAvailable: React.PropTypes.bool.isRequired,
|
||||
disabled: React.PropTypes.bool.isRequired
|
||||
},
|
||||
/*
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
mode: 'CREDENTIALS',
|
||||
isNewUserRegistrationAvailable: false,
|
||||
disabled: false,
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
// template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.oneOf(['CREDENTIALS','PIN']),
|
||||
isNewUserRegistrationAvailable: React.PropTypes.bool,
|
||||
disabled: React.PropTypes.bool,
|
||||
template: React.PropTypes.func
|
||||
},
|
||||
|
||||
*/
|
||||
getInitialState: function () {
|
||||
return {
|
||||
username: '',
|
||||
@@ -54,7 +56,7 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
var newState = {};
|
||||
|
||||
newState[refName] = event.target.value;
|
||||
newState[refName] = anEvent.target.value;
|
||||
this.setState(newState);
|
||||
},
|
||||
|
||||
@@ -86,25 +88,21 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
((this.state['username'] != '') && (this.state['passphrase'] != ''))
|
||||
||
|
||||
(this.state['pin'] != '')
|
||||
) && !this.props['disabled'];
|
||||
)
|
||||
&&
|
||||
!this.props['disabled'];
|
||||
},
|
||||
|
||||
|
||||
loginForm: function () {
|
||||
registrationLink = React.DOM.div({'className':'registrationLink'}, [
|
||||
React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up")
|
||||
]);
|
||||
return React.DOM.div({'className':'loginForm credentials'},[
|
||||
React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for' :'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
|
||||
React.DOM.label({'for' :'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
|
||||
return React.DOM.form({'className':'loginForm credentials', 'onChange':this.handleChange, 'onSubmit':this.handleCredentialSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'htmlFor' :'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
|
||||
React.DOM.label({'htmlFor' :'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
|
||||
]),
|
||||
this.props.isNewUserRegistrationAvailable ? registrationLink : null
|
||||
React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
|
||||
]);
|
||||
},
|
||||
|
||||
@@ -121,14 +119,12 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
},
|
||||
|
||||
pinForm: function () {
|
||||
return React.DOM.div({'className':'loginForm pin'},[
|
||||
React.DOM.form({onChange: this.handleChange, onSubmit:this.handlePINSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for':'pin'}, "pin"),
|
||||
React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login")
|
||||
])
|
||||
return React.DOM.form({'className':'loginForm pin', 'onChange':this.handleChange, 'onSubmit':this.handlePINSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for':'pin'}, "pin"),
|
||||
React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login")
|
||||
]);
|
||||
},
|
||||
|
||||
@@ -145,6 +141,16 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return new this.props.template({'innerComponent': this.props.mode == 'PIN' ? this.pinForm() : this.loginForm()});
|
||||
var registrationLink = React.DOM.div({'className':'registrationLink'}, [
|
||||
React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up")
|
||||
]);
|
||||
|
||||
return React.DOM.div({'className':'loginForm ' + this.props['style']}, [
|
||||
React.DOM.header({}, 'clipperz'),
|
||||
React.DOM.div({'className':'form'}, [
|
||||
this.props.mode == 'PIN' ? this.pinForm() : this.loginForm(),
|
||||
]),
|
||||
this.props.isNewUserRegistrationAvailable ? registrationLink : null
|
||||
]);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.MainPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
'messageBox': React.PropTypes.object.isRequired,
|
||||
// 'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']),
|
||||
'accountStatus': React.PropTypes.object.isRequired,
|
||||
// 'mediaQueryStyle': React.PropTypes.oneOf(['extra-short', 'narrow', 'wide', 'extra-wide']).isRequired,
|
||||
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
|
||||
// 'cards': React.PropTypes.deferred.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
// shouldStoreDataLocally: false
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var classes = {
|
||||
'mainPage': true
|
||||
};
|
||||
classes[this.props['style']] = true;
|
||||
//console.log("MainPage.cards", this.props['cards'], this.props['cards'].state());
|
||||
|
||||
return React.DOM.div({className:React.addons.classSet(classes)}, [
|
||||
this.props['style'] != 'extra-wide' ? Clipperz.PM.UI.Components.Panels.SelectionPanel(this.props) : null,
|
||||
Clipperz.PM.UI.Components.Panels.MainPanel(this.props),
|
||||
Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel(this.props)
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -21,7 +21,9 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.RegistrationPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
@@ -31,7 +33,7 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
{name:'TERMS_OF_SERVICE', label:'registration', _label:'terms', description:"Check our terms of service"}
|
||||
],
|
||||
disabled: false,
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
// template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
@@ -166,16 +168,16 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
|
||||
render_CREDENTIALS: function () {
|
||||
return React.DOM.div(null,[
|
||||
React.DOM.label({'for':'name'}, "username"),
|
||||
React.DOM.label({'htmlFor':'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'/*, value:this.state.username*/}),
|
||||
React.DOM.label({'for':'passphrase'}, "passphrase"),
|
||||
React.DOM.label({'htmlFor':'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'/*, value:this.state.passphrase*/})
|
||||
]);
|
||||
},
|
||||
|
||||
render_PASSWORD_VERIFICATION: function () {
|
||||
return React.DOM.div(null,[
|
||||
React.DOM.label({'for':'verify_passphrase'}, "passphrase"),
|
||||
React.DOM.label({'htmlFor':'verify_passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'verify_passphrase', 'ref':'verify_passphrase', 'placeholder':"verify passphrase", 'key':'verify_passphrase'})
|
||||
]);
|
||||
},
|
||||
@@ -183,12 +185,12 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
render_TERMS_OF_SERVICE: function () {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({className:'checkboxBlock'}, [
|
||||
React.DOM.label({'for':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
|
||||
React.DOM.label({'htmlFor':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
|
||||
React.DOM.input({'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'key':'no_password_recovery'}),
|
||||
React.DOM.p(null, "I understand that Clipperz will not be able to recover a lost passphrase.")
|
||||
]),
|
||||
React.DOM.div({className:'checkboxBlock'}, [
|
||||
React.DOM.label({'for':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
|
||||
React.DOM.label({'htmlFor':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
|
||||
React.DOM.input({'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'key':'agree_terms_of_service'}),
|
||||
React.DOM.p(null, [
|
||||
"I have read and agreed to the ",
|
||||
@@ -208,7 +210,7 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
]);
|
||||
},
|
||||
|
||||
_render: function () {
|
||||
render: function () {
|
||||
return React.DOM.div({'className':'registrationForm'},[
|
||||
React.DOM.form({onChange: this.handleChange}, [
|
||||
React.DOM.div({'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps']))
|
||||
@@ -216,9 +218,9 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return new this.props.template({'innerComponent': this._render()});
|
||||
},
|
||||
// render: function () {
|
||||
// return new this.props.template({'innerComponent': this._render()});
|
||||
// },
|
||||
|
||||
//=========================================================================
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
|
||||
|
||||
Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({
|
||||
|
||||
settingsToggleHandler: function (anEvent) {
|
||||
//console.log("settingsToggleHandler");
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel');
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var classes = {
|
||||
'panel': true,
|
||||
'right': true,
|
||||
'open': this.props['settingsPanelStatus'] == 'OPEN'
|
||||
}
|
||||
|
||||
return React.DOM.div({key:'extraFeaturesPanel', id:'extraFeaturesPanel', className:React.addons.classSet(classes)}, [
|
||||
React.DOM.header({}, [
|
||||
React.DOM.div({className:'settingsToggle'}, [
|
||||
Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler})
|
||||
])
|
||||
]),
|
||||
React.DOM.h2({}, "Extra features")
|
||||
]);
|
||||
/*
|
||||
<div id="extraFeaturesPanel" class="panel extraFeatures">
|
||||
|
||||
<div class="warnings">
|
||||
<ul>
|
||||
<li>Synchronize local data</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
<li>Account</li>
|
||||
<li>Subscription</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li>Local Data</li>
|
||||
<li>OTP</li>
|
||||
</ul>
|
||||
|
||||
<div class="donation">
|
||||
<a>Make a donation</a>
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
193
frontend/delta/js/Clipperz/PM/UI/Components/Panels/MainPanel.js
Normal file
193
frontend/delta/js/Clipperz/PM/UI/Components/Panels/MainPanel.js
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
|
||||
|
||||
Clipperz.PM.UI.Components.Panels.MainPanel = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
propTypes: {
|
||||
'messageBox': React.PropTypes.object.isRequired,
|
||||
'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']).isRequired,
|
||||
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
featureSet: 'FULL'
|
||||
};
|
||||
},
|
||||
|
||||
style: function () {
|
||||
return this.props['style'];
|
||||
},
|
||||
|
||||
featureSet: function () {
|
||||
return this.props['featureSet'];
|
||||
},
|
||||
|
||||
handleMaskClick: function () {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'maskClick');
|
||||
},
|
||||
|
||||
handleAddCardClick: function () {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'addCardClick');
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderToolbarFrame: function (anInnerComponent) {
|
||||
return React.DOM.div({'className':'cardToolbarFrame'}, [
|
||||
this.renderToolbar(),
|
||||
anInnerComponent
|
||||
]);
|
||||
},
|
||||
|
||||
renderCardFrame: function (firstColumnComponents, secondColumnComponents) {
|
||||
var addCardButton = React.DOM.div({'className': 'addCardButton', 'onClick':this.handleAddCardClick}, 'add card');
|
||||
|
||||
return React.DOM.div({'key':'cardContent', 'className':'cardContent'}, [
|
||||
React.DOM.div({'className':'cardListColumn column'}, [addCardButton, firstColumnComponents]),
|
||||
React.DOM.div({'className':'cardDetail column right'}, secondColumnComponents)
|
||||
])
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderToolbar: function () {
|
||||
var cardToolbarProps;
|
||||
|
||||
cardToolbarProps = MochiKit.Base.merge(this.props, {
|
||||
'key': 'toolbar',
|
||||
'style': this.style(),
|
||||
'enableSidePanels': (this.props['featureSet'] != 'EXPIRED')
|
||||
});
|
||||
|
||||
return Clipperz.PM.UI.Components.CardToolbar(cardToolbarProps);
|
||||
},
|
||||
|
||||
renderExpiredPanel: function () {
|
||||
return this.featureSet() == 'EXPIRED' ? Clipperz.PM.UI.Components.ExpiredPanel(this.props) : null;
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
viewComponentProps: function () {
|
||||
var result;
|
||||
|
||||
result = this.props['selectedCard'];
|
||||
if (result) {
|
||||
result['style'] = this.props['style'];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderExtraWide: function () {
|
||||
return [
|
||||
React.DOM.div({'className':'selection subpanel'}, [Clipperz.PM.UI.Components.Selections(this.props)]),
|
||||
React.DOM.div({'className':'cardContent subpanel'}, [
|
||||
this.renderToolbarFrame(
|
||||
this.renderCardFrame(
|
||||
[Clipperz.PM.UI.Components.Cards.List(this.props)],
|
||||
[
|
||||
this.renderExpiredPanel(),
|
||||
Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
]
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderWide: function () {
|
||||
return [
|
||||
this.renderToolbarFrame(
|
||||
this.renderCardFrame(
|
||||
[Clipperz.PM.UI.Components.Cards.List(this.props)],
|
||||
[
|
||||
this.renderExpiredPanel(),
|
||||
Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())
|
||||
]
|
||||
)
|
||||
)
|
||||
];
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderNarrow: function () {
|
||||
return this.renderCardFrame(
|
||||
this.renderToolbarFrame([
|
||||
this.renderExpiredPanel(),
|
||||
Clipperz.PM.UI.Components.Cards.List(this.props),
|
||||
]),
|
||||
[Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())]
|
||||
);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLayout: function (aLayout) {
|
||||
var result;
|
||||
|
||||
if (aLayout == 'extra-wide') {
|
||||
result = this.renderExtraWide();
|
||||
} else if (aLayout == 'wide') {
|
||||
result = this.renderWide();
|
||||
} else if (aLayout == 'narrow') {
|
||||
result = this.renderNarrow();
|
||||
} else if (aLayout == 'extra-short') {
|
||||
result = this.renderNarrow();
|
||||
} else {
|
||||
Clipperz.Base.exception.raise('UnknownType');
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
//console.log("MainPanel.cards", this.props['cards']);
|
||||
var classes = {
|
||||
'panel': true,
|
||||
'left': this.props['selectionPanelStatus'] == 'OPEN',
|
||||
'right': this.props['settingsPanelStatus'] == 'OPEN',
|
||||
'open': this.props['selectionPanelStatus'] == 'OPEN' || this.props['settingsPanelStatus'] == 'OPEN'
|
||||
};
|
||||
classes[this.style()] = true;
|
||||
|
||||
return React.DOM.div({'key':'mainPanel', 'id':'mainPanel', 'className':React.addons.classSet(classes)}, [
|
||||
React.DOM.div({'className':'mask', 'onClick': this.handleMaskClick}),
|
||||
React.DOM.div({'className':'container'},
|
||||
// this.style() == 'extra-wide' ? this.renderExtraWide() : this.renderOther()
|
||||
this.renderLayout(this.style())
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
|
||||
|
||||
Clipperz.PM.UI.Components.Panels.SelectionPanel = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
selectionPanelStatus: React.PropTypes.oneOf(['OPEN', 'CLOSED']).isRequired
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
//console.log("SelectionPanel", this.props);
|
||||
var classes = React.addons.classSet({
|
||||
'panel': true,
|
||||
'left': true,
|
||||
'open': this.props['selectionPanelStatus'] == 'OPEN'
|
||||
});
|
||||
|
||||
return React.DOM.div({'key':'selectionPanel', 'id':'selectionPanel', 'className':classes}, [
|
||||
Clipperz.PM.UI.Components.Selections(this.props),
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.PreferencePage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
// card: React.PropTypes.object.isRequired
|
||||
// checked: React.PropTypes.boolean.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
// return {
|
||||
// shouldStoreDataLocally: false
|
||||
// };
|
||||
},
|
||||
|
||||
handleBackClick: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
|
||||
},
|
||||
|
||||
toggleShouldStoreDataLocally: function (anEvent) {
|
||||
// this.setState({shouldStoreDataLocally: !this.state['shouldStoreDataLocally']});
|
||||
Clipperz.PM.DataModel.devicePreferences.setShouldStoreDataLocally(!Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally());
|
||||
this.setState({});
|
||||
},
|
||||
|
||||
shouldStoreDataLocally: function () {
|
||||
return Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally();
|
||||
},
|
||||
|
||||
syncNow: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'synchronizeLocalData');
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
return React.DOM.div({className:'preferences'}, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, "Preferences")),
|
||||
React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
|
||||
]),
|
||||
React.DOM.div({className:'content'}, [
|
||||
React.DOM.form(null, [
|
||||
React.DOM.div({className:'section'}, [
|
||||
React.DOM.h4(null, "Local storage"),
|
||||
React.DOM.p(null, "Store you account data locally for offline viewing"),
|
||||
new Clipperz.PM.UI.Components.Checkbox({'id':'shouldStoreLocally_checkbox', 'checked':this.shouldStoreDataLocally(), 'eventHandler':this.toggleShouldStoreDataLocally}),
|
||||
this.shouldStoreDataLocally() ? React.DOM.div({className:'syncInfo'}, [
|
||||
// React.DOM.h5(null, "data were never synchronized before"),
|
||||
React.DOM.a({className:'button', onClick:this.syncNow}, "Sync now")
|
||||
]) : null
|
||||
])
|
||||
])
|
||||
]),
|
||||
React.DOM.div({className:'footer'}, [
|
||||
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
57
frontend/delta/js/Clipperz/PM/UI/Components/Selections.js
Normal file
57
frontend/delta/js/Clipperz/PM/UI/Components/Selections.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Selections = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
selectAll: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectAllCards');
|
||||
},
|
||||
|
||||
selectRecent: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectRecentCards');
|
||||
},
|
||||
|
||||
render: function () {
|
||||
//console.log("Selections", this.props);
|
||||
return React.DOM.div({'key':'selections', 'id':'selections'}, [
|
||||
React.DOM.ul({'className':'defaultSet'}, [
|
||||
React.DOM.li({'className':'allCards', onClick: this.selectAll}, "All"),
|
||||
React.DOM.li({'className':'recentCards', onClick: this.selectRecent}, "Recent")
|
||||
]),
|
||||
React.DOM.div({'className':'search'}, [
|
||||
React.DOM.form({'className':'searchForm'}, [
|
||||
React.DOM.label({'htmlFor':'searchValue'}, 'search'),
|
||||
React.DOM.input({'type':'text', 'id':'searchValue', 'name':'search'})
|
||||
])
|
||||
]),
|
||||
React.DOM.ul({'className':'tagList'}, MochiKit.Base.map(function (aTag) { return Clipperz.PM.UI.Components.TagIndexItem({'label':aTag}); }, this.props['tags'] ? this.props['tags'] : []))
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
45
frontend/delta/js/Clipperz/PM/UI/Components/TagIndexItem.js
Normal file
45
frontend/delta/js/Clipperz/PM/UI/Components/TagIndexItem.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.TagIndexItem = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
propTypes: {
|
||||
'label': React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
handleClick: function (anEvent) {
|
||||
//console.log("TAG INDEX ITEM - handle click TAG", anEvent.target.dataset.tag);
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'tagSelected', anEvent.target.dataset.tag);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return React.DOM.li({onClick: this.handleClick, 'data-tag':this.props['label']}, this.props['label']);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
Reference in New Issue
Block a user