mirror of
http://git.whoc.org.uk/git/password-manager.git
synced 2025-10-30 02:47:36 +01:00
Fixed minor issues reported by user after official release of /delta
This commit is contained in:
@@ -58,10 +58,33 @@ Clipperz.PM.UI.Components.Cards.ViewClass = React.createClass({
|
||||
handlePasswordFieldAction: function (aField) {
|
||||
var self = this;
|
||||
var newState = {}
|
||||
|
||||
|
||||
newState[aField['_reference']] = !this.state[aField['_reference']];
|
||||
|
||||
|
||||
return function () {
|
||||
var fieldReference = aField['_reference'];
|
||||
var currentTimeout;
|
||||
|
||||
if (newState[fieldReference]) {
|
||||
currentTimeout = setTimeout(function(){
|
||||
var newState;
|
||||
|
||||
newState = {};
|
||||
newState[fieldReference] = false;
|
||||
|
||||
self.setState(newState);
|
||||
}, Clipperz.PM.UI.Components.Cards.ViewClass.automaticRescrambleTimeout);
|
||||
}
|
||||
|
||||
if (self.state['currentTimeout']) {
|
||||
clearTimeout(self.state['currentTimeout']);
|
||||
delete self.state['currentTimeout'];
|
||||
}
|
||||
|
||||
if (currentTimeout) {
|
||||
newState['currentTimeout'] = currentTimeout;
|
||||
}
|
||||
|
||||
self.setState(newState);
|
||||
};
|
||||
},
|
||||
@@ -193,7 +216,12 @@ Clipperz.PM.UI.Components.Cards.ViewClass = React.createClass({
|
||||
React.DOM.div({'className':'fieldEditAction'}, null),
|
||||
React.DOM.div({'className':'fieldValues'}, [
|
||||
React.DOM.div({'className':'fieldLabel'}, aField['label']),
|
||||
React.DOM.div({'className':Clipperz.PM.UI.Components.classNames(cardFieldValueClasses)}, aField['value']),
|
||||
React.DOM.textarea({
|
||||
'readOnly': true,
|
||||
'onClick': function(e) { e.target.select(); },
|
||||
'className':Clipperz.PM.UI.Components.classNames(cardFieldValueClasses),
|
||||
'value': aField['value']
|
||||
}),
|
||||
]),
|
||||
React.DOM.div({'className':'fieldAction'}, [
|
||||
React.DOM.span({'className':Clipperz.PM.UI.Components.classNames(cardFieldActionClasses), 'onClick':this.handleFieldAction(aField)}, aField['actionType'].toLowerCase() == 'password' ? 'view password' : aField['actionType'].toLowerCase())
|
||||
@@ -258,4 +286,6 @@ Clipperz.PM.UI.Components.Cards.ViewClass = React.createClass({
|
||||
//=========================================================================
|
||||
});
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.ViewClass.automaticRescrambleTimeout = 5000;
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.View = React.createFactory(Clipperz.PM.UI.Components.Cards.ViewClass);
|
||||
|
||||
@@ -79,9 +79,7 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImportClass = React.createClass({
|
||||
]),
|
||||
React.DOM.div({'className': 'content' + ' ' + currentStep + ' ' + this.importContext().inputFormat()}, [
|
||||
React.DOM.div({'className': 'step' + ' ' + currentStep}, [
|
||||
new this.componentWithName(this.importContext().currentStep())({
|
||||
'importContext': this.importContext(),
|
||||
}),
|
||||
new this.componentWithName(this.importContext().currentStep())({'importContext': this.importContext()}),
|
||||
]),
|
||||
this.renderNavbar(currentStep),
|
||||
React.DOM.div({'className': 'buttons' + ' ' + currentStep}, [
|
||||
|
||||
@@ -28,7 +28,13 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.ImportClass = React.createCla
|
||||
//=========================================================================
|
||||
|
||||
importHandler: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'importCards', this.props.importContext.state('recordsToImport'));
|
||||
var recordsToImport = this.props.importContext.state('recordsToImport');
|
||||
|
||||
if (this.props.importContext.state('useImportTag') && this.props.importContext.state('importTag')) {
|
||||
this.props.importContext.enhanceJsonDataWithImportTag(recordsToImport, this.props.importContext.state('importTag'))
|
||||
}
|
||||
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'importCards', recordsToImport);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
||||
@@ -28,7 +28,7 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.PreviewClass = React.createCl
|
||||
|
||||
getInitialState: function() {
|
||||
var recordsToImport;
|
||||
|
||||
|
||||
recordsToImport = MochiKit.Iter.reduce(
|
||||
function (acc, item) { acc[item['reference']] = item; return acc; },
|
||||
MochiKit.Base.filter(
|
||||
@@ -47,6 +47,53 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.PreviewClass = React.createCl
|
||||
|
||||
//=========================================================================
|
||||
|
||||
selectRecordsToImport: function(records) {
|
||||
var newRecordsToImport;
|
||||
var i;
|
||||
|
||||
newRecordsToImport = {};
|
||||
for (i in records) {
|
||||
newRecordsToImport[records[i]['reference']] = records[i];
|
||||
}
|
||||
|
||||
this.setState({'recordsToImport': newRecordsToImport});
|
||||
this.props.importContext.setState('recordsToImport', MochiKit.Base.values(newRecordsToImport));
|
||||
},
|
||||
|
||||
selectAll: function() {
|
||||
this.selectRecordsToImport(this.props.importContext.state('jsonData'));
|
||||
},
|
||||
|
||||
selectNone: function() {
|
||||
this.selectRecordsToImport({});
|
||||
},
|
||||
|
||||
selectNotArchived: function() {
|
||||
this.selectRecordsToImport(MochiKit.Base.filter(function (aRecord) {
|
||||
return !Clipperz.PM.DataModel.Record.labelContainsArchiveTag(aRecord['label']);
|
||||
}, this.props.importContext.state('jsonData')));
|
||||
},
|
||||
|
||||
selectArchived: function() {
|
||||
this.selectRecordsToImport(MochiKit.Base.filter(function (aRecord) {
|
||||
return Clipperz.PM.DataModel.Record.labelContainsArchiveTag(aRecord['label']);
|
||||
}, this.props.importContext.state('jsonData')));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
handleImportTagTextChange: function() {
|
||||
var newTag = this.refs['importTagText'].getDOMNode().value;
|
||||
|
||||
this.props.importContext.setState('importTag', newTag);
|
||||
},
|
||||
|
||||
handleImportTagCheckboxChange: function() {
|
||||
this.props.importContext.setState('useImportTag', ! this.props.importContext.state('useImportTag'));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
toggleRecordToImport: function(record) {
|
||||
var newRecordsToImport;
|
||||
var recordPosition;
|
||||
@@ -76,6 +123,10 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.PreviewClass = React.createCl
|
||||
tagList = MochiKit.Base.keys(tagObject);
|
||||
tagList = MochiKit.Base.filter(function(aTag) { return !Clipperz.PM.DataModel.Record.isSpecialTag(aTag); }, tagList);
|
||||
|
||||
if (this.props.importContext.state('useImportTag') && this.props.importContext.state('importTag')) {
|
||||
tagList.push(this.props.importContext.state('importTag'));
|
||||
}
|
||||
|
||||
if (tagList.length > 0) {
|
||||
result = React.DOM.ul({'className': 'tagList'},
|
||||
MochiKit.Base.map(function(aTag){
|
||||
@@ -123,7 +174,32 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.PreviewClass = React.createCl
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var inputFormat = this.props.importContext.inputFormat();
|
||||
|
||||
return React.DOM.div({'className': 'preview'},
|
||||
React.DOM.div({'className': 'selectButtons'},
|
||||
React.DOM.span({}, "Select:"),
|
||||
React.DOM.a({'onClick': this.selectAll}, "All"),
|
||||
React.DOM.a({'onClick': this.selectNone}, "None"),
|
||||
(inputFormat == 'JSON') ? React.DOM.a({'onClick': this.selectNotArchived}, "Not Archived") : null,
|
||||
(inputFormat == 'JSON') ? React.DOM.a({'onClick': this.selectArchived}, "Archived") : null
|
||||
),
|
||||
React.DOM.div({'className': 'tagButtons'},
|
||||
React.DOM.input({
|
||||
'type': 'checkbox',
|
||||
'id': 'tagCheckbox',
|
||||
'checked': this.props.importContext.state('useImportTag'),
|
||||
'onChange': this.handleImportTagCheckboxChange
|
||||
}),
|
||||
React.DOM.label({'htmlFor': 'tagCheckbox'}, "Apply the following tag to imported cards:"),
|
||||
React.DOM.input({
|
||||
'ref': 'importTagText',
|
||||
'type': 'text',
|
||||
'value': this.props.importContext.state('importTag'),
|
||||
'disabled': ! this.props.importContext.state('useImportTag'),
|
||||
'onChange': this.handleImportTagTextChange
|
||||
})
|
||||
),
|
||||
React.DOM.ul({}, MochiKit.Base.map(MochiKit.Base.method(this, 'renderCard'), this.props.importContext.state('jsonData')))
|
||||
);
|
||||
},
|
||||
|
||||
@@ -120,7 +120,7 @@ Clipperz.PM.UI.Components.ExtraFeatures.PassphraseClass = React.createClass({
|
||||
|
||||
React.DOM.p({}, [
|
||||
React.DOM.input({'key':'confirm', 'id':'changePassphraseConfirmCheckbox', 'className':'confirmCheckbox', 'type':'checkbox', 'name':'confirm', 'ref':'confirm'}),
|
||||
React.DOM.label({'htmlFor':'changePassphraseConfirmCheckbox'}, "I understand that Clipperz will not be able to help me recovering a lost passphrase.")
|
||||
React.DOM.label({'htmlFor':'changePassphraseConfirmCheckbox'}, "I understand that Clipperz is unable to recover a lost passphrase.")
|
||||
]),
|
||||
]),
|
||||
React.DOM.button({'key':'button', 'type':'submit', 'disabled':!this.shouldEnableChangePassphraseButton(), 'className':'button'}, "Change passphrase"),
|
||||
|
||||
@@ -189,13 +189,13 @@ Clipperz.PM.UI.Components.Pages.RegistrationPageClass = React.createClass({
|
||||
render_TERMS_OF_SERVICE: function () {
|
||||
return React.DOM.div({'key':'termsOfService'}, [
|
||||
React.DOM.div({'key':'termsOfService_choice_1', 'className':'checkboxBlock'}, [
|
||||
React.DOM.label({'key':'termsOfService_label_1', 'htmlFor':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
|
||||
React.DOM.input({'key':'no_password_recovery', 'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery'}),
|
||||
React.DOM.p({'key':'termsOfService_description_1'}, "I understand that Clipperz will not be able to recover a lost passphrase.")
|
||||
React.DOM.label({'key':'termsOfService_label_1', 'htmlFor':'no_password_recovery'}, "I understand that Clipperz is unable to recover a lost passphrase."),
|
||||
React.DOM.input({'key':'no_password_recovery', 'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'id':'no_password_recovery'}),
|
||||
React.DOM.p({'key':'termsOfService_description_1'}, "I understand that Clipperz is unable to recover a lost passphrase.")
|
||||
]),
|
||||
React.DOM.div({'key':'termsOfService_choice_2', 'className':'checkboxBlock'}, [
|
||||
React.DOM.label({'key':'termsOfService_label_2', 'htmlFor':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
|
||||
React.DOM.input({'key':'agree_terms_of_service', 'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service'}),
|
||||
React.DOM.input({'key':'agree_terms_of_service', 'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'id':'agree_terms_of_service'}),
|
||||
React.DOM.p({'key':'termsOfService_description_2'}, [
|
||||
React.DOM.span({'key':'termsOfService_description_2_p1'}, "I have read and agreed to the "),
|
||||
React.DOM.a({'key':'termsOfService_description_2_p2', 'href':'https://clipperz.com/terms_service/', target:'_blank'}, "Terms of Service.")
|
||||
|
||||
@@ -32,6 +32,8 @@ Clipperz.PM.UI.ImportContext = function(anInputComponent) {
|
||||
'isInputStringValid': false,
|
||||
'inputFormat': 'UNDEFINED',
|
||||
'currentStep': 'Input',
|
||||
'useImportTag': true,
|
||||
'importTag': Clipperz.PM.UI.ImportContext.getDefaultImportTag()
|
||||
};
|
||||
|
||||
return this;
|
||||
@@ -185,17 +187,20 @@ MochiKit.Base.update(Clipperz.PM.UI.ImportContext.prototype, {
|
||||
},
|
||||
|
||||
enhanceJsonDataWithCardReferences: function (someJsonData) {
|
||||
var now = new XDate();
|
||||
var dateString = now.toString('yyyyMMdd');
|
||||
|
||||
return MochiKit.Base.map(function (item) {
|
||||
item['reference'] = Clipperz.PM.Crypto.randomKey();
|
||||
// item['label'] = "COPY - " + item['label'];
|
||||
item['label'] = item['label'] + ' ' + Clipperz.PM.DataModel.Record.tagChar + "Import_" + dateString;
|
||||
return item;
|
||||
}, someJsonData);
|
||||
},
|
||||
|
||||
enhanceJsonDataWithImportTag: function(someJsonData, aTag) {
|
||||
return MochiKit.Base.map(function (item) {
|
||||
item['label'] = item['label'] + ' ' + Clipperz.PM.DataModel.Record.tagChar + aTag;
|
||||
return item;
|
||||
}, someJsonData);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
startCsvWizard: function (csvData) {
|
||||
@@ -447,3 +452,10 @@ MochiKit.Base.update(Clipperz.PM.UI.ImportContext.prototype, {
|
||||
//=============================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
Clipperz.PM.UI.ImportContext.getDefaultImportTag = function() {
|
||||
var now = new XDate();
|
||||
var dateString = now.toString('yyyyMMdd');
|
||||
|
||||
return "Import_" + dateString;
|
||||
}
|
||||
|
||||
@@ -341,7 +341,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
deferredResult.addMethod(this, 'setUser', user);
|
||||
deferredResult.addMethod(this, 'runApplication');
|
||||
deferredResult.addMethod(this.overlay(), 'done', "", 1);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', someCredentials));
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', someCredentials, "login failed"));
|
||||
deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) {
|
||||
if (anError['isPermanent'] != true) {
|
||||
this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()});
|
||||
@@ -381,7 +381,8 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase'])
|
||||
);
|
||||
deferredResult.addMethod(this, 'doLogin', credentials);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', credentials));
|
||||
deferredResult.addMethod(this,'importCards', Clipperz.PM.DefaultCards);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', credentials, "registration failed"));
|
||||
deferredResult.addErrback(MochiKit.Base.bind(function (anError) {
|
||||
if (anError['isPermanent'] != true) {
|
||||
this.pages()['registrationPage'].setProps({disabled:false});
|
||||
@@ -636,7 +637,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
rangeFilter = MochiKit.Base.operator.identity;
|
||||
} else if (aFilter['type'] == 'RECENT') {
|
||||
filterCriteria = MochiKit.Base.operator.truth;
|
||||
sortCriteria = Clipperz.Base.reverseComparator(MochiKit.Base.keyComparator('accessDate'));
|
||||
sortCriteria = Clipperz.Base.reverseComparator(MochiKit.Base.keyComparator('_accessDate'));
|
||||
rangeFilter = function (someCards) { return someCards.slice(0, 10)};
|
||||
} else if (aFilter['type'] == 'SEARCH') {
|
||||
filterCriteria = this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForSearch(aFilter['value']));
|
||||
@@ -832,12 +833,13 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
genericErrorHandler: function (anEvent, anError) {
|
||||
genericErrorHandler: function (anEvent, aMessage, anError) {
|
||||
var errorMessage;
|
||||
var result;
|
||||
|
||||
result = anError;
|
||||
errorMessage = "login failed";
|
||||
// errorMessage = "login failed";
|
||||
errorMessage = aMessage;
|
||||
|
||||
if (anError['isPermanent'] === true) {
|
||||
this.pages()['errorPage'].setProps({message:anError.message});
|
||||
@@ -925,7 +927,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
//console.log("ADD ITEM TO HISTORY");
|
||||
//console.log("ADD ITEM TO HISTORY - window", window);
|
||||
//console.log("ADD ITEM TO HISTORY - window.history", window.history);
|
||||
window.history.pushState({'fromPage': fromPage, 'toPage': toPage});
|
||||
window.history.pushState({'fromPage': fromPage, 'toPage': toPage}, "");
|
||||
//# window.history.pushState();
|
||||
//console.log("ADDED ITEM TO HISTORY");
|
||||
} else {
|
||||
@@ -956,7 +958,6 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
userInfo: function () {
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
result['checkPassphraseCallback'] = MochiKit.Base.bind(this.checkPassphrase,this);
|
||||
@@ -1011,7 +1012,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
//console.log("messageBox - this.user()", this.user());
|
||||
if (this.featureSet() == 'EXPIRED') {
|
||||
message = "Exprired subscription";
|
||||
message = "Expired subscription";
|
||||
level = 'ERROR';
|
||||
}
|
||||
|
||||
@@ -1102,6 +1103,8 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
resetPanels: function () {
|
||||
this._isSelectionPanelOpen = false;
|
||||
this._isSettingsPanelOpen = false;
|
||||
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'closeSettingsPanel');
|
||||
},
|
||||
|
||||
featureAvailableForStyles: function (listOfSupportedStyles) {
|
||||
@@ -1344,6 +1347,15 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
MochiKit.Base.method(this.overlay(), 'show', "importing …", true),
|
||||
MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel'),
|
||||
// MochiKit.Base.method(this.pages()[this.currentPage()], 'setProps', {'mode':'view', 'showGlobalMask':false}),
|
||||
function () { return data; },
|
||||
MochiKit.Base.method(this,'importCards'),
|
||||
MochiKit.Base.method(this.overlay(), 'done', "finished", 1),
|
||||
MochiKit.Base.method(this.pages()[this.currentPage()], 'setProps', {'mode':'view', 'showGlobalMask':false}),
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
importCards: function(data) {
|
||||
return Clipperz.Async.callbacks("MainController.importCards", [
|
||||
function () { return data; },
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this.user(), 'createNewRecordFromJSON')),
|
||||
|
||||
@@ -1358,8 +1370,6 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
MochiKit.Base.method(this.user(), 'saveChanges'),
|
||||
MochiKit.Base.partial(MochiKit.Base.method(this, 'resetRecordsInfo')),
|
||||
MochiKit.Base.partial(MochiKit.Base.method(this, 'refreshUI', null)),
|
||||
MochiKit.Base.method(this.overlay(), 'done', "finished", 1),
|
||||
MochiKit.Base.method(this.pages()[this.currentPage()], 'setProps', {'mode':'view', 'showGlobalMask':false}),
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user