From ef68436ac04da078ffdcacd7e1f785473a303d45 Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Sun, 02 Oct 2011 23:56:18 +0000 Subject: First version of the newly restructured repository --- (limited to 'frontend/gamma/js/Clipperz/PM/UI/Web/Controllers') diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js new file mode 100644 index 0000000..05563bf --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js @@ -0,0 +1,329 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.AppController = function(args) { + + this._user = null; + this._tabSlotNames = { + //tabName: slotName + 'cards': 'cardGrid', +// 'directLogins': 'directLoginGrid', + 'account': 'accountPanel', + 'data': 'dataPanel', + 'tools': 'toolsPanel' + }; + + //controllers + this._cardsController = null; +// this._directLoginsController = null; + this._filterController = null; // new Clipperz.PM.UI.Web.Controllers.FilterController(); + + //components + this._appPage = null; + this._userInfoBox = null; + this._tabSidePanel = null; + +// MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'editCard', this, 'handleEditCard'); +// MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'deleteCard', this, 'handleDeleteCard'); + + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'userDataSuccessfullySaved', this, 'userDataSuccessfullySavedHandler'); + + return this; +} + +MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.AppController"; + }, + + //----------------------------------------------------------------------------- + + 'setUser': function(anUser) { + this._user = anUser; + }, + + 'user': function() { + return this._user; + }, + + //----------------------------------------------------------------------------- +/* + 'tabSlotNames': function() { + return this._tabSlotNames; + }, +*/ + 'slotNameForTab': function(aTabName) { + return this._tabSlotNames[aTabName]; + }, + + 'hideAllAppPageTabSlots': function() { + var aTabName; + + for (aTabName in this._tabSlotNames) { + this.appPage().hideSlot(this.slotNameForTab(aTabName)); + } + }, + + //----------------------------------------------------------------------------- + + 'appPage': function() { + if (this._appPage == null) { + this._appPage = new Clipperz.PM.UI.Web.Components.AppPage(); + } + + return this._appPage; + }, + + //----------------------------------------------------------------------------- + + 'tabSidePanel': function() { + if (this._tabSidePanel == null) { + this._tabSidePanel = new Clipperz.PM.UI.Web.Components.TabSidePanel(); + } + + return this._tabSidePanel; + }, + + //----------------------------------------------------------------------------- + + 'userInfoBox': function() { + if (this._userInfoBox == null) { + this._userInfoBox = new Clipperz.PM.UI.Web.Components.UserInfoBox(); + + MochiKit.Signal.connect(this._userInfoBox, 'logout', this, 'handleLogout'); + MochiKit.Signal.connect(this._userInfoBox, 'lock', this, 'handleLock'); + MochiKit.Signal.connect(this._userInfoBox, 'unlock', this, 'handleUnlock'); + } + + return this._userInfoBox; + }, + + //----------------------------------------------------------------------------- + + 'accountPanel': function () { + if (this._accountPanel == null) { + this._accountPanel = new Clipperz.PM.UI.Web.Components.AccountPanel(/*{selected:'Preferences'}*/); + } + + return this._accountPanel; + }, + + //......................................................................... + + 'dataPanel': function () { + if (this._dataPanel == null) { + this._dataPanel = new Clipperz.PM.UI.Web.Components.DataPanel(); + } + + return this._dataPanel; + }, + + //......................................................................... + + 'toolsPanel': function () { + if (this._toolsPanel == null) { + this._toolsPanel = new Clipperz.PM.UI.Web.Components.ToolsPanel(); + } + + return this._toolsPanel; + }, + + //----------------------------------------------------------------------------- + + 'filterController': function () { + if (this._filterController == null) { + this._filterController = new Clipperz.PM.UI.Web.Controllers.FilterController(); + } + + return this._filterController; + }, + + 'cardsController': function() { + if (this._cardsController == null) { + this._cardsController = new Clipperz.PM.UI.Web.Controllers.CardsController({'filterController':this._filterController}); + } + + return this._cardsController; + }, + + //----------------------------------------------------------------------------- +/* + 'directLoginsController': function() { +//Clipperz.log(">>> AppController.directLoginsController"); + if (this._directLoginsController == null) { + this._directLoginsController = new Clipperz.PM.UI.Web.Controllers.DirectLoginsController({'filterController':this._filterController}); + } +//Clipperz.log("<<< AppController.directLoginsController"); + + return this._directLoginsController; + }, +*/ + //----------------------------------------------------------------------------- + + 'populateUserInfo': function() { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("AppController.populateUserInfo", {trace:false}); + deferredResult.collectResults({ + 'username': MochiKit.Base.methodcaller('displayName'), + 'cardsNumber': [ + MochiKit.Base.methodcaller('getRecords'), + function (someResults) { return someResults.length; } + ], + 'directLoginsNumber': [ + MochiKit.Base.methodcaller('getDirectLogins'), + function (someResults) { return someResults.length; } + ] + }) + deferredResult.addMethod(this.userInfoBox(), 'updateUserDetails'); + deferredResult.callback(this.user()); + + return deferredResult; + }, + + //----------------------------------------------------------------------------- + + 'run': function(args) { + var deferredResult; + var slot; + var page; + var user; + + slot = args.slot; + user = args.user; + + this.setUser(user); + + slot.setContent(this.appPage()); + + this.appPage().slotNamed('userInfoBox').setContent(this.userInfoBox()); + this.appPage().slotNamed('tabSidePanel').setContent(this.tabSidePanel()); + + this.appPage().slotNamed('accountPanel').setContent(this.accountPanel()); + this.appPage().slotNamed('dataPanel').setContent(this.dataPanel()); + this.appPage().slotNamed('toolsPanel').setContent(this.toolsPanel()); + + this.hideAllAppPageTabSlots(); + this.appPage().showSlot(this.slotNameForTab('cards')); + + MochiKit.Signal.connect(this.tabSidePanel(), 'tabSelected', this, 'handleTabSelected'); + MochiKit.Signal.connect(this.tabSidePanel(), 'addCard', this, 'handleAddCard'); + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'addCard', this, 'handleAddCard'); + + deferredResult = new Clipperz.Async.Deferred("AppController.run", {trace:false}); + + deferredResult.addMethod(this.cardsController(), 'run', {slot:this.appPage().slotNamed('cardGrid'), user:user}); +// deferredResult.addMethod(this.directLoginsController(), 'run', {slot:this.appPage().slotNamed('directLoginGrid'), user:user}); + deferredResult.addMethod(this, 'populateUserInfo'); + + deferredResult.addCallback(MochiKit.Visual.ScrollTo, 'miscLinks', {duration:0}); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'CARDS_CONTROLLER_DID_RUN'); + deferredResult.addMethod(this.tabSidePanel(), 'selectTab', 'cards'); + deferredResult.callback(); + }, + + //----------------------------------------------------------------------------- + + 'handleTabSelected': function (selectedTabName) { + var aTabName; + var aSlotName; + +//Clipperz.log(">>> AppController.handleTabSelected", selectedTabName); + this.hideAllAppPageTabSlots(); + this.appPage().showSlot(this.slotNameForTab(selectedTabName)); + + switch (selectedTabName) { + case 'cards': + this.cardsController().focus(); + break; +// case 'directLogins': +// this.directLoginsController().focus(); +// break; + case 'data': + break; + case 'account': + break; + case 'tools': + break; + } +//Clipperz.log("<-- AppController.handleTabSelected", aTabName); + }, + + //============================================================================= + + 'handleAddCard': function (aSourceElement) { +//Clipperz.log("=== AppController.addCard", aSourceElement); + this.cardsController().addCard(aSourceElement); + }, + + //============================================================================= + + 'userDataSuccessfullySavedHandler': function (anEvent) { + this.populateUserInfo(); + }, + + //============================================================================= + + 'handleLogout': function(anEvent) { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("AppController.handleLogout", {trace:false}); + deferredResult.addMethod(this.user(), 'logout'); + deferredResult.addCallback(MochiKit.Signal.signal, this, 'logout'); + deferredResult.callback(); + + return deferredResult; + }, + + //----------------------------------------------------------------------------- + + 'handleLock': function (anEvent) { + return Clipperz.Async.callbacks("AppController.handleLock", [ + MochiKit.Base.method(this.cardsController(), 'deleteAllCleanTextData'), + MochiKit.Base.method(this.user(), 'lock') + ], {trace:false}); + }, + + //............................................................................. + + 'handleUnlock': function (anEvent) { + return Clipperz.Async.callbacks("AppController.handleUnock", [ + MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress'), + MochiKit.Base.method(this.user(), 'login'), + MochiKit.Base.method(this.cardsController(), 'focus'), + MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'progressDone'), + MochiKit.Base.method(this.userInfoBox(), 'unlock') + ], {trace:false}); + }, + + //============================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js new file mode 100644 index 0000000..2340aeb --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js @@ -0,0 +1,652 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.CardDialogController = function(args) { + args = args || {}; + + Clipperz.PM.UI.Web.Controllers.CardDialogController.superclass.constructor.call(this, args); + + this._record = args.record || Clipperz.Base.exception.raise('MandatoryParameter'); + this._delegate = args.delegate || Clipperz.Base.exception.raise('MandatoryParameter'); + + this._referenceElement = null; + this._cardDialogComponent = null; + + this._fieldsReferences = {}; + this._directLoginReferences = {}; + + this._directLoginWizardController = null; + this._directLoginEditingComponent = null; + this._isDirectLoginEditingComponentVisible = false; + + return this; +}; + +Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.CardDialogController, Object, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.CardDialogController"; + }, + + //------------------------------------------------------------------------- + + 'record': function () { + return this._record; + }, + + 'delegate': function () { + return this._delegate; + }, + + //------------------------------------------------------------------------- + + 'fieldsReferences': function () { + return this._fieldsReferences; + }, + + 'directLoginReferences': function () { + return this._directLoginReferences; + }, + + //------------------------------------------------------------------------- + + 'referenceElement': function () { + return this._referenceElement; + }, + + 'setReferenceElement': function (anElement) { + this._referenceElement = anElement; + }, + + //------------------------------------------------------------------------- + + 'cardDialogComponent': function () { + if (this._cardDialogComponent == null) { + this._cardDialogComponent = new Clipperz.PM.UI.Web.Components.CardDialogComponent(); + + MochiKit.Signal.connect(this._cardDialogComponent, 'cancel', this, 'handleCancel'); + MochiKit.Signal.connect(this._cardDialogComponent, 'save', this, 'handleSave'); + + MochiKit.Signal.connect(this._cardDialogComponent, 'addField', this, 'handleAddField'); + MochiKit.Signal.connect(this._cardDialogComponent, 'changedValue', this, 'handleChangedValue'); + + MochiKit.Signal.connect(this._cardDialogComponent, 'addDirectLogin',this, 'handleAddDirectLogin'); + MochiKit.Signal.connect(this._cardDialogComponent, 'keyPressed', this, 'handleCardDialogComponentKeyPressed'); + } + + return this._cardDialogComponent; + }, + + //========================================================================= + + 'directLoginWizardController': function () { + if (this._directLoginWizardController == null) { + this._directLoginWizardController = new Clipperz.PM.UI.Web.Controllers.DirectLoginWizardController({ + 'cardLabel': this.cardDialogComponent().title(), + 'directLoginEditingComponent': this.directLoginEditingComponent() + }) + + MochiKit.Signal.connect(this._directLoginWizardController, 'exit', this, 'handleHideDirectLoginEditingComponent'); + MochiKit.Signal.connect(this._directLoginWizardController, 'done', this, 'handleCompleteDirectLoginEditingComponent'); + } + + return this._directLoginWizardController; + }, + + //------------------------------------------------------------------------- + + 'directLoginEditingComponent': function () { + if (this._directLoginEditingComponent == null) { + this._directLoginEditingComponent = new Clipperz.PM.UI.Web.Components.DirectLoginEditingComponent(); + + this.cardDialogComponent().renderDirectLoginEditingComponent(this._directLoginEditingComponent); + +// MochiKit.Signal.connect(this._directLoginEditingComponent, 'back', this, 'handleHideDirectLoginEditingComponent') +// MochiKit.Signal.connect(this._directLoginEditingComponent, 'changedValue', this, 'handleChangedValue'); +// MochiKit.Signal.connect(this.__directLoginEditingComponent, 'keyPressed', this, 'handleDirectLoginEditingComponentKeyPressed'); + } + + return this._directLoginEditingComponent; + }, + + //------------------------------------------------------------------------- + + 'isDirectLoginEditingComponentVisible': function () { + return this._isDirectLoginEditingComponentVisible; + }, + + 'setIsDirectLoginEditingComponentVisible': function (aValue) { + this._isDirectLoginEditingComponentVisible = aValue; + }, + + //========================================================================= + + 'run': function (anElement) { + var deferredResult; + + this.setReferenceElement(anElement); + + deferredResult = new Clipperz.Async.Deferred("CardDialogController.run", {trace:false}); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':11}); + + deferredResult.addMethod(this.cardDialogComponent(), 'deferredShowModal', {openFromElement:this.referenceElement()}); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); + + deferredResult.addMethod(this.record(), 'label'); + deferredResult.addMethod(this.cardDialogComponent(), 'setTitle'); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); + + deferredResult.addMethod(this, 'updateComponentState'); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'progressDone'); + + deferredResult.addMethod(this.cardDialogComponent(), 'fixRendering'); + deferredResult.addMethod(this.cardDialogComponent(), 'hideProgressMask'); + + if (this.record().isBrandNew()) { + deferredResult.addMethod(this.cardDialogComponent(), 'setHintMode', 'ON'); + deferredResult.addMethod(this.cardDialogComponent(), 'setFocusOnTitleField'); + } + + deferredResult.addErrback(MochiKit.Base.method(this.cardDialogComponent(), 'showError')); + deferredResult.callback(); + + return deferredResult; + }, + + //========================================================================= + + 'updateComponentState': function () { + return Clipperz.Async.callbacks("CardDialogController.updateComponentState", [ + MochiKit.Base.method(this.record(), 'hasPendingChanges'), + MochiKit.Base.method(this.cardDialogComponent(), 'setShouldEnableSaving'), + + MochiKit.Base.method(this.record(), 'label'), + MochiKit.Base.method(this.cardDialogComponent(), 'setTitle'), + MochiKit.Base.method(this.record(), 'notes'), + MochiKit.Base.method(this.cardDialogComponent(), 'setNotes'), + + MochiKit.Base.method(this.record(), 'fields'), + MochiKit.Base.values, + MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addCardDialogComponentWithField')), + + MochiKit.Base.method(this.record(), 'directLogins'), + MochiKit.Base.values, + MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addCardDialogComponentWithDirectLogin')), + + MochiKit.Base.method(this.cardDialogComponent(), 'resetNewFieldInputs'), + MochiKit.Base.noop + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'addCardDialogComponentWithField': function (aField) { + var fieldComponent; + + fieldComponent = new Clipperz.PM.UI.Web.Components.CardDialogRecordFieldComponent({reference: aField.reference()}); + MochiKit.Signal.connect(fieldComponent, 'changedValue', this, 'handleChangedValue'); + MochiKit.Signal.connect(fieldComponent, 'performAction',this, 'handlePerformFieldAction'); + MochiKit.Signal.connect(fieldComponent, 'deleteField', this, 'handleDeleteField'); + +// this.fieldsReferences().push({'field':aField, 'component':fieldComponent}); + this.fieldsReferences()[aField.reference()] = {'field':aField, 'component':fieldComponent}; + + return Clipperz.Async.callbacks("CardDialogController.addCardDialogComponentWithField", [ + MochiKit.Base.method(this.cardDialogComponent(), 'addFieldRowComponent', fieldComponent), + + MochiKit.Base.method(aField, 'label'), + MochiKit.Base.method(fieldComponent, 'setLabel'), + MochiKit.Base.method(aField, 'value'), + MochiKit.Base.method(fieldComponent, 'setValue'), + MochiKit.Base.method(aField, 'actionType'), + MochiKit.Base.method(fieldComponent, 'setActionType'), + MochiKit.Base.method(aField, 'isHidden'), + MochiKit.Base.method(fieldComponent, 'setIsHidden') + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'addCardDialogComponentWithDirectLogin': function (aDirectLogin) { + var directLoginComponent; + + directLoginComponent = new Clipperz.PM.UI.Web.Components.CardDialogRecordDirectLoginComponent({reference: aDirectLogin.reference()}); + MochiKit.Signal.connect(directLoginComponent, 'changedValue', this, 'handleChangedValue'); + MochiKit.Signal.connect(directLoginComponent, 'deleteDirectLogin', this, 'handleDeleteDirectLogin'); + MochiKit.Signal.connect(directLoginComponent, 'editDirectLogin', this, 'handleEditDirectLogin'); + MochiKit.Signal.connect(directLoginComponent, 'openDirectLogin', this, 'handleOpenDirectLogin'); + + this.directLoginReferences()[aDirectLogin.reference()] = {'directLogin':aDirectLogin, 'component':directLoginComponent}; + + return Clipperz.Async.callbacks("CardDialogController.addCardDialogComponentWithDirectLogin", [ + MochiKit.Base.method(this.cardDialogComponent(), 'addDirectLoginComponent', directLoginComponent), + MochiKit.Base.method(this, 'refreshDirectLoginComponent', this.directLoginReferences()[aDirectLogin.reference()]) + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'refreshDirectLoginComponent': function (aDirectLoginReference) { + return Clipperz.Async.callbacks("CardDialogController.refreshDirectLoginComponent", [ + MochiKit.Base.method(aDirectLoginReference['directLogin'], 'favicon'), +// MochiKit.Base.method(aDirectLoginReference['directLogin'], 'faviconData'), + MochiKit.Base.method(aDirectLoginReference['component'], 'setFavicon'), + MochiKit.Base.method(aDirectLoginReference['directLogin'], 'label'), + MochiKit.Base.method(aDirectLoginReference['component'], 'setLabel') + ], {trace:false}); + }, + + 'refreshDirectLoginComponents': function () { + return Clipperz.Async.callbacks("CardDialogController.refreshDirectLoginComponents", [ + MochiKit.Base.method(this, 'directLoginReferences'), + MochiKit.Base.values, + MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'refreshDirectLoginComponent')), + Clipperz.Async.collectAll + ]) + }, + + //------------------------------------------------------------------------- + + 'updateRecordValues': function () { + return Clipperz.Async.callbacks('CardDialogController.updateRecordValues', [ + MochiKit.Base.method(this.cardDialogComponent(), 'title'), + MochiKit.Base.method(this.record(), 'setLabel'), + MochiKit.Base.method(this.cardDialogComponent(), 'notes'), + MochiKit.Base.method(this.record(), 'setNotes'), + + MochiKit.Base.method(this, 'fieldsReferences'), + MochiKit.Base.values, + MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'updateRecordFieldValues')), + + MochiKit.Base.method(this, 'directLoginReferences'), + MochiKit.Base.values, + MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'updateRecordDirectLoginValues')), + + MochiKit.Base.method(this.directLoginEditingComponent(), 'directLoginReference'), + MochiKit.Base.method(this.record(), 'directLoginWithReference'), + MochiKit.Base.method(this, 'updateRecordDirectLoginDetails'), + + MochiKit.Base.noop + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'updateRecordFieldValues': function (aFieldReference) { + var deferredResult; + + deferredResult = Clipperz.Async.callbacks('CardDialogController.updateRecordFieldValues', [ + MochiKit.Base.method(aFieldReference['component'], 'label'), + MochiKit.Base.method(aFieldReference['field'], 'setLabel'), + + MochiKit.Base.method(aFieldReference['component'], 'value'), + MochiKit.Base.method(aFieldReference['field'], 'setValue'), + + MochiKit.Base.method(aFieldReference['component'], 'isHidden'), + MochiKit.Base.method(aFieldReference['field'], 'setIsHidden'), + + MochiKit.Base.method(aFieldReference['field'], 'actionType'), + MochiKit.Base.method(aFieldReference['component'], 'setActionType') + ], {trace:false}); + + return deferredResult; + }, + + //------------------------------------------------------------------------- + + 'updateRecordDirectLoginValues': function (aDirectLoginReference) { + var deferredResult; + + deferredResult = Clipperz.Async.callbacks('CardDialogController.updateRecordDirectLoginValues', [ + MochiKit.Base.method(aDirectLoginReference['component'], 'label'), + MochiKit.Base.method(aDirectLoginReference['directLogin'], 'setLabel') + ], {trace:false}); + + return deferredResult; + }, + + //------------------------------------------------------------------------- + + 'updateRecordDirectLoginDetails': function (aDirectLogin) { + var result; + + if (MochiKit.Base.isUndefinedOrNull(aDirectLogin)) { + result = MochiKit.Async.succeed(); + } else { + result = Clipperz.Async.callbacks("CardDialogController.updateRecordDirectLoginDetails", [ + MochiKit.Base.method(this.directLoginEditingComponent(), 'label'), + MochiKit.Base.method(aDirectLogin, 'setLabel'), + MochiKit.Base.method(this.directLoginEditingComponent(), 'favicon'), + MochiKit.Base.method(aDirectLogin, 'setFavicon') + ], {trace:false}); + } + + return result; + }, + + //========================================================================= + + 'addField': function () { + return this.record().addField({ + 'label':this.cardDialogComponent().newFieldLabel(), + 'value':this.cardDialogComponent().newFieldValue(), + 'isHidden':this.cardDialogComponent().newFieldIsHidden() + }); + }, + + 'handleAddField': function () { + return Clipperz.Async.callbacks("CardDialogController.handleAddField", [ + MochiKit.Base.method(this, 'addField'), + + MochiKit.Base.method(this, 'addCardDialogComponentWithField'), + MochiKit.Base.method(this.cardDialogComponent(), 'resetNewFieldInputs'), + + MochiKit.Base.method(this.cardDialogComponent(), 'fixRendering'), + MochiKit.Base.method(this, 'handleChangedValue') + ], {trace:false}) + }, + + //------------------------------------------------------------------------- + + 'handlePerformFieldAction': function (aFieldID, aTargetElement) { +//console.log("### targetElement", aTargetElement); + return Clipperz.Async.callbacks("CardDialogController.handleDeleteField", [ + MochiKit.Base.method(this.record(), 'fields'), + MochiKit.Base.itemgetter(aFieldID), + Clipperz.Async.collectResults("CardDialogController.handleDeleteField ", { + 'value': MochiKit.Base.methodcaller('value'), + 'type': MochiKit.Base.methodcaller('actionType') + }, {trace:false}), + MochiKit.Base.bind(function (someValues) { + switch (someValues['type']) { + case 'NONE': + throw "this event handler should not be triggered for fields with type 'NONE'"; + break; + case 'URL': + var url; + + url = someValues['value']; + if (/^https?\:\/\//.test(url) == false) { + url = 'http://' + url; + } + + window.open(url); + break; + case 'EMAIL': + var url; + + url = 'mailto:' + someValues['value']; + + MochiKit.DOM.currentWindow().location = url; + break; + case 'PASSWORD': +//Clipperz.log("SHOW PASSWORD " + someValues['value']); + this.showPasswordTooltip(someValues['value'], aTargetElement); + break; + } + }, this) + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleDeleteField': function (aFieldID) { + return Clipperz.Async.callbacks("CardDialogController.handleDeleteField", [ + MochiKit.Base.method(this.record(), 'fields'), + MochiKit.Base.itemgetter(aFieldID), + MochiKit.Base.method(this.record(), 'removeField'), + + MochiKit.Base.method(this, 'fieldsReferences'), + MochiKit.Base.itemgetter(aFieldID), + MochiKit.Base.itemgetter('component'), + + function (aComponent) { + return Clipperz.Async.callbacks("CardDialogController.handleDeleteField [fade and remove]", [ + MochiKit.Base.partial(Clipperz.Visual.deferredAnimation, MochiKit.Visual.fade, aComponent.element(), {from:1.0, to:0.0, duration:0.5}), +// Clipperz.Visual.deferredAnimation(MochiKit.Visual.fade, aComponent.element(), {from:1.0, to:0.0, duration:0.5}), + MochiKit.Base.method(aComponent, 'remove') + ], {trace:false}); + }, + + MochiKit.Base.bind(function () { + delete this.fieldsReferences()[aFieldID]; + }, this), + + MochiKit.Base.method(this.cardDialogComponent(), 'fixRendering'), + MochiKit.Base.method(this, 'handleChangedValue') + ], {trace:false}); + }, + + //========================================================================= + + 'handleDeleteDirectLogin': function(aDirectLoginReference) { + var cardDialogComponent; + + cardDialogComponent = this.cardDialogComponent(); + + return Clipperz.Async.callbacks("CardDialogController.handleDeleteDirectLogin", [ + MochiKit.Base.method(this.record(), 'directLogins'), + MochiKit.Base.itemgetter(aDirectLoginReference), + MochiKit.Base.methodcaller('remove'), + + MochiKit.Base.method(this, 'directLoginReferences'), + MochiKit.Base.itemgetter(aDirectLoginReference), + MochiKit.Base.itemgetter('component'), + + function (aComponent) { + return Clipperz.Async.callbacks("CardDialogController.handleDeleteDirectLogin [fade and remove]", [ + MochiKit.Base.partial(Clipperz.Visual.deferredAnimation, MochiKit.Visual.fade, aComponent.element(), {from:1.0, to:0.0, duration:0.5}),// Clipperz.Visual.deferredAnimation(MochiKit.Visual.fade, aComponent.element(), {from:1.0, to:0.0, duration:0.5}), +/// MochiKit.Base.method(aComponent, 'remove') + MochiKit.Base.method(cardDialogComponent, 'removeDirectLoginComponent', aComponent) + ], {trace:false}); + }, + + MochiKit.Base.bind(function () { + delete this.directLoginReferences()[aDirectLoginReference]; + }, this), + + MochiKit.Base.method(this.cardDialogComponent(), 'fixRendering'), + MochiKit.Base.method(this, 'handleChangedValue') + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleOpenDirectLogin': function (aDirectLoginReference) { + return Clipperz.Async.callbacks("CardDialogController.handleOpenDirectLogin", [ + MochiKit.Base.method(this.record(), 'directLoginWithReference', aDirectLoginReference), + Clipperz.PM.UI.Common.Controllers.DirectLoginRunner.openDirectLogin + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleEditDirectLogin': function (aDirectLoginReference) { + return Clipperz.Async.callbacks("CardDialogController.handleEditDirectLogin", [ + MochiKit.Base.method(this, 'setIsDirectLoginEditingComponentVisible', true), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setDirectLoginReference', aDirectLoginReference), + MochiKit.Base.method(this.cardDialogComponent(), 'placeDirectLoginEditingComponent'), + MochiKit.Base.method(this.record(), 'directLoginWithReference', aDirectLoginReference), + MochiKit.Base.method(this.directLoginWizardController(), 'runWithDirectLogin'), + MochiKit.Base.method(this.directLoginWizardController(), 'fixRulerRendering', this.cardDialogComponent().displayMode()), + MochiKit.Base.method(this.cardDialogComponent(), 'showDirectLoginEditingComponent') + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleHideDirectLoginEditingComponent': function () { + return Clipperz.Async.callbacks("CardDialogController.handleHideDirectLoginEditingComponent", [ + MochiKit.Base.method(this, 'setIsDirectLoginEditingComponentVisible', false), + MochiKit.Base.method(this.directLoginWizardController(), 'hideRuler'), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setDirectLoginReference', null), + MochiKit.Base.method(this, 'refreshDirectLoginComponents'), + MochiKit.Base.method(this.cardDialogComponent(), 'hideDirectLoginEditingComponent') + ], {trace:false}) + }, + + 'handleCompleteDirectLoginEditingComponent': function (someParameters) { + return Clipperz.Async.callbacks("CardDialogController.handleCompleteDirectLoginEditingComponent", [ + MochiKit.Base.method(this, 'setIsDirectLoginEditingComponentVisible', false), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setDirectLoginReference', null), + MochiKit.Base.partial(MochiKit.Async.succeed, someParameters['hasJustBeenAdded']), + Clipperz.Async.deferredIf("CardDialogController.handleCompleteDirectLoginEditingComponent - should addTheEditedDirectLogin", [ + MochiKit.Base.method(this, 'addCardDialogComponentWithDirectLogin', someParameters['directLogin']) + ], []), + MochiKit.Base.method(this, 'refreshDirectLoginComponents'), + MochiKit.Base.method(this, 'handleChangedValue'), + MochiKit.Base.method(this.cardDialogComponent(), 'hideDirectLoginEditingComponent') + ], {trace:false}) + }, + + //========================================================================= + + 'handleChangedValue': function () { + return Clipperz.Async.callbacks("CardDialogController.handleChangedValue", [ + MochiKit.Base.method(this, 'updateRecordValues'), + MochiKit.Base.method(this.record(), 'hasPendingChanges'), + MochiKit.Base.method(this.cardDialogComponent(), 'setShouldEnableSaving') + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleSave': function () { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("CardDialogController.handleSave", {trace:false}); + deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':8}); + deferredResult.addMethod(this.cardDialogComponent(), 'showProgressMask'); + deferredResult.addMethod(this.cardDialogComponent(), 'newFieldHasPendingChanges'); + deferredResult.addIf([ + MochiKit.Base.method(this, 'addField') + ], []) + deferredResult.addMethod(this, 'saveChanges'); + deferredResult.addMethod(this.cardDialogComponent(), 'deferredHideModal', {closeToElement:null}); + deferredResult.addMethod(this.cardDialogComponent(), 'remove'); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'cardDialogComponentClosed'); + + deferredResult.callback(); + + return deferredResult; + }, + + //......................................................................... + + 'saveChanges': function () { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("CardDialogController.handleSave", {trace:false}); + deferredResult.addMethod(this.delegate(), 'saveChanges'); +deferredResult.addErrback(function (aValue) { Clipperz.log("SHIT HAPPENS!!"); return aValue; }); + + deferredResult.callback(); + + return deferredResult; + }, + + //------------------------------------------------------------------------- + + 'handleCancel': function () { + var deferredResult; + + if (this.isDirectLoginEditingComponentVisible()) { + deferredResult = this.handleHideDirectLoginEditingComponent(); + } else { + deferredResult = new Clipperz.Async.Deferred("CardDialogController.handleCancel", {trace:false}); + // deferredResult.addMethod(this.record(), 'hasPendingChanges'), + deferredResult.addMethod(this.delegate(), 'hasPendingChanges'), + deferredResult.addIf([ + MochiKit.Base.method(this.cardDialogComponent(), 'askConfirmationForLoosingPendingChanges') + ], []) + deferredResult.addMethod(this.delegate(), 'revertChanges'); + deferredResult.addMethod(this.cardDialogComponent(), 'deferredHideModal', {closeToElement:this.referenceElement()}); + deferredResult.addMethod(this.cardDialogComponent(), 'remove'); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'cardDialogComponentClosed'); + + deferredResult.callback(); + } + + return deferredResult; + }, + + //------------------------------------------------------------------------- + + 'handleAddDirectLogin': function () { + return Clipperz.Async.callbacks("CardDialogController.handleAddDirectLogin", [ + MochiKit.Base.method(this.record(), 'createNewDirectLogin'), + MochiKit.Base.bind(function (aDirectLogin) { + return Clipperz.Async.callbacks("CardDialogController.handleAddDirectLogin - directLogin", [ + MochiKit.Base.method(this.cardDialogComponent(), 'newFieldHasPendingChanges'), + Clipperz.Async.deferredIf("cardDialogComponent.newFieldHasPendingChanges", [ + MochiKit.Base.method(this, 'handleAddField') + ], []), + + MochiKit.Base.method(this.directLoginEditingComponent(), 'setDirectLoginReference', aDirectLogin.reference()), + MochiKit.Base.method(this.cardDialogComponent(), 'placeDirectLoginEditingComponent'), + MochiKit.Base.method(this.directLoginWizardController(), 'runWithDirectLogin', aDirectLogin, true), + MochiKit.Base.method(this.directLoginWizardController(), 'fixRulerRendering', this.cardDialogComponent().displayMode()), + MochiKit.Base.method(this.cardDialogComponent(), 'showDirectLoginEditingComponent') + ], {trace:false}); + }, this) + ], {trace:false}); + }, + + //========================================================================= + + 'handleCardDialogComponentKeyPressed': function (anEvent) { + if ((anEvent.key().string == 'KEY_TAB') && this.cardDialogComponent().newFieldHasPendingChanges()) { + anEvent.preventDefault(); + +// MochiKit.Signal.signal(this.cardDialogComponent(), 'addField'); + this.handleAddField() + this.cardDialogComponent().focusOnNewFieldLabel(); + } + }, + + //========================================================================= + + 'showPasswordTooltip': function (aValue, anElement) { + var passwordTooltip; + + passwordTooltip = new Clipperz.PM.UI.Web.Components.PasswordTooltip({ + 'referebceElement': anElement, + 'text': aValue + }); + + passwordTooltip.show(); + + + }, + + //========================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardsController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardsController.js new file mode 100644 index 0000000..b1a34b2 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardsController.js @@ -0,0 +1,207 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.CardsController = function() { + Clipperz.PM.UI.Web.Controllers.CardsController.superclass.constructor.apply(this, arguments); + + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'cardDialogComponentClosed', this, 'handleHideCard'); + + return this; +} + +Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.CardsController, Clipperz.PM.UI.Web.Controllers.GridController, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.CardsController"; + }, + + 'createGrid': function () { + var grid; + + grid = new Clipperz.PM.UI.Web.Components.GridComponent({columnsManagers: [ + new Clipperz.PM.UI.Web.Components.FaviconColumnManager({ + 'name': 'Cards.favicon', + 'selector': MochiKit.Base.methodcaller('favicon'), + 'cssClass': 'favicon' + }), + new Clipperz.PM.UI.Web.Components.LinkColumnManager({ + 'name': 'Cards.title', + 'selector': MochiKit.Base.methodcaller('label'), + 'label': 'title', + 'cssClass': 'title', + 'comparator': Clipperz.Base.caseInsensitiveCompare, + 'sortable': true, + 'sorted': 'ASCENDING', +// 'actionMethod': function(anObject, anEvent) { MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'editCard', {objectData:anObject, element:anEvent.src()})} + 'actionMethod': MochiKit.Base.method(this, 'handleShowCard') + }), + new Clipperz.PM.UI.Web.Components.DirectLoginsColumnManager({ + 'name': 'Cards.directLogins', + 'selector': MochiKit.Base.methodcaller('directLoginReferences'), + 'label': 'direct logins', + 'cssClass': 'directLogin' + }), + new Clipperz.PM.UI.Web.Components.DateColumnManager({ + 'name': 'Cards.latestUpdate', + 'selector': MochiKit.Base.methodcaller('updateDate'), + 'label': 'latest update', + 'cssClass': 'latestUpdate', + 'format': 'd-m-Y', + 'comparator': MochiKit.Base.compare, + 'sortable': true, + 'sorted': 'UNSORTED' + }), + new Clipperz.PM.UI.Web.Components.DeleteObjectColumnManager({ + 'name': 'Cards.delete', + 'selector': MochiKit.Base.noop, + 'cssClass': 'delete', +// 'actionMethod': function(anObject, anEvent) { MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'deleteCard', {objectData:anObject, element:anEvent.src()})} + 'actionMethod': MochiKit.Base.method(this, 'handleDeleteCard') + }) + ]}); + + grid.setComponentForSlotNamed(new Clipperz.PM.UI.Web.Components.BookmarkletComponent(), 'headerSlot'); + + return grid; + }, + + //----------------------------------------------------------------------------- + + 'getRows': function () { + //TODO relying on user() in GridController, bad code smell :| + return this.user().getRecords(); + }, + + //============================================================================= + + 'displayEmptyContent': function () { + var emptyGridComponent; + + emptyGridComponent = new Clipperz.PM.UI.Web.Components.CreateNewCardSplashComponent(); + + return Clipperz.Async.callbacks("CardsController.displayEmptyContent", [ + MochiKit.Base.method(this.grid(), 'setNoRowsGridComponent', emptyGridComponent), + MochiKit.Base.bind(Clipperz.PM.UI.Web.Controllers.CardsController.superclass.displayEmptyContent, this) + ], {trace:false}); + }, + + 'displaySelectedRows': function (aFilter) { + this.columnManagerWithName('Cards.directLogins').hideDirectLoginListPopup(); + + return Clipperz.PM.UI.Web.Controllers.CardsController.superclass.displaySelectedRows.apply(this, arguments); + }, + + //============================================================================= + + 'handleShowCard': function (anObject, anEvent) { + var cardDialogController; + + cardDialogController = new Clipperz.PM.UI.Web.Controllers.CardDialogController({record:anObject, delegate:this}); + this.grid().selectRow(anObject); + + cardDialogController.run(anEvent.src()); + }, + + //......................................................................... + + 'handleHideCard': function () { + this.focus(); + }, + + //----------------------------------------------------------------------------- + + 'addCard': function (aSourceElement) { + return Clipperz.Async.callbacks("CardsController.addCard", [ + Clipperz.Async.collectResults("CardsController.addCard ", { + 'record': MochiKit.Base.method(this.user(), 'createNewRecord'), + 'delegate': MochiKit.Base.partial(MochiKit.Async.succeed, this) + }, {trace:false}), + function (someParameters) { + return new Clipperz.PM.UI.Web.Controllers.CardDialogController(someParameters); + }, + MochiKit.Base.methodcaller('run', aSourceElement) + ], {trace:false}); + }, + + //----------------------------------------------------------------------------- + + 'handleDeleteCard': function (anObject, anEvent) { + var deferredResult; + var confirmationDialog; + +// confirmationDialog = new Clipperz.PM.UI.Common.Components.SimpleMessagePanel({ + confirmationDialog = new Clipperz.PM.UI.Common.Components.MessagePanelWithProgressBar({ + 'title': "Delete Card", + 'text': "Do you want to delete …", + 'type': 'ALERT', + 'buttons': [ + {text:"Cancel", result:'CANCEL'}, + {text:"Delete", result:'OK', isDefault:true} + ], + 'canCancelWhileProcessing': false + }); + + deferredResult = new Clipperz.Async.Deferred("AppController.handleDeleteCard", {trace:false}); + deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':5}), + deferredResult.addMethod(this.grid(), 'selectRow', anObject); + deferredResult.addMethod(confirmationDialog, 'deferredShowModal', { + 'openFromElement': anEvent.src(), + 'onOkCloseToElement': null, // MochiKit.DOM.currentDocument().body, + 'onCancelCloseToElement': anEvent.src() + }); +// deferredResult.addCallback(function () { Clipperz.log("DELETE: " + anObject.toString(), anObject); }); + deferredResult.addMethod(this.user(), 'deleteRecord', anObject); + deferredResult.addBothPass(MochiKit.Base.method(this.grid(), 'unselectRow', anObject)); + deferredResult.addMethod(this, 'saveChanges'); + deferredResult.addMethod(confirmationDialog, 'deferredDone'); + deferredResult.addErrbackPass(function (anError) { + var result; + + if (! (anError instanceof MochiKit.Async.CancelledError)) { + result = confirmationDialog.deferredError({ + 'type': 'ALERT', + 'title': "Error", + 'text': Clipperz.PM.Strings.errorDescriptionForException(anError), + 'buttons': [{text:"Close", result:'CANCEL', isDefault:true}] + }) + } else { + result = anError; + } + + return result; + }); + deferredResult.callback(); + + return deferredResult; + }, + + //============================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/DirectLoginWizardController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/DirectLoginWizardController.js new file mode 100644 index 0000000..38fdc08 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/DirectLoginWizardController.js @@ -0,0 +1,611 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.DirectLoginWizardController = function(args) { + this._directLoginEditingComponent = args.directLoginEditingComponent || Clipperz.Base.exception.raise('MandatoryParameter'); + this._cardLabel = args.cardLabel || Clipperz.Base.exception.raise('MandatoryParameter'); + + MochiKit.Signal.connect(this._directLoginEditingComponent, 'changedValue', this, 'handleChangedValue'); + MochiKit.Signal.connect(this._directLoginEditingComponent, 'moveForward', this, 'handleMoveForward'); + MochiKit.Signal.connect(this._directLoginEditingComponent, 'keyPressed', this, 'handleDirectLoginEditingComponentKeyPressed'); + + this._directLogin = null; + this._directLoginHasJustBeenAdded = false; + + this._rulerComponent = null; + + this._steps = null; + this._currentStepIndex = 0; + this._isNextEnabled = false; + + this._recordFields = null; + this._originalBindings = null; + + this._bindingComponents = []; + this._formValueComponents = []; + + return this; +} + +MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.DirectLoginWizardController.prototype, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.DirectLoginWizardController"; + }, + + //------------------------------------------------------------------------- + + 'directLogin': function () { + return this._directLogin; + }, + + //------------------------------------------------------------------------- + + 'directLoginHasJustBeenAdded': function () { + return this._directLoginHasJustBeenAdded; + }, + + 'setDirectLoginHasJustBeenAdded': function (aValue) { + this._directLoginHasJustBeenAdded = aValue; + }, + + //------------------------------------------------------------------------- + + 'directLoginEditingComponent': function () { + return this._directLoginEditingComponent; + }, + + //============================================================================= + + 'cardLabel': function () { + return this._cardLabel; + }, + + //============================================================================= + + 'resetCurrentStepIndex': function () { + this._currentStepIndex = 0; + this.rulerComponent().resetStatus(); + }, + + //----------------------------------------------------------------------------- + + 'enableNext': function (aValue) { + this.rulerComponent().enableNext(aValue); + this._isNextEnabled = aValue; + }, + + 'isNextEnabled': function () { + return this._isNextEnabled; + }, + + //----------------------------------------------------------------------------- + + 'enablePrevious': function (aValue) { + this.rulerComponent().enablePrevious(aValue); + }, + + //============================================================================= + + 'bindingComponents': function () { + return this._bindingComponents; + }, + + 'resetBindingComponents': function () { + this.directLoginEditingComponent().clearAllBindingsComponents(); + this._bindingComponents = []; + }, + + //============================================================================= + + 'formValueComponents': function () { + return this._formValueComponents; + }, + + 'resetFormValueComponents': function () { + this.directLoginEditingComponent().clearAllFormValueComponents(); + this._formValueComponents = []; + }, + + //============================================================================= + + 'recordFields': function () { + return this._recordFields; + }, + + 'setRecordFields': function (aValue) { + this._recordFields = aValue; + }, + + 'recordFieldWithReference': function (aReference) { + var matchingValues; + var result; + + matchingValues = MochiKit.Base.filter(function (aField) { return aField['reference'] == aReference; }, this.recordFields()); + + if (matchingValues.length == 0) { + result = null; + } else { + result = matchingValues[0]; + } + + return result; + }, + + //----------------------------------------------------------------------------- + + 'originalBindings': function () { + return this._originalBindings; + }, + + 'setOriginalBindings': function (aValue) { +//console.log("BINDINGS", aValue); + this._originalBindings = aValue; + }, + + //============================================================================= + + 'rulerComponent': function () { + if (this._rulerComponent == null) { + this._rulerComponent = new Clipperz.PM.UI.Web.Components.RulerComponent({ + translationContext:'Wizards.DirectLoginWizard' + }); + this._rulerComponent.render(); + + MochiKit.Signal.connect(this._rulerComponent, 'exit', this, 'handleExit'); + MochiKit.Signal.connect(this._rulerComponent, 'done', this, 'done'); + MochiKit.Signal.connect(this._rulerComponent, 'moveForward', this, 'handleMoveForward'); + MochiKit.Signal.connect(this._rulerComponent, 'moveBackward', this, 'handleMoveBackward'); + MochiKit.Signal.connect(this._rulerComponent, 'cursorMoved', this, 'handleCursorMoved'); + } + + return this._rulerComponent; + }, + + //----------------------------------------------------------------------------- + + 'showRuler': function (someSteps) { + var rulerElement; + + this.setSteps(someSteps); + + rulerElement = this.rulerComponent().element(); + this.directLoginEditingComponent().disableAllPanels(); + + MochiKit.Style.showElement(rulerElement); + MochiKit.Style.setElementPosition(rulerElement, {x:-1000, y:this.directLoginEditingComponent().bottomMargin()}); + new MochiKit.Visual.Move(rulerElement, { + x:0, y:this.directLoginEditingComponent().bottomMargin(), + mode:'absolute', + duration:1, + afterFinish:MochiKit.Base.method(this, 'handleCursorMoved') + }); + }, + + 'fixRulerRendering': function (aValue) { + this.rulerComponent().setDisplayMode(aValue); + }, + + //----------------------------------------------------------------------------- + + 'hideRuler': function () { + new MochiKit.Visual.Move(this.rulerComponent().element(), {x:-1000, mode:'relative', duration:1}); + }, + + 'doneWithRuler': function () { + var rulerComponentElement; + + rulerComponentElement = this.rulerComponent().element(); + new MochiKit.Visual.Move(this.rulerComponent().element(), { + x:1000, + mode:'relative', + duration:1, +// afterFinish:MochiKit.Base.partial(MochiKit.Style.hideElement, rulerComponentElement) + afterFinish:function () { MochiKit.Style.hideElement(rulerComponentElement); } + }); + }, + + //============================================================================= + + 'addNewDirectLoginRulerSteps': function () { + return MochiKit.Base.concat([ 'LABEL'], this.editDirectLoginRulerSteps()); + + }, + + 'editDirectLoginRulerSteps': function () { + return [ /*'TYPE',*/ 'CONFIGURATION', 'BINDINGS','FAVICON', 'DONE']; + }, + + //------------------------------------------------------------------------- + + 'runWithDirectLogin': function (aDirectLogin, hasJustBeenAdded) { + this._directLogin = aDirectLogin; + this.setDirectLoginHasJustBeenAdded(hasJustBeenAdded); + + return Clipperz.Async.callbacks("DirectLoginWizardController.runWithDirectLogin", [ + MochiKit.Base.method(aDirectLogin, 'label'), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setLabel'), + + MochiKit.Base.method(aDirectLogin, 'favicon'), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setDirectLoginFavicon'), + + MochiKit.Base.method(aDirectLogin, 'bookmarkletConfiguration'), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setBookmarkletConfiguration'), + + MochiKit.Base.method(aDirectLogin, 'bindings'), + MochiKit.Base.method(this, 'setOriginalBindings'), + + MochiKit.Base.method(aDirectLogin, 'record'), + MochiKit.Base.methodcaller('fields'), + MochiKit.Base.values, + MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("Record.directLoginReferences - collectResults", { + 'reference': MochiKit.Base.methodcaller('reference'), + 'label': MochiKit.Base.methodcaller('label'), + 'isHidden': MochiKit.Base.methodcaller('isHidden'), + 'value': MochiKit.Base.methodcaller('value') + }, {trace:false})), + Clipperz.Async.collectAll, + + MochiKit.Base.method(this, 'setRecordFields'), + + MochiKit.Base.partial(MochiKit.Async.succeed, hasJustBeenAdded), + Clipperz.Async.deferredIf("Direct login has just been added", [ + MochiKit.Base.method(this, 'addNewDirectLoginRulerSteps') + ], [ + MochiKit.Base.method(this, 'editDirectLoginRulerSteps') + ]), + MochiKit.Base.method(this, 'showRuler') + ], {trace:false}); + }, + + //----------------------------------------------------------------------------- + + 'checkState': function () { + var enablePrevious; + var enableNext; + + enablePrevious = true; + enableNext = false; + + this.directLoginEditingComponent().disableAllPanels(); + + switch(this.currentStep()) { + case 'LABEL': + this.directLoginEditingComponent().enableLabelField(); + + enableNext = (this.directLoginEditingComponent().label() != ''); + enablePrevious = false; + break; + case 'TYPE': + this.directLoginEditingComponent().enableTypeField(); + + enableNext = true; + enablePrevious = true; + break + case 'CONFIGURATION': + this.directLoginEditingComponent().enableConfigurationField(); + + enableNext = (this.directLoginEditingComponent().bookmarkletConfiguration() != ''); + + if (enableNext == true) { + try { + Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration(this.directLoginEditingComponent().bookmarkletConfiguration()); + this.directLoginEditingComponent().removeHighlightConfigurationSyntaxError(); + } catch (e) { + this.directLoginEditingComponent().highlightConfigurationSyntaxError(); + enableNext = false; + } + } + break; + case 'BINDINGS': + enableNext = MochiKit.Iter.every(this.bindingComponents(), function (aBindingComponent) { return aBindingComponent.selectedValue() != null; }) + this.directLoginEditingComponent().enableBindingFields(); + break; + case 'FAVICON': + enableNext = true; + this.directLoginEditingComponent().enableFaviconField(); + break; + case 'DONE': + enableNext = true; + this.directLoginEditingComponent().enableDonePanel(); + break; + } + + if (this.currentStepIndex() > 0) { + this.enablePrevious(enablePrevious); + } else { + this.enablePrevious(false); + } + this.enableNext(enableNext); + }, + + //----------------------------------------------------------------------------- + + 'setFocus': function () { + switch(this.currentStep()) { + case 'LABEL': + this.directLoginEditingComponent().focusOnLabelElement(); + break; + case 'TYPE': + break; + case 'CONFIGURATION': + this.directLoginEditingComponent().focusOnBookmarkletConfigurationElement(); + break; + case 'BINDINGS': +// this.directLoginEditingComponent().getElement('???').focus(); + break; + case 'FAVICON': + this.directLoginEditingComponent().focusOnFaviconElement(); + break; + case 'DONE': + break; + } + }, + + //============================================================================= + + 'steps': function () { + return this._steps; + }, + + 'setSteps': function (aValue) { + this._steps = aValue; + + this.rulerComponent().setSteps(aValue); + this.resetCurrentStepIndex(); + }, + + 'currentStepIndex': function () { + return this._currentStepIndex; + }, + + 'currentStep': function () { + return this.steps()[this.currentStepIndex()]; + }, + + //============================================================================= + + 'handleExit': function () { + MochiKit.Signal.signal(this, 'exit'); + }, + + 'done': function () { + this.doneWithRuler(); + + Clipperz.Async.callbacks("DirectLoginWizardController.done", [ + MochiKit.Base.method(this.directLoginEditingComponent(), 'label'), + MochiKit.Base.method(this.directLogin(), 'setLabel'), + + MochiKit.Base.method(this.directLoginEditingComponent(), 'bookmarkletConfiguration'), + MochiKit.Base.method(this.directLogin(), 'setBookmarkletConfiguration'), + + // Bindings + MochiKit.Base.method(this.directLoginEditingComponent(), 'bindingComponents'), +// MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.bind(function (aBindingComponent) { + Clipperz.Async.forEach(MochiKit.Base.bind(function (aBindingComponent) { +//console.log("aBindingComponent", aBindingComponent); +// this.directLogin(). + return Clipperz.Async.callbacks("DirectLoginWizardController.done - update directLogin bindings", [ + MochiKit.Base.method(this.directLogin(), 'bindings'), + MochiKit.Base.itemgetter(aBindingComponent.formFieldName()), + MochiKit.Base.methodcaller('setFieldKey', aBindingComponent.selectedValue()) + ], {trace:false}); + }, this)), + + MochiKit.Base.method(this.directLoginEditingComponent(), 'favicon'), + MochiKit.Base.method(this.directLogin(), 'setFavicon'), + + MochiKit.Base.partial(MochiKit.Signal.signal, this, 'done', { + 'directLogin': this.directLogin(), + 'hasJustBeenAdded': this.directLoginHasJustBeenAdded() + }) + ], {trace:false}); + }, + + //============================================================================= + + 'handleMoveBackward': function () { + if (this._currentStepIndex > 0) { + var afterMoveAction; + + this._currentStepIndex --; + afterMoveAction = MochiKit.Base.noop; + + switch(this.currentStep()) { + case 'LABEL': + break; + case 'TYPE': + break; + case 'CONFIGURATION': + break; + case 'BINDINGS': + break; + case 'FAVICON': + break; + case 'DONE': + break; + }; + + this.rulerComponent().moveBackward(afterMoveAction); + } + + if (this._currentStepIndex == 0) { + this.enablePrevious(false); + } + }, + + 'handleMoveForward': function () { + if (this.isNextEnabled()) { + var afterMoveAction; + + this._currentStepIndex ++; + afterMoveAction = MochiKit.Base.noop; + + switch(this.currentStep()) { + case 'LABEL': + break; + case 'TYPE': + break; + case 'CONFIGURATION': + break; + case 'BINDINGS': + this.resetBindingComponents(); + this.resetFormValueComponents(); + + afterMoveAction = MochiKit.Base.partial(Clipperz.Async.callbacks, "DirectLoginWizardController.handleMoveForward - BINDINGS", [ + MochiKit.Base.method(this.directLogin(), 'setBookmarkletConfiguration', this.directLoginEditingComponent().bookmarkletConfiguration()), + + MochiKit.Base.method(this.directLogin(), 'favicon'), + MochiKit.Base.method(this.directLoginEditingComponent(), 'setDirectLoginFavicon'), + + MochiKit.Base.method(this.directLogin(), 'bindings'), + MochiKit.Base.values, + Clipperz.Async.forEach(MochiKit.Base.bind(function (aBinding) { + var bindingComponent; + + bindingComponent = new Clipperz.PM.UI.Web.Components.DirectLoginEditingBindingComponent({ + formFieldName: aBinding.key(), + fields: this.recordFields(), + selectedFieldKey: aBinding.fieldKey() + }); + + this.bindingComponents().push(bindingComponent); + + MochiKit.Signal.connect(bindingComponent, 'bindChange', this, 'handleBindChange', bindingComponent); + this.directLoginEditingComponent().addBindingComponent(bindingComponent); + + }, this)), + + MochiKit.Base.method(this.directLogin(), 'formValues'), + MochiKit.Base.values, + Clipperz.Async.forEach(MochiKit.Base.bind(function (aFormValue) { + var formValueComponent; + + formValueComponent = new Clipperz.PM.UI.Web.Components.DirectLoginEditingFormValueComponent({ + 'formFieldName': aFormValue.key(), + 'fieldOptions': aFormValue.fieldOptions(), + 'initialValue': aFormValue.value() + }); + + this.formValueComponents().push(formValueComponent); + + MochiKit.Signal.connect(formValueComponent, 'formValueChange', this, 'handleFormValueChange', formValueComponent); + this.directLoginEditingComponent().addFormValueComponent(formValueComponent); + }, this)) + + ], {trace:false}); + + break; + case 'FAVICON': + break; + case 'DONE': + this.directLoginEditingComponent().setDoneDescriptionWithKeys({ + '__cardName__': this.cardLabel(), + '__directLoginName__': this.directLoginEditingComponent().label() + }); + break; + }; + + this.rulerComponent().moveForward(afterMoveAction); + }; + }, + + 'handleCursorMoved': function () { + this.checkState(); + this.setFocus(); + }, + + //------------------------------------------------------------------------- + + 'handleChangedValue': function (anEvent) { + this.checkState(); + }, + + //......................................................................... + + 'handleBindChange': function (aDirectLoginEditingBindingComponent) { + var selectedField; + + selectedField = this.recordFieldWithReference(aDirectLoginEditingBindingComponent.selectedValue()); + + return Clipperz.Async.callbacks("DirectLoginWizardController.handleBindChange", [ + MochiKit.Base.method(this.directLogin(), 'bindings'), + MochiKit.Base.itemgetter(aDirectLoginEditingBindingComponent.formFieldName()), + MochiKit.Base.methodcaller('setFieldKey', selectedField['reference']), + function () { + if (selectedField != null) { + aDirectLoginEditingBindingComponent.setFieldValue(selectedField['value']); + aDirectLoginEditingBindingComponent.setIsHidden(selectedField['isHidden']); + } else { + aDirectLoginEditingBindingComponent.setFieldValue(''); + aDirectLoginEditingBindingComponent.setIsHidden(false); + } + }, + MochiKit.Base.method(this, 'checkState') + ], {trace:false}); + }, + + //......................................................................... + + 'handleFormValueChange': function (someOptions) { + return Clipperz.Async.callbacks("DirectLoginWizardController.handleFormValueChange", [ + MochiKit.Base.method(this.directLogin(), 'formValues'), + MochiKit.Base.itemgetter(someOptions['fieldName']), + MochiKit.Base.methodcaller('setValue', someOptions['selectedValue']), + MochiKit.Base.method(this, 'checkState') + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleDirectLoginEditingComponentKeyPressed': function (anEvent) { + if (anEvent.key().string == 'KEY_ENTER') { + if (anEvent.target().nodeName != 'TEXTAREA') { + anEvent.preventDefault(); + this.handleMoveForward(); + } + } else if (anEvent.key().string == 'KEY_TAB') { + this.handleMoveForward(); + if ((anEvent.target().nodeName == 'INPUT') || (anEvent.target().nodeName == 'TEXTAREA')) { + anEvent.preventDefault(); + } + } else if ((anEvent.key().string == 'KEY_ARROW_RIGHT') && (anEvent.modifier().meta == true)) { + this.handleMoveForward(); + } else if ((anEvent.key().string == 'KEY_ARROW_LEFT') && (anEvent.modifier().meta == true)) { + this.handleMoveBackward(); + } else if (anEvent.key().string == 'KEY_ESCAPE') { + anEvent.stop(); + this.handleExit(); + } + }, + + //============================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/DirectLoginsController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/DirectLoginsController.js new file mode 100644 index 0000000..28401a2 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/DirectLoginsController.js @@ -0,0 +1,145 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +/* +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.DirectLoginsController = function() { + Clipperz.PM.UI.Web.Controllers.DirectLoginsController.superclass.constructor.apply(this, arguments); + + return this; +}; + +Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.DirectLoginsController, Clipperz.PM.UI.Web.Controllers.GridController, { + + 'createGrid': function () { + return new Clipperz.PM.UI.Web.Components.GridComponent({columnsManagers: [ + new Clipperz.PM.UI.Web.Components.FaviconColumnManager({ + 'name': 'DirectLogins.favicon', + 'selector': MochiKit.Base.methodcaller('favicon'), + 'cssClass': 'favicon' + }), +// new Clipperz.PM.UI.Web.Components.LinkColumnManager({ + new Clipperz.PM.UI.Web.Components.DirectLoginColumnManager({ + 'name': 'DirectLogins.title', + 'selector': MochiKit.Base.methodcaller('label'), + 'label': 'title', + 'cssClass': 'title', + 'comparator': Clipperz.Base.caseInsensitiveCompare, + 'sortable': true, + 'sorted': 'ASCENDING', + 'actionMethod': MochiKit.Base.methodcaller('runDirectLogin') + }), +// new Clipperz.PM.UI.Web.Components.TextColumnManager({ //should be StrengthColumnManager +// 'label': 'strength', +// 'cssClass': 'title', +// 'selector': MochiKit.Base.methodcaller('label') //should be 'strength' or a strenght evaluation function +// }), + new Clipperz.PM.UI.Web.Components.LinkColumnManager({ + 'name': 'DirectLogins.cardTitle', + 'selector': MochiKit.Base.compose(MochiKit.Base.methodcaller('label'), MochiKit.Base.methodcaller('record')), + 'label': 'card', + 'cssClass': 'cardTitle', + 'comparator': Clipperz.Base.caseInsensitiveCompare, + 'sortable': true, + 'sorted': 'UNSORTED', + 'actionMethod': MochiKit.Base.method(this, 'handleShowCard') + }), +// new Clipperz.PM.UI.Web.Components.TextColumnManager({ //should be StrengthColumnManager +// 'label': 'last access', +// 'cssClass': 'title', +// 'selector': MochiKit.Base.methodcaller('label') +// // 'sortable': true, +// // 'sorted': 'UNSORTED' +// }), +// new Clipperz.PM.UI.Web.Components.TextColumnManager({ +// 'label': 'commands', +// 'cssClass': 'title', +// 'selector': MochiKit.Base.methodcaller('label'), //should be a function for commands display +// }), + new Clipperz.PM.UI.Web.Components.DeleteObjectColumnManager({ + 'name': 'DirectLogins.delete', + 'selector': MochiKit.Base.noop, + 'cssClass': 'delete', +// 'actionMethod': function(anObject, anEvent) { MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'deleteDirectLogin', {objectData:anObject, element:anEvent.src()})} + 'actionMethod': MochiKit.Base.method(this, 'handleDeleteDirectLogin') + }) + ]}); + + }, + + //----------------------------------------------------------------------------- + + 'getRows': function () { + // TODO: relying on user() in GridController, bad code smell :| + return this.user().getDirectLogins(); + }, + + //----------------------------------------------------------------------------- + + 'handleShowCard': function (anObject, anEvent) { + var cardDialogController; + + cardDialogController = new Clipperz.PM.UI.Web.Controllers.CardDialogController({record:anObject.record()}) + cardDialogController.run(anEvent.src()); + }, + + //----------------------------------------------------------------------------- + + 'handleDeleteDirectLogin': function (anObject, anEvent) { + var deferredResult; + var confirmationDialog; + + confirmationDialog = new Clipperz.PM.UI.Common.Components.SimpleMessagePanel({ + title: "Delete DirectLogin", + text: "Do you want to delete …", + type: 'ALERT', + buttons: [ + {text:"Cancel", result:'CANCEL', isDefault:true}, + {text:"Delete", result:'OK'} + ] + }); + + deferredResult = new Clipperz.Async.Deferred("AppController.handleDeleteCard", {trace:false}); +// deferredResult = confirmationDialog.deferredShow({openFromElement:anEvent.src(), onOkCloseToElement:MochiKit.DOM.currentDocument().body, onCancelCloseToElement:anEvent.src()}); + deferredResult.addMethod(confirmationDialog, 'deferredShow', { + 'openFromElement': anEvent.src(), + 'onOkCloseToElement': null, // MochiKit.DOM.currentDocument().body, + 'onCancelCloseToElement': anEvent.src() + }); + deferredResult.addCallback(function () { Clipperz.log("DELETE: " + anObject.toString(), anObject); }); + deferredResult.addErrbackPass(function () { Clipperz.log("skip deletion: " + anObject.toString(), anObject); }); + deferredResult.callback(); + + return deferredResult; + }, + + //----------------------------------------------------------------------------- + __syntaxFix__: "syntax fix" +}); +*/ \ No newline at end of file diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/FilterController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/FilterController.js new file mode 100644 index 0000000..13e02bc --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/FilterController.js @@ -0,0 +1,158 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.FilterController = function(args) { + args = args || {}; + + Clipperz.PM.UI.Web.Controllers.FilterController.superclass.constructor.call(this, args); + + this._filterElements = []; + this._filter = ""; + + this._pendingSearchClicks = 0; + + return this; +}; + + +Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.FilterController, Object, { + + //----------------------------------------------------------------------------- + + 'getFilter': function () { + return this._filter; + }, + + '_setFilter': function (aFilterElement, aFilter) { + if (aFilter != this._filter) { + this._filter = aFilter; + MochiKit.Signal.signal(this, 'filterUpdated', aFilter); + this.updateFilterElements(aFilterElement, aFilter); + } + }, + + 'setFilter': function (aFilter) { + this._setFilter(null, aFilter); + }, + + //----------------------------------------------------------------------------- + + 'filterElements': function () { + return this._filterElements; + }, + + 'registerFilterElement': function (aFilterElement) { +//Clipperz.log("=== FilterController.registerFilterElement", aFilterElement); + this._filterElements.push(aFilterElement); + MochiKit.Signal.connect(aFilterElement, 'onkeydown', this, 'searchClickHandler'); + MochiKit.Signal.connect(aFilterElement, 'onfocus', this, 'searchClickHandler'); + }, + + 'removeFilterElement': function (aFilterElement) { + var i; + var filterElements; + for (i=0; i < filterElements; i++) { + if (filterElements[i] == aFilterElement); + filterElements.splice(i, 1); +// TODO unregister/disconnect filterElement ?? MochiKit.Signal.disconnect(this.grid().filterElement(), 'updateFilter', this.filterController(), 'handleUpdateFilter'); + } + }, + + 'updateFilterElements': function (aSourceElement, aFilterString) { + MochiKit.Iter.forEach(this.filterElements(), + function (aFilterElement) { + if (aFilterElement != aSourceElement) { + aFilterElement.value = aFilterString; + } + } + ); + + if (aSourceElement != null) { + aSourceElement.focus(); + } + }, + + //----------------------------------------------------------------------------- + + 'run': function () { +//Clipperz.log("=== FilterController.run"); + }, + + //----------------------------------------------------------------------------- + + 'pendingSearchClicks': function () { + return this._pendingSearchClicks; + }, + + 'incrementPendingSearchClicks': function () { + this._pendingSearchClicks++; + }, + + 'decrementPendingSearchClicks': function () { + this._pendingSearchClicks--; + }, + + //----------------------------------------------------------------------------- + + 'searchClickHandler': function (anEvent) { + if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ENTER')) { + anEvent.preventDefault(); + } else { + var value; + + if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ESCAPE')) { + value = "" + } else if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ARROW_UP')) { + } else if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ARROW_DOWN')) { + } else { + value = null; + } + + this.incrementPendingSearchClicks(); + MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, "searchClickDeferredHandler", anEvent.src(), value)); + } + }, + + //......................................................................... + + 'searchClickDeferredHandler': function (aFilterElement, aValue) { + if (aValue != null) { + aFilterElement.value = aValue; + } + + this.decrementPendingSearchClicks(); + if (this.pendingSearchClicks()==0) { + this._setFilter(aFilterElement, aFilterElement.value); + } + }, + + //----------------------------------------------------------------------------- + 'syntaxFix': 'syntax fix' +}); \ No newline at end of file diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/GridController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/GridController.js new file mode 100644 index 0000000..740a091 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/GridController.js @@ -0,0 +1,374 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.GridController = function(args) { + args = args || {}; + + Clipperz.PM.UI.Web.Controllers.GridController.superclass.constructor.call(this, args); + + this._grid = null; + this._user = null; + this._sortedColumnManager = null; + this._cachedObjects = null; + this._filterController = args.filterController || null; + + this._deferredDisplaySelectedRowsInvocation = null; + + return this; +}; + +Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.GridController, Object, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.GridController"; + }, + + //----------------------------------------------------------------------------- + + 'createGrid': function () { + throw Clipperz.Base.exception.AbstractMethod; + }, + + 'setupWithGrid': function (aGrid) { + this._grid = aGrid; + + if (this._grid != null) { + MochiKit.Iter.forEach(this.columnsManagers(), function (aColumnManager) { + if (aColumnManager.isSortable()) { + if (aColumnManager.isSorted()) { + this.setSortedColumnManager(aColumnManager); + } + MochiKit.Signal.connect(aColumnManager, 'sort', this, 'handleColumnManagerSort'); + } + MochiKit.Signal.connect(aColumnManager, 'selectRow', this, 'handleColumnManagerSelectRow'); + MochiKit.Signal.connect(aColumnManager, 'unselectRow', this, 'handleColumnManagerUnselectRow'); + }, this); + } + }, + + 'grid': function() { + if (this._grid == null) { + this.setupWithGrid(this.createGrid()); + } + + return this._grid; + }, + + 'filterController': function () { +//Clipperz.log('GridController.filterController >>>', this._filterController); + if (this._filterController == null) { + this._filterController = new Clipperz.PM.UI.Web.Controllers.FilterController(); + } +//Clipperz.log('GridController.filterController <<<', this._filterController); + return this._filterController; + }, + + //----------------------------------------------------------------------------- + + 'columnsManagers': function () { + return this.grid().columnsManagers(); + }, + + 'columnManagerWithName': function (aName) { + var managers; + var result; + + managers = MochiKit.Base.filter(function (aManager) { return aManager.name() == aName; } , this.columnsManagers()); + + if (managers.length == 1) { + result = managers[0]; + } else if (managers.length == 0) { + result = null; + } else { + throw "WTF!!!"; + } + + return result; + }, + + 'sortedColumnManager': function () { + return this._sortedColumnManager; + }, + + 'setSortedColumnManager': function(aValue) { + if (aValue.sorted() != 'UNSORTED') { + this._sortedColumnManager = aValue; + } else { + this._sortedColumnManager = null; + } + }, + + //----------------------------------------------------------------------------- + + 'handleColumnManagerSort': function(aSelectedColumnManager) { + MochiKit.Iter.forEach(this.columnsManagers(), function(aColumnManager) { + if (aSelectedColumnManager != aColumnManager) { + if (aColumnManager.isSortable()) { + aColumnManager.setSorted('UNSORTED'); + } + } + }); + + aSelectedColumnManager.toggleSorting(); + this.setSortedColumnManager(aSelectedColumnManager); + + this.displaySelectedRows(this.filterController().getFilter()); + }, + + 'handleColumnManagerSelectRow': function (aRowObject) { + this.grid().selectRow(aRowObject); + }, + + 'handleColumnManagerUnselectRow': function (aRowObject) { + this.grid().unselectRow(aRowObject); + }, + + //----------------------------------------------------------------------------- + + 'handleFilterUpdated': function (aFilter) { + if (this.grid().isActive()) { + this.displaySelectedRows(aFilter); + } + }, + + //----------------------------------------------------------------------------- + // TODO: relying on user() in GridController, bad code smell :| + // mhh: a controller should have access to business logic object too. Otherwise it will fail its controller role. [Giulio Cesare] + + 'setUser': function(anUser) { + this._user = anUser; + }, + + 'user': function() { + return this._user; + }, + + //----------------------------------------------------------------------------- + + 'run': function(args) { +//Clipperz.log("=== GridController.run"); + var deferredResult; + + this.setUser(args.user); + args.slot.setContent(this.grid()); + this.filterController().registerFilterElement(this.grid().filterElement()); + MochiKit.Signal.connect(this.filterController(), 'filterUpdated', this, 'handleFilterUpdated'); + + return this.displaySelectedRows(); + }, + + //----------------------------------------------------------------------------- + + 'handleGenericError': function(anError) { + var result; + + if (anError instanceof MochiKit.Async.CancelledError) { + result = anError; + } else { +Clipperz.log("## GridController - GENERIC ERROR" + "\n" + "==>> " + anError + " <<==\n" + anError.stack); + result = new MochiKit.Async.CancelledError(anError); + } + + return result; + }, + + //----------------------------------------------------------------------------- + + 'getRows': function () { + throw Clipperz.Base.AbstractMethod; + }, + + //----------------------------------------------------------------------------- + + 'setDeferredDisplaySelectedRowsInvocation': function (aDeferred) { + if (this._deferredDisplaySelectedRowsInvocation != null) { + this._deferredDisplaySelectedRowsInvocation.cancel(); + } + + this._deferredDisplaySelectedRowsInvocation = aDeferred; + }, + + //----------------------------------------------------------------------------- + + 'resetDeferredDisplaySelectedRowsInvocation': function () { + if (this._deferredDisplaySelectedRowsInvocation != null) { + this._deferredDisplaySelectedRowsInvocation.cancel(); + } + }, + + //----------------------------------------------------------------------------- + + '_displaySelectedRows': function (aFilter, someRows) { + var result; + var delay; + + if ((aFilter != null) && (aFilter != '')) { + var filter; + var filterRegExp; + + filter = aFilter.replace(/[^A-Za-z0-9]/g, "\\$&"); + filterRegExp = new RegExp(filter, "i"); + result = MochiKit.Base.filter(function (aCachedResult) { return filterRegExp.test(aCachedResult['_searchableContent'])}, someRows); + delay = 0.002*result.length; + + this.setDeferredDisplaySelectedRowsInvocation(MochiKit.Async.callLater(delay, MochiKit.Base.method(this, "deferredDisplaySelectedRows", result))); + } else { + result = someRows; + + this.resetDeferredDisplaySelectedRowsInvocation(); + this.deferredDisplaySelectedRows(result); + } + + }, + + //----------------------------------------------------------------------------- + + 'deferredDisplaySelectedRows': function (someRows) { + if (this.sortedColumnManager() != null) { + var comparator; + var fieldName; + + fieldName = this.sortedColumnManager().name(); + comparator = this.sortedColumnManager().comparator(); + if (this.sortedColumnManager().sorted() == 'DESCENDING') { + comparator = Clipperz.Base.reverseComparator(comparator); + } + + someRows.sort(MochiKit.Base.partial(function(aKey, aComparator, aObject, bObject){ + return comparator(aObject[aKey], bObject[aKey]); + }, this.sortedColumnManager().name(), comparator)); + } + + this.grid().update(someRows); + this.grid().endSearch(); + }, + + //----------------------------------------------------------------------------- + + 'getCachedValues': function () { + var deferredResult; + + if (this._cachedObjects != null) { + deferredResult = MochiKit.Async.succeed(this._cachedObjects); + } else { + var objectCollectResultsConfiguration; + + objectCollectResultsConfiguration = { + '_rowObject': MochiKit.Async.succeed, + '_reference': MochiKit.Base.methodcaller('reference'), + '_searchableContent': MochiKit.Base.methodcaller('searchableContent') + }; + + MochiKit.Base.map(function (aColumnManager) { + objectCollectResultsConfiguration[aColumnManager.name()] = aColumnManager.selector(); + }, this.columnsManagers()); + + deferredResult = new Clipperz.Async.Deferred("GridController.getCachedValues", {trace:false}); + deferredResult.addMethod(this, 'getRows'); + deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("GridController.getCachedValues - collectResults", objectCollectResultsConfiguration, {trace:false})); + deferredResult.addCallback(Clipperz.Async.collectAll); + deferredResult.addCallback(MochiKit.Base.bind(function (someRows) { + this._cachedObjects = someRows; + return this._cachedObjects; + }, this)); + deferredResult.callback(); + } + + return deferredResult; + }, + + //----------------------------------------------------------------------------- + + 'hasPendingChanges': function () { + return this.user().hasPendingChanges(); + }, + + 'saveChanges': function () { + this._cachedObjects = null; + + return Clipperz.Async.callbacks("GridController.saveChanges", [ + MochiKit.Base.method(this.user(), 'saveChanges'), + MochiKit.Base.method(this, 'focus') + ], {trace:false}); + }, + + 'revertChanges': function () { + return this.user().revertChanges(); + }, + + //----------------------------------------------------------------------------- + + 'displayEmptyContent': function () { + }, + + 'hideEmptyContent': function () { + this.grid().removeNoRowsGridComponent(); + }, + + 'displaySelectedRows': function (aFilter) { + if ((aFilter != null) && (aFilter != '')){ + this.grid().startSearch(); + } + + return Clipperz.Async.callbacks("GridController.displaySelectedrows", [ + MochiKit.Base.method(this, 'getCachedValues'), + MochiKit.Base.itemgetter('length'), + Clipperz.Async.deferredIf("There are some items to show in the grid", [ + MochiKit.Base.method(this, 'hideEmptyContent'), + MochiKit.Base.method(this, 'getCachedValues'), + MochiKit.Base.method(this, '_displaySelectedRows', aFilter) + ], [ + MochiKit.Base.method(this, 'displayEmptyContent'), + MochiKit.Base.method(this.grid(), 'endSearch') + ]) + ], {trace:false}); + }, + + //----------------------------------------------------------------------------- + + 'focus': function () { + return Clipperz.Async.callbacks("GridController.focus", [ + MochiKit.Base.method(this, 'displaySelectedRows', this.filterController().getFilter()), + MochiKit.Base.method(this.grid(), 'focus') + ], {trace:false}) +//*##*/ this.displaySelectedRows(this.filterController().getFilter()); +// this.grid().focus(); + }, + + //============================================================================= + + 'deleteAllCleanTextData': function () { + this._cachedObjects = null; + this.grid().drawEmpty(); + }, + + //============================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/LoginController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/LoginController.js new file mode 100644 index 0000000..d88af41 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/LoginController.js @@ -0,0 +1,259 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.LoginController = function(args) { + this._args = args || {}; + + this._loginPage = null; + + this._newUserWizardController = null; + this._newUserCreationComponent = null; + + return this; +} + +MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.LoginController.prototype, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.LoginController"; + }, + + 'args': function () { + return this._args; + }, + + //----------------------------------------------------------------------------- + + 'loginPage': function() { + if (this._loginPage == null) { + this._loginPage = new Clipperz.PM.UI.Web.Components.LoginPage(); + + MochiKit.Signal.connect(this._loginPage, 'createNewAccountClick', this, 'handleCreateNewAccountClick') + } + + return this._loginPage; + }, + + //----------------------------------------------------------------------------- + + 'run': function(args) { + var slot; + var loginPage; + var loginForm; + + slot = args.slot; + + loginForm = new Clipperz.PM.UI.Web.Components.LoginForm({'autocomplete': this.args()['autocomplete']}); + + slot.setContent(this.loginPage()); + this.loginPage().slotNamed('loginForm').setContent(loginForm); + + MochiKit.Signal.connect(loginForm, 'doLogin', MochiKit.Base.method(this, 'doLogin', loginForm)); + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'doLogin', MochiKit.Base.method(this, 'doLogin', loginForm)); + }, + + //----------------------------------------------------------------------------- + + 'doLogin': function(aLoginForm, anEvent) { + var deferredResult; + var parameters; +// var shouldUseOTP; + var loginProgress; + var user; + var getPassphraseDelegate; + + parameters = anEvent; +// shouldUseOTP = (typeof(parameters.passphrase) == 'undefined'); + + getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, parameters.passphrase); + user = new Clipperz.PM.DataModel.User({'username':parameters.username, 'getPassphraseFunction':MochiKit.Base.method(Clipperz.PM.RunTime.mainController, 'getPassphrase')}); + + loginProgress = new Clipperz.PM.UI.Web.Components.LoginProgress(); + + deferredResult = new Clipperz.Async.Deferred("LoginController.doLogin", {trace:false}); + deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':4}); + deferredResult.addMethod(Clipperz.PM.RunTime.mainController, 'setPassphraseDelegate', getPassphraseDelegate); + deferredResult.addMethod(loginProgress, 'deferredShowModal', {deferredObject:deferredResult, openFromElement:aLoginForm.submitButtonElement()}); + deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); +// if (shouldUseOTP == false) { + deferredResult.addMethod(user, 'login'); +// } else { +// deferredResult.addMethod(user, 'loginUsingOTP', parameters.username, parameters.otp); +// } + deferredResult.addCallback(function(aLoginProgress, res) { + aLoginProgress.disableCancel(); + return res; + }, loginProgress); + deferredResult.addCallback(function () { + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'CARDS_CONTROLLER_DID_RUN', MochiKit.Base.method(loginProgress, 'deferredHideModalAndRemove', {closeToElement:MochiKit.DOM.currentDocument().body})); + }) + deferredResult.addMethod(this, 'userLoggedIn', user, loginProgress, aLoginForm); + deferredResult.addErrback (MochiKit.Base.method(this, 'handleFailedLogin', loginProgress)); + + deferredResult.addErrback (MochiKit.Base.method(loginProgress, 'deferredHideModalAndRemove', {closeToElement:aLoginForm.submitButtonElement()})); + deferredResult.addErrbackPass (MochiKit.Base.method(aLoginForm, 'focusOnPassphraseField')); + deferredResult.addBoth(MochiKit.Base.method(Clipperz.PM.RunTime.mainController, 'removePassphraseDelegate', getPassphraseDelegate)); + deferredResult.callback(); + + MochiKit.Signal.connect(loginProgress, 'cancelEvent', deferredResult, 'cancel'); + + return deferredResult; + }, + + //----------------------------------------------------------------------------- + + 'userLoggedIn': function(aUser) { +//Clipperz.log(">>> LoginController.userLoggedIn"); + MochiKit.Signal.signal(this, 'userLoggedIn', {user: aUser}); +//Clipperz.log("<<< LoginController.userLoggedIn"); + }, + + //========================================================================= + + 'handleCreateNewAccountClick': function (aComponent) { +// return Clipperz.PM.DataModel.User.registerNewAccount("new", "user"); + return Clipperz.Async.callbacks("LoginController.handleCreateNewAccountClick", [ +//' MochiKit.Base.method(this, 'newUserCreationComponent'), +// MochiKit.Base.methodcaller('deferredShowModal', {openFromElement:aComponent}), +// MochiKit.Base.method(this.newUserWizardController(), 'run') + + + MochiKit.Base.method(this, 'newUserCreationComponent'), + Clipperz.Async.forkAndJoin("Async.test succeedingForkedAndWaitDeferrer", [ + MochiKit.Base.method(this.newUserCreationComponent(), 'deferredShowModal', {openFromElement:aComponent, duration:0.5}), + MochiKit.Base.method(this.newUserWizardController(), 'run') + ], {trace:false}), +// MochiKit.Base.method(this.newUserCreationComponent(), 'enableCredentialsField') + ], {trace:false}); + }, + + //----------------------------------------------------------------------------- + + 'newUserWizardController': function () { + if (this._newUserWizardController == null) { + this._newUserWizardController = new Clipperz.PM.UI.Web.Controllers.NewUserWizardController({ + 'newUserCreationComponent': this.newUserCreationComponent() + }) + +// MochiKit.Signal.connect(this._newUserWizardController, 'exit', this, 'handleHideNewUserCreationComponent'); + MochiKit.Signal.connect(this._newUserWizardController, 'done', this, 'handleCompleteNewUserCreationComponent'); + } + + return this._newUserWizardController; + }, + + //------------------------------------------------------------------------- + + 'newUserCreationComponent': function () { + if (this._newUserCreationComponent == null) { + this._newUserCreationComponent = new Clipperz.PM.UI.Web.Components.NewUserCreationComponent(); + } + + return this._newUserCreationComponent; + }, + + 'clearNewUserCreationComponent': function () { + if (this._newUserCreationComponent != null) { + this._newUserCreationComponent.clear(); + } + this._newUserCreationComponent = null; + }, + + //------------------------------------------------------------------------- + + 'handleHideNewUserCreationComponent': function () { + this.clearNewUserCreationComponent(); + }, + + 'handleCompleteNewUserCreationComponent': function (someParameters) { + var deferredResult; + var user; + var newUserCreationComponent; + + user = someParameters.user; + newUserCreationComponent = this.newUserCreationComponent(); + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'CARDS_CONTROLLER_DID_RUN', MochiKit.Base.method(newUserCreationComponent, 'deferredHideModal', {closeToElement:MochiKit.DOM.currentDocument().body})), + + deferredResult = new Clipperz.Async.Deferred("LoginController.handleCompleteNewUserCreationComponent", {trace:false}); + + deferredResult.addCallbackList([ + MochiKit.Base.method(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'), + MochiKit.Base.method(user, 'login'), + MochiKit.Base.method(this, 'userLoggedIn', user), + MochiKit.Base.method(this, 'clearNewUserCreationComponent') + ]); + deferredResult.addErrback(function (aValue) { Clipperz.log("WTF!! Error doing the login after creating a new user" + aValue)}); + deferredResult.callback(); + + return deferredResult; + }, + + + //========================================================================= + + 'handleFailedLogin': function(aLoginProgress, anError) { + var result; + +//console.log("anError", anError); + if (anError instanceof MochiKit.Async.CancelledError) { + result = anError; + } else { + var deferredResult; + +MochiKit.Logging.logError("## MainController - FAILED LOGIN: " + anError); + deferredResult = new MochiKit.Async.Deferred(); + + aLoginProgress.showErrorMessage("failed login"); +// Clipperz.NotificationCenter.register(loginProgress, 'cancelEvent', deferredResult, 'callback'); + MochiKit.Signal.connect(aLoginProgress, 'cancelEvent', deferredResult, 'callback'); + deferredResult.addCallback(MochiKit.Async.fail, anError) + result = deferredResult; + } + + return result; + }, + + 'handleGenericError': function(anError) { + var result; + + if (anError instanceof MochiKit.Async.CancelledError) { + result = anError; + } else { +MochiKit.Logging.logError("## MainController - GENERIC ERROR" + "\n" + "==>> " + anError + " <<==\n" + anError.stack); +//console.log(anError); + result = new MochiKit.Async.CancelledError(anError); + } + + return result; + }, + + //----------------------------------------------------------------------------- + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js new file mode 100644 index 0000000..aa0d6ad --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js @@ -0,0 +1,218 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.MainController = function(args) { + this._args = args; + + // controllers + this._loginController = null; + this._appController = null; + + // components + this._headerComponent = null; + this._pageComponent = null; + this._footerComponent = null; + + this._passphraseDelegateLock = new MochiKit.Async.DeferredLock(); + this._passphraseDelegateLock.acquire(); +//Clipperz.log('MainController init _passphraseDelegateLock', this._passphraseDelegateLock); + this._passphraseDelegate = null; + + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'remoteRequestSent', this, 'handleRemoteRequestSent'); + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'remoteRequestReceived', this, 'handleRemoteRequestReceived'); + + return this; +} + +MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.MainController.prototype, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.MainController"; + }, + + 'args': function () { + return this._args; + }, + + //----------------------------------------------------------------------------- + + 'headerComponent': function() { + if (this._headerComponent == null) { + this._headerComponent = new Clipperz.PM.UI.Web.Components.PageHeader(); + } + + return this._headerComponent; + }, + + 'footerComponent': function() { + if (this._footerComponent == null) { + this._footerComponent = new Clipperz.PM.UI.Web.Components.PageFooter(); + } + + return this._footerComponent; + }, + + //----------------------------------------------------------------------------- + + 'pageComponent': function() { + if (this._pageComponent == null) { + this._pageComponent = new Clipperz.PM.UI.Web.Components.Page({element:MochiKit.DOM.getElement('mainDiv')}); + } + + return this._pageComponent; + }, + + //----------------------------------------------------------------------------- + + 'loginController': function() { + if (this._loginController == null) { + this._loginController = new Clipperz.PM.UI.Web.Controllers.LoginController(this.args()); + + MochiKit.Signal.connect(this._loginController, 'userLoggedIn', this, 'loginControllerUserLoggedInCallback'); + } + + return this._loginController; + }, + + 'appController': function() { + if (this._appController == null) { + this._appController = new Clipperz.PM.UI.Web.Controllers.AppController(); + + MochiKit.Signal.connect(this._appController, 'logout', this, 'handleLogout'); + } + + return this._appController; + }, + + //----------------------------------------------------------------------------- + + 'run': function(shoudShowRegistrationForm) { + this.pageComponent().slotNamed('header').setContent(this.headerComponent()); + this.pageComponent().slotNamed('footer').setContent(this.footerComponent()); + + this.pageComponent().render(); + + this.loginController().run({slot:this.pageComponent().slotNamed('body')}); + + if (shoudShowRegistrationForm) { + MochiKit.Signal.signal(this.loginController().loginPage(), 'createNewAccountClick'); +// this.loginController().handleCreateNewAccountClick(); + } + }, + + //----------------------------------------------------------------------------- + + 'getPassphrase': function () { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("MainController.getPassphrase", {trace:false}); + + deferredResult.acquireLock(this._passphraseDelegateLock); + deferredResult.addMethod(this, 'invokePassphraseDelegate'); + deferredResult.releaseLock(this._passphraseDelegateLock); + deferredResult.callback(); + + return deferredResult; + }, + + //......................................................................... + + 'invokePassphraseDelegate': function () { + return this._passphraseDelegate(); + }, + + 'passphraseDelegateLock': function () { + return this._passphraseDelegateLock; + }, + + //......................................................................... + + 'setPassphraseDelegate': function (aDelegate) { + var shouldReleaseLock; + + shouldReleaseLock = (this._passphraseDelegate == null); + + this._passphraseDelegate = aDelegate; + + if (shouldReleaseLock) { + this._passphraseDelegateLock.release(); + } + }, + + //......................................................................... + + 'removePassphraseDelegate': function (aDelegate) { + if (this._passphraseDelegate == aDelegate) { + this._passphraseDelegate = null; + this._passphraseDelegateLock.acquire(); + } + }, + + //------------------------------------------------------------------------- + + 'loginControllerUserLoggedInCallback': function(anEvent) { +//Clipperz.log(">>> loginControllerUserLoggedInCallback", anEvent); +// this.setUser(anEvent.parameters()['user']); +//console.log("--- loginControllerUserLoggedInCallback - 1"); + +//console.log("--- loginControllerUserLoggedInCallback - 2"); + this.headerComponent().switchToLoggedMode(); + this.appController().run({slot:this.pageComponent().slotNamed('body'), user:anEvent['user']}); +//Clipperz.log("<<< loginControllerUserLoggedInCallback"); + }, + + //----------------------------------------------------------------------------- + + 'handleRemoteRequestSent': function () { +//Clipperz.log("REMOTE REQUEST sent >>>"); + }, + + 'handleRemoteRequestReceived': function () { +//Clipperz.log("REMOTE REQUEST received <<<"); + }, + + //----------------------------------------------------------------------------- + + 'handleLogout': function(anEvent) { + this.exit('logout.html'); + }, + + //----------------------------------------------------------------------------- + + 'exit': function(aPageName) { +//Clipperz.log("### exit " + aPageName); + MochiKit.Async.wait(0).addCallback(function() { + window.location.href = "./" + aPageName + "?ln=" + Clipperz.PM.Strings.selectedLanguage; + }); + }, + + //----------------------------------------------------------------------------- + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js new file mode 100644 index 0000000..28d9d20 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js @@ -0,0 +1,469 @@ +/* + +Copyright 2008-2011 Clipperz Srl + +This file is part of Clipperz's Javascript Crypto Library. +Javascript Crypto Library provides web developers with an extensive +and efficient set of cryptographic functions. The library aims to +obtain maximum execution speed while preserving modularity and +reusability. +For further information about its features and functionalities please +refer to http://www.clipperz.com + +* Javascript Crypto Library 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. + +* Javascript Crypto Library 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 Javascript Crypto Library. If not, see + . + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.NewUserWizardController = function(args) { + this._newUserCreationComponent = args.newUserCreationComponent || Clipperz.Base.exception.raise('MandatoryParameter'); + + MochiKit.Signal.connect(this._newUserCreationComponent, 'changedValue', this, 'handleChangedValue'); + MochiKit.Signal.connect(this._newUserCreationComponent, 'moveForward', this, 'handleMoveForward'); + MochiKit.Signal.connect(this._newUserCreationComponent, 'keyPressed', this, 'handleNewUserCreationComponentKeyPressed'); + + this._rulerComponent = null; + + this._steps = null; + this._currentStepIndex = 0; + this._isNextEnabled = false; + + this._userCreationState = 'IDLE'; // 'IN PROGRESS', 'DONE', 'FAILED' + this._user = null; + return this; +} + +MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.NewUserWizardController.prototype, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.NewUserWizardController"; + }, + + //------------------------------------------------------------------------- + + 'newUserCreationComponent': function () { + return this._newUserCreationComponent; + }, + + //============================================================================= + + 'user': function () { + return this._user; + }, + + 'setUser': function (aValue) { + this._user = aValue; + }, + + //----------------------------------------------------------------------------- + + 'userCreationState': function () { + return this._userCreationState; + }, + + 'setUserCreationState': function (aValue) { +//console.log("+++ NewUserWizardController.setUserCreationState", aValue); + this._userCreationState = aValue; + this.checkState(); + }, + + //============================================================================= + + 'resetCurrentStepIndex': function () { + this._currentStepIndex = 0; + this.rulerComponent().resetStatus({animateTransition:true}); + }, + + //----------------------------------------------------------------------------- + + 'enableNext': function (aValue) { + this.rulerComponent().enableNext(aValue); + this._isNextEnabled = aValue; + }, + + 'isNextEnabled': function () { + return this._isNextEnabled; + }, + + //----------------------------------------------------------------------------- + + 'enablePrevious': function (aValue) { + this.rulerComponent().enablePrevious(aValue); + }, + + //============================================================================= + + 'rulerComponent': function () { + if (this._rulerComponent == null) { + this._rulerComponent = new Clipperz.PM.UI.Web.Components.RulerComponent({ + translationContext:'Wizards.NewUserWizard' + }); + this._rulerComponent.render(); + + MochiKit.Signal.connect(this._rulerComponent, 'exit', this, 'handleExit'); + MochiKit.Signal.connect(this._rulerComponent, 'done', this, 'done'); + MochiKit.Signal.connect(this._rulerComponent, 'moveForward', this, 'handleMoveForward'); + MochiKit.Signal.connect(this._rulerComponent, 'moveBackward', this, 'handleMoveBackward'); + MochiKit.Signal.connect(this._rulerComponent, 'cursorMoved', this, 'handleCursorMoved'); + } + + return this._rulerComponent; + }, + + 'resetRuler': function () { +// if (this._rulerComponent != null) { +// this._rulerComponent.clear(); +// } +// this._rulerComponent = null; + }, + + //----------------------------------------------------------------------------- + + 'showRuler': function (someSteps) { + var rulerElement; + + this.setSteps(someSteps); + + rulerElement = this.rulerComponent().element(); + this.newUserCreationComponent().disableAllPanels(); + + MochiKit.Style.showElement(rulerElement); + MochiKit.Style.setElementPosition(rulerElement, {x:-1000, y:this.newUserCreationComponent().bottomMargin()}); + new MochiKit.Visual.Move(rulerElement, { + x:0, y:this.newUserCreationComponent().bottomMargin(), + mode:'absolute', + duration:0.5, +// afterFinish:MochiKit.Base.method(this, 'handleCursorMoved') + afterFinish:MochiKit.Base.method(this, 'handleRulerShowed') + }); + }, + + //----------------------------------------------------------------------------- + + 'handleRulerShowed':function () { + return Clipperz.Async.callbacks("NewUserWizardController.handlerRulerShowed", [ + MochiKit.Base.method(this.newUserCreationComponent(), 'waitUntilFullyRendered'), + MochiKit.Base.method(this, 'handleCursorMoved') + ], {trace:false}); + }, + + //----------------------------------------------------------------------------- + + 'hideRuler': function () { + new MochiKit.Visual.Move(this.rulerComponent().element(), {x:-1000, mode:'relative', duration:0.5}); + }, + + 'doneWithRuler': function () { + var rulerComponentElement; + + rulerComponentElement = this.rulerComponent().element(); + new MochiKit.Visual.Move(this.rulerComponent().element(), { + x:1000, + mode:'relative', + duration:1, +// afterFinish:MochiKit.Base.partial(MochiKit.Style.hideElement, rulerComponentElement) + afterFinish:function () { MochiKit.Style.hideElement(rulerComponentElement); } + }); + }, + + //============================================================================= + + 'createNewUserRulerSteps': function () { + return [ 'CREDENTIALS', 'CHECK_CREDENTIALS', 'TERMS_OF_SERVICE', 'CREATE_USER'/*, 'LOGIN' */]; + }, + + //------------------------------------------------------------------------- + + 'run': function () { + return Clipperz.Async.callbacks("NewUserWizardController.run", [ + MochiKit.Base.method(this, 'createNewUserRulerSteps'), + MochiKit.Base.method(this, 'showRuler') + ], {trace:false}); + }, + + //----------------------------------------------------------------------------- + + 'checkState': function () { + var enablePrevious; + var enableNext; + + enablePrevious = true; + enableNext = false; + + this.newUserCreationComponent().disableAllPanels(); + + switch(this.currentStep()) { + case 'CREDENTIALS': + this.newUserCreationComponent().enableCredentialsPanel(); + + enableNext = ( + (this.newUserCreationComponent().username() != '') + && + (this.newUserCreationComponent().passphrase() != '') + ); +// enablePrevious = false; + break; + case 'CHECK_CREDENTIALS': + this.newUserCreationComponent().enableCheckCredentialsPanel(); + + enableNext = (this.newUserCreationComponent().passphrase() == this.newUserCreationComponent().rePassphrase()); +// enablePrevious = true; + break + case 'TERMS_OF_SERVICE': + this.newUserCreationComponent().enableTermsOfServicePanel(); + +//console.log("awareOfUnrecoverablePassphrase", this.newUserCreationComponent().awareOfUnrecoverablePassphrase()); +//console.log("readTermsOfService", this.newUserCreationComponent().readTermsOfService()); + enableNext = ( + (this.newUserCreationComponent().awareOfUnrecoverablePassphrase() == 'on') + && + (this.newUserCreationComponent().readTermsOfService() == 'on') + ) + break; + case 'CREATE_USER': +//console.log(">>> CREATE_USER", this.userCreationState()); + this.newUserCreationComponent().enableCreateUserPanel(); + + switch (this.userCreationState()) { + case 'IDLE': + this.setUserCreationState('IN PROGRESS'); + this.preformActualUserRegistration(); + + enablePrevious = false; + enableNext = false; + break; + case 'IN PROGRESS': + enablePrevious = false; + enableNext = false; + break; + case 'DONE': + enablePrevious = false; + enableNext = true; + break; + case 'FAILED': + enablePrevious = true; + enableNext = false; + break; + }; + break; +// case 'LOGIN': +// this.newUserCreationComponent().enableLoginPanel(); +// break; + } + + if (this.currentStepIndex() > 0) { + this.enablePrevious(enablePrevious); + } else { + this.enablePrevious(false); + } + this.enableNext(enableNext); + }, + + //----------------------------------------------------------------------------- + + 'setFocus': function () { + switch(this.currentStep()) { + case 'CREDENTIALS': + this.newUserCreationComponent().focusOnUsernameElement(); + break; + case 'CHECK_CREDENTIALS': + this.newUserCreationComponent().focusOnRePassphraseElement(); + break + case 'TERMS_OF_SERVICE': + break; + case 'CREATE_USER': + break; +// case 'LOGIN': +// break; + } + }, + + //============================================================================= + + 'steps': function () { + return this._steps; + }, + + 'setSteps': function (aValue) { + this._steps = aValue; + + this.rulerComponent().setSteps(aValue); + this.resetCurrentStepIndex(); + }, + + 'currentStepIndex': function () { + return this._currentStepIndex; + }, + + 'currentStep': function () { + return this.steps()[this.currentStepIndex()]; + }, + + //============================================================================= + + 'handleExit': function () { + return Clipperz.Async.callbacks("NewUserWizardController.handleExit", [ +// MochiKit.Base.method(this.newUserCreationComponent(), 'resetContent'), + Clipperz.Async.forkAndJoin("NewUserWizardController.handleExit - fork and join", [ + MochiKit.Base.method(this, 'hideRuler'), + MochiKit.Base.method(this.newUserCreationComponent(), 'deferredHideModal') + ], {trace:false}), + MochiKit.Base.method(this, 'resetRuler'), +// MochiKit.Base.method(this.newUserCreationComponent(), 'reset'), + MochiKit.Base.partial(MochiKit.Signal.signal, this, 'exit') + ], {trace:false}) + }, + + 'done': function () { + this.doneWithRuler(); + MochiKit.Signal.signal(this, 'done', {'user': this.user()}); + }, + + //============================================================================= + + 'handleMoveBackward': function () { + if (this._currentStepIndex > 0) { + var afterMoveAction; + + afterMoveAction = MochiKit.Base.noop; + +//console.log("<-- backward", this.currentStep()); + switch(this.currentStep()) { + case 'CREDENTIALS': + case 'CHECK_CREDENTIALS': + case 'TERMS_OF_SERVICE': + this._currentStepIndex --; + this.rulerComponent().moveBackward(afterMoveAction); + break; + case 'CREATE_USER': + this.setUser(null); + this.newUserCreationComponent().hideAllProgeressStates(); + this.resetCurrentStepIndex(); + this.setUserCreationState('IDLE'); + break; +// case 'LOGIN': +// break; + }; + + } + + if (this._currentStepIndex == 0) { + this.enablePrevious(false); + } + }, + + 'handleMoveForward': function () { + if (this.isNextEnabled()) { + var afterMoveAction; + + this._currentStepIndex ++; + afterMoveAction = MochiKit.Base.noop; + + switch(this.currentStep()) { + case 'CREDENTIALS': + break; + case 'CHECK_CREDENTIALS': + break + case 'TERMS_OF_SERVICE': + break; + case 'CREATE_USER': + break; +// case 'LOGIN': +// break; + }; + + this.rulerComponent().moveForward(afterMoveAction); + }; + }, + + 'handleCursorMoved': function () { +// this.checkState(); +// this.setFocus(); + + return Clipperz.Async.callbacks("NewUserWizardController.handleCursorMoved", [ + MochiKit.Base.method(this.newUserCreationComponent(), 'waitUntilFullyRendered'), + MochiKit.Base.method(this, 'checkState'), + MochiKit.Base.method(this, 'setFocus') + ], {trace:false}); + }, + + //------------------------------------------------------------------------- + + 'handleChangedValue': function (anEvent) { + this.checkState(); + }, + + //------------------------------------------------------------------------- + + 'handleNewUserCreationComponentKeyPressed': function (anEvent) { +//console.log(">>> handleNewUserCreationComponentKeyPressed", anEvent.key().string); + if (anEvent.key().string == 'KEY_ENTER') { + if (anEvent.target().nodeName != 'TEXTAREA') { + anEvent.preventDefault(); + this.handleMoveForward(); + } + } else if (anEvent.key().string == 'KEY_TAB') { + if (anEvent.target() == this.newUserCreationComponent().usernameElement()) { + } else { + this.handleMoveForward(); + if ((anEvent.target().nodeName == 'INPUT') || (anEvent.target().nodeName == 'TEXTAREA')) { + anEvent.preventDefault(); + } + } + } else if ((anEvent.key().string == 'KEY_ARROW_RIGHT') && (anEvent.modifier().meta == true)) { + this.handleMoveForward(); + } else if ((anEvent.key().string == 'KEY_ARROW_LEFT') && (anEvent.modifier().meta == true)) { + this.handleMoveBackward(); + } else if (anEvent.key().string == 'KEY_ESCAPE') { + anEvent.stop(); + this.handleExit(); + } else { + MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, 'checkState')); + } + }, + + //============================================================================= + + 'preformActualUserRegistration': function () { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("NewUSerWizardController.preformActualUserRegistration", {trace:false}); + deferredResult.addMethod(this.newUserCreationComponent(), 'showProgressOnUserCreation'); + deferredResult.addMethod(Clipperz.PM.RunTime.mainController, 'setPassphraseDelegate', MochiKit.Base.method(this.newUserCreationComponent(), 'passphrase')); + deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount, + this.newUserCreationComponent().username(), + MochiKit.Base.method(Clipperz.PM.RunTime.mainController, 'getPassphrase') + ); + deferredResult.addMethod(this, 'setUser'); + deferredResult.addMethod(this.newUserCreationComponent(), 'showUserCreationDone'); + deferredResult.addMethod(this, 'setUserCreationState', 'DONE'); + +// deferredResult.addErrback(MochiKit.Base.method(this.newUserCreationComponent(), 'showUserCreationFailed')); +// deferredResult.addErrback(MochiKit.Base.method(this, 'setUser', null)); +// deferredResult.addErrback(MochiKit.Base.method(this, 'setUserCreationState', 'FAILED')); + deferredResult.addErrback(MochiKit.Base.bind(function (aValue) { + this.newUserCreationComponent().showUserCreationFailed(); + this.setUser(null); + this.setUserCreationState('FAILED'); + }, this)); + deferredResult.callback(); + + return deferredResult; + }, + + //============================================================================= + __syntaxFix__: "syntax fix" +}); -- cgit v0.9.0.2