From 20bea94ab6b91c85b171dcf86baba0a64169d508 Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Fri, 30 Aug 2013 15:56:53 +0000 Subject: First release of /delta version --- (limited to 'frontend/delta/js/Clipperz/PM/UI/MainController.js') diff --git a/frontend/delta/js/Clipperz/PM/UI/MainController.js b/frontend/delta/js/Clipperz/PM/UI/MainController.js new file mode 100644 index 0000000..da7540e --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/UI/MainController.js @@ -0,0 +1,491 @@ +/* + +Copyright 2008-2013 Clipperz Srl + +This file is part of Clipperz, the online password manager. +For further information about its features and functionalities please +refer to http://www.clipperz.com. + +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + +* You should have received a copy of the GNU Affero General Public + License along with Clipperz. If not, see http://www.gnu.org/licenses/. + +*/ + +Clipperz.Base.module('Clipperz.PM.UI'); + +Clipperz.PM.UI.MainController = function() { + var pages; + + this._proxy = null; + this._user = null; + this._filter = ''; + +// this._currentPage = 'loadingPage'; + + this._pageStack = ['loadingPage']; + this._overlay = new Clipperz.PM.UI.Components.Overlay(); + pages = { + 'loginPage': new Clipperz.PM.UI.Components.LoginForm(), + 'registrationPage': new Clipperz.PM.UI.Components.RegistrationWizard(), + 'cardListPage': new Clipperz.PM.UI.Components.CardList(), + 'cardDetailPage': new Clipperz.PM.UI.Components.CardDetail({card: {}}), + 'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''}) + }; + + MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages)); + this._pages = pages; + this.registerForNotificationCenterEvents(); + + return this; +} + +MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, { + + toString: function () { + return "Clipperz.PM.UI.MainController"; + }, + + //========================================================================= + + overlay: function () { + return this._overlay; + }, + + loginForm: function () { + return this._loginForm; + }, + + registrationWizard: function () { + return this._registrationWizard; + }, + + //========================================================================= + + isOnline: function() { + return navigator.onLine; + }, + + hasLocalData: function() { + return false; + }, + + loginMode: function () { + // PIN is set using this command: + // Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'}); + + return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS'; + }, + + //========================================================================= + + pages: function () { + return this._pages; + }, + + pageStack: function () { + return this._pageStack; + }, + + //========================================================================= + + selectInitialProxy: function () { + if (this.isOnline()) { + this._proxy = Clipperz.PM.Proxy.defaultProxy; + } else { + if (this.hasLocalData()) { + this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false}); + } else { + this.showOfflineError(); + } + } + }, + + proxy: function () { + return this._proxy; + }, + + //========================================================================= + + registerForNotificationCenterEvents: function () { + var events = ['doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack', 'showRecord', 'searchCards', 'runDirectLogin']; + var self = this; + + MochiKit.Base.map(function (anEvent) { + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent)); + }, events); + +// MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack')); + MochiKit.Signal.connect(window, 'onbeforeunload', MochiKit.Base.method(this, 'shouldExitApp')); + }, + + //------------------------------------------------------------------------- + + run: function (parameters) { + var shouldShowRegistrationForm; + + this.selectInitialProxy(); + shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && this.proxy().canRegisterNewUsers(); + this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()}); + + if (shouldShowRegistrationForm) { + this.showRegistrationForm(); + } else { + this.showLoginForm(); + } + this.overlay().done("", 0.5); + }, + + //------------------------------------------------------------------------- + + showLoginForm: function () { + var loginFormPage; + + loginFormPage = this.pages()['loginPage']; + loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()}); + this.moveInPage(this.currentPage(), 'loginPage'); + MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus')); + }, + + showRegistrationForm: function () { + var currentPage; + var registrationPage; + + currentPage = this.currentPage(); + registrationPage = this.pages()['registrationPage']; + this.setCurrentPage('loginPage'); + registrationPage.setProps({}); + this.moveInPage(currentPage, 'registrationPage'); + MochiKit.Async.callLater(0.5, MochiKit.Base.method(registrationPage, 'setInitialFocus')); + }, + + //========================================================================= + + doLogin: function (event) { + var credentials; + var getPassphraseDelegate; + var user; + + user = null; + + this.overlay().show("logging in"); + this.pages()['loginPage'].setProps({disabled:true}); + + if ('pin' in event) { + credentials = Clipperz.PM.PIN.credentialsWithPIN(event['pin']); + } else { + credentials = event; + } + getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase); + user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate}); + + deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false}); + deferredResult.addCallback(MochiKit.Async.wait, 0.1); + deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); + deferredResult.addMethod(user, 'login'); + deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount'); + deferredResult.addMethod(this, 'setUser', user); + +// deferredResult.addMethod(this, 'setupApplication'); + deferredResult.addMethod(this, 'runApplication'); + deferredResult.addMethod(this.overlay(), 'done', "", 1); + deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); + deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) { + if (anError['isPermanent'] != true) { + this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()}); + this.pages()['loginPage'].setInitialFocus(); + } + return anError; + }, this, event)) + deferredResult.callback(); + + return deferredResult; + }, + + //------------------------------------------------------------------------- + + registerNewUser: function (credentials) { + var deferredResult; + + this.overlay().show("creating user"); + + this.pages()['registrationPage'].setProps({disabled:true}); + deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false}); + deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount, + credentials['username'], + MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase']) + ); + deferredResult.addMethod(this, 'doLogin', credentials); + deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); + deferredResult.addErrback(MochiKit.Base.bind(function (anError) { + if (anError['isPermanent'] != true) { + this.pages()['registrationPage'].setProps({disabled:false}); + this.pages()['registrationPage'].setInitialFocus(); + } + return anError; + }, this)); + + deferredResult.callback(); + + return deferredResult; + + }, + + //------------------------------------------------------------------------- + + user: function () { + return this._user; + }, + + setUser: function (aUser) { + this._user = aUser; + return this._user; + }, + + //========================================================================= + + allCardInfo: function () { + var deferredResult; + var cardInfo; + + cardInfo = { + '_rowObject': MochiKit.Async.succeed, + '_reference': MochiKit.Base.methodcaller('reference'), + '_searchableContent': MochiKit.Base.methodcaller('searchableContent'), + 'label': MochiKit.Base.methodcaller('label'), + 'favicon': MochiKit.Base.methodcaller('favicon') + }; + + deferredResult = new Clipperz.Async.Deferred('MainController.allCardInfo', {trace:false}); + deferredResult.addMethod(this.user(), 'getRecords'); + deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false})); + deferredResult.addCallback(Clipperz.Async.collectAll); + deferredResult.callback(); + + return deferredResult; + }, + + filterCards: function (someCardInfo) { + var filter; + var filterRegExp; + var result; + + filter = this.filter().replace(/[^A-Za-z0-9]/g, "\\$&"); + filterRegExp = new RegExp(filter, "i"); + result = MochiKit.Base.filter(function (aCardInfo) { return filterRegExp.test(aCardInfo['_searchableContent'])}, someCardInfo); + + return result; + }, + + sortCards: function (someCardInfo) { + return someCardInfo.sort(Clipperz.Base.caseInsensitiveKeyComparator('label')); + }, + + showRecordList: function () { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred('MainController.showRecordList', {trace:false}); + deferredResult.addMethod(this, 'allCardInfo'); + deferredResult.addMethod(this, 'filterCards'); + deferredResult.addMethod(this, 'sortCards'); + deferredResult.addCallback(MochiKit.Base.bind(function (someRecordInfo) { + this.pages()['cardListPage'].setProps({cardList: someRecordInfo}); + }, this)); + deferredResult.callback(); + + return deferredResult; + }, + + filter: function () { + return this._filter; + }, + + setFilter: function (aValue) { + this._filter = aValue; + }, + + searchCards: function (someParameters) { +//console.log("SEARCH CARDS", someParameters); + this.setFilter(someParameters); + this.showRecordList(); + }, + + //========================================================================= + + runApplication: function () { + MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack')); + this.moveInPage(this.currentPage(), 'cardListPage'); + return this.showRecordList(); + }, + + showRecord: function (aRecordReference) { +//console.log("Show Record", aRecordReference); + var deferredResult; + + this.pages()['cardListPage'].setProps({selectedCard:aRecordReference}); + deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false}); +// deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']); + deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); + deferredResult.addMethodcaller('content'); + deferredResult.addCallback(MochiKit.Base.bind(function (aCard) { +//console.log("CARD DETAILS", aCard); + this.pages()['cardDetailPage'].setProps({card: aCard}); + this.pages()['cardListPage'].setProps({selectedCard: null}); + }, this)); + deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true); + deferredResult.callback(); + + return deferredResult; + }, + + runDirectLogin: function (someParameters) { +console.log("RUN DIRECT LOGIN", someParameters); + var deferredResult; + +// this.pages()['cardListPage'].setProps({selectedCard:aRecordReference}); + deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false}); +// deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']); + deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']); + deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']); + deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin); + deferredResult.callback(); + + return deferredResult; + }, + + shouldExitApp: function (anEvent) { +console.log("SHOULD EXIT APP"); + anEvent.preventDefault(); + anEvent.stopPropagation(); + }, + + //========================================================================= + + genericErrorHandler: function (anEvent, anError) { + var errorMessage; + var result; + + result = anError; + errorMessage = "login failed"; + + if (anError['isPermanent'] === true) { + this.pages()['errorPage'].setProps({message:anError.message}); + this.moveInPage(this.currentPage(), 'errorPage'); + errorMessage = "failure"; + } else { + if ('pin' in anEvent) { + errorCount = Clipperz.PM.PIN.recordFailedAttempt(); + if (errorCount == -1) { + errorMessage = "PIN resetted"; + } + } + } + this.overlay().failed(errorMessage, 1); + + return result; + }, + + //========================================================================= + + slidePage: function (fromPage, toPage, direction) { + var fromPosition; + var toPosition; + + if (direction == "LEFT") { + fromPosition = 'right'; + toPosition = 'left' + } else { + fromPosition = 'left'; + toPosition = 'right' + } + + MochiKit.DOM.addElementClass(fromPage, toPosition + ' transition'); + + MochiKit.DOM.addElementClass(toPage, fromPosition); + MochiKit.DOM.removeElementClass(toPage, toPosition); + MochiKit.DOM.addElementClass(toPage, 'transition'); + MochiKit.Async.callLater(0.1, function () { + MochiKit.DOM.removeElementClass(toPage, fromPosition); + }) + + MochiKit.Async.callLater(0.5, function () { + MochiKit.DOM.removeElementClass(fromPage, 'transition'); + MochiKit.DOM.removeElementClass(toPage, 'transition'); + }) + }, + + rotateInPage: function (fromPage, toPage) { + // Broken! :( + MochiKit.DOM.addElementClass(MochiKit.DOM.getElement('mainDiv'), 'show-right'); + }, + + //......................................................................... + + goBack: function () { + var fromPage; + var toPage; + + fromPage = this.pageStack().shift(); + toPage = this.currentPage(); + this.pages()[toPage].setProps({}); + this.moveOutPage(fromPage, toPage); + }, + + historyGoBack: function (anEvent) { + anEvent.preventDefault(); + anEvent.stopPropagation(); + this.goBack(); + }, + + currentPage: function () { + return this.pageStack()[0]; + }, + + setCurrentPage: function (aPage) { + this.pageStack().unshift(aPage); + }, + + moveInPage: function (fromPage, toPage, addToHistory) { + var shouldAddItemToHistory; + + shouldAddItemToHistory = typeof(addToHistory) == 'undefined' ? false : addToHistory; + + this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'LEFT'); + this.setCurrentPage(toPage); + + if (shouldAddItemToHistory) { +//console.log("ADD ITEM TO HISTORY"); +//console.log("ADD ITEM TO HISTORY - window", window); +//console.log("ADD ITEM TO HISTORY - window.history", window.history); + window.history.pushState({'fromPage': fromPage, 'toPage': toPage}); +//# window.history.pushState(); +//console.log("ADDED ITEM TO HISTORY"); + } else { +//console.log("Skip HISTORY"); + } + }, + + moveOutPage: function (fromPage, toPage) { + this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT'); + this.setCurrentPage(toPage); + }, + + //========================================================================= +/* + wrongAppVersion: function (anError) { +// this.pages()['errorPage'].setProps({message:anError.message}); +// this.moveInPage('errorPage', this.currentPage()); + }, +*/ + //========================================================================= + __syntaxFix__: "syntax fix" +}); -- cgit v0.9.0.2