Permalink
Browse files

Bug 810153 - Account creation now blocks until calendar sync.

General bug fixes, improvements to the sync controller.
  • Loading branch information...
1 parent 69bbfcf commit b664b4cc74a64436e6a52afa2155481f697520ff @lightsofapollo lightsofapollo committed Dec 4, 2012
View
@@ -20,6 +20,7 @@
<link rel="stylesheet" type="text/css" href="/shared/style/confirm.css" />
<link rel="stylesheet" type="text/css" href="/shared/style/switches.css" />
<link rel="stylesheet" type="text/css" href="/shared/style/status.css" />
+ <link rel="stylesheet" type="text/css" href="/shared/style_unstable/progress_activity.css" />
<script src="/js/mozalarm_shim.js" type="text/javascript" charset="utf-8"></script>
@@ -350,6 +351,12 @@ <h1 data-l10n-id="add-event-header">
<h1 data-l10n-id="account-header">Account</h1>
</header>
+
+ <section class="during-progress">
+ <p data-l10n-id="modify-account-setting-up">SeTtiNg uP ACcOunt</p>
+ <progress class="small"></progress>
+ </section>
+
<form>
<fieldset>
<ol>
@@ -369,13 +376,11 @@ <h1 data-l10n-id="account-header">Account</h1>
</ol>
</fieldset>
</form>
-
- <section role="status">
- <p class="errors"></p>
- </section>
-
- <div class="during-progress">
- </div>
+
+ <section role="status">
+ <p class="errors"></p>
+ </section>
+
<a data-l10n-id="remove-account-data" role="button" href="#remove-account-dialog" class="danger delete-record">
Remove Local Data
View
@@ -24,6 +24,10 @@ Calendar.App = (function(window) {
CreateAccount: [
{type: 'Templates', name: 'Account'}
],
+ ModifyAccount: [
+ {type: 'Utils', name: 'AccountCreation'},
+ {type: 'Style', name: 'ModifyAccountView'}
+ ],
Day: [
{type: 'Views', name: 'DayChild'},
{type: 'Views', name: 'TimeParent'}
@@ -165,7 +169,6 @@ Calendar.App = (function(window) {
this.dateFormat = navigator.mozL10n.DateTimeFormat();
- this.syncController.observe();
this.timeController.observe();
this.alarmController.observe();
@@ -10,116 +10,102 @@ Calendar.ns('Controllers').Sync = (function() {
*/
function Sync(app) {
this.app = app;
+ this.pending = 0;
+
Calendar.Responder.call(this);
}
Sync.prototype = {
__proto__: Calendar.Responder.prototype,
- observe: function() {
- var self = this;
- var account = this.app.store('Account');
+ _incrementPending: function() {
+ if (!this.pending)
+ this.emit('syncStart');
- // used instead of bind for testing reasons.
- account.on('add', function(id, data) {
- self.emit('sync start');
- self._syncAccount(data, function() {
- self.emit('sync complete');
- });
- });
+ this.pending++;
+ },
+
+ _resolvePending: function() {
+ if (!(--this.pending)) {
+ this.emit('syncComplete');
+ }
},
/**
* Sync all accounts, calendars, events.
+ * There is no callback for all intentionally.
+ *
+ * Use:
+ *
+ * controller.once('syncComplete', cb);
+ *
*/
- sync: function(callback) {
- var key;
- var self = this;
+ all: function() {
var account = this.app.store('Account');
- var pending = 0;
- var errorList = [];
-
- function next(err) {
- if (err) {
- errorList.push(err);
- }
-
- if (!(--pending)) {
- if (callback) {
- if (errorList.length) {
- callback(errorList);
- } else {
- callback(null);
- }
- }
- self.emit('sync complete');
- }
- }
-
- this.emit('sync start');
-
- for (key in account.cached) {
- pending++;
- this._syncAccount(
- account.cached[key], next
- );
- }
- if (!pending) {
- callback();
- this.emit('sync complete');
+ for (var key in account.cached) {
+ this.account(account.cached[key]);
}
},
- _syncAccount: function(model, callback) {
+ /**
+ * Initiates a sync for a single calendar.
+ *
+ * @param {Object} account parent of calendar.
+ * @param {Object} calendar specific calendar to sync.
+ * @param {Function} [callback] optional callback.
+ */
+ calendar: function(account, calendar, callback) {
+ var store = this.app.store('Calendar');
var self = this;
- var account = this.app.store('Account');
- var calendar = this.app.store('Calendar');
- account.sync(model, function(err) {
- if (err) {
- //TODO: Implement error handling to show
- // UI to change user/password, etc..
+ this._incrementPending();
+ store.sync(account, calendar, function(err) {
+ self._resolvePending();
+ if (callback)
callback(err);
- return;
- }
+ });
+ },
- var pending = 0;
- var cals = calendar.remotesByAccount(
- model._id
- );
+ /**
+ * Initiates a sync of a single account and all
+ * associated calendars (calendars that exist after
+ * the full sync of the account itself).
+ *
+ * @param {Object} account sync target.
+ * @param {Function} [callback] optional callback.
+ */
+ account: function(account, callback) {
+ var accountStore = this.app.store('Account');
+ var calendarStore = this.app.store('Calendar');
- var key;
- var errorList = [];
+ var self = this;
- function next(err) {
- if (err) {
- errorList.push(err);
- }
+ this._incrementPending();
+ accountStore.sync(account, function(err) {
+ // find all calendars
+ var calendars = calendarStore.remotesByAccount(
+ account._id
+ );
+
+ var pending = 0;
+ function next() {
if (!(--pending)) {
- if (errorList.length) {
- callback(errorList);
- } else {
- callback(null);
- }
+ self._resolvePending();
+
+ if (callback)
+ callback();
}
}
- for (key in cals) {
+ for (var key in calendars) {
pending++;
- calendar.sync(
- model,
- cals[key],
- next
- );
+ self.calendar(account, calendars[key], next);
}
});
}
-
};
return Sync;
-
}());
-
@@ -149,8 +149,8 @@ Calendar.ns('Controllers').Time = (function() {
// handle cache pause/resume
var sync = this.app.syncController;
- sync.on('sync start', this);
- sync.on('sync complete', this);
+ sync.on('syncStart', this);
+ sync.on('syncComplete', this);
// XXX: case that the event name is so generic
// we handle it here directly.
@@ -454,10 +454,10 @@ Calendar.ns('Controllers').Time = (function() {
var type;
switch (event.type) {
- case 'sync start':
+ case 'syncStart':
this.cacheLocked = true;
break;
- case 'sync complete':
+ case 'syncComplete':
this.cacheLocked = false;
this.purgeCache();
break;
View
@@ -411,7 +411,7 @@
this.once('loaded', function() {
if ('syncController' in Calendar.App && navigator.onLine) {
- Calendar.App.syncController.sync(function() {
+ Calendar.App.syncController.all(function() {
debug('begin resync after reset');
});
} else {
@@ -624,6 +624,11 @@ Calendar.ns('Service').Caldav = (function() {
}
function handleResponse(url, data) {
+ if (!data) {
+ // throw some error;
+ console.log('Could not sync: ', url);
+ return;
+ }
var etag = data.getetag.value;
if (url in cache) {
// don't need to track this for missing events.
@@ -0,0 +1,88 @@
+Calendar.ns('Utils').AccountCreation = (function() {
+
+ /**
+ * Helper class to create accounts.
+ * Emits events during the process of
+ * creation to allow views to hook into
+ * the full cycle while further separating
+ * this logic from their own.
+ *
+ *
+ * Events:
+ *
+ * - authorize
+ * - calendar sync
+ *
+ *
+ * @param {Calendar.App} app instance of app.
+ */
+ function AccountCreation(app) {
+ this.app = app || Calendar.App;
+
+ Calendar.Responder.call(this);
+ }
+
+ AccountCreation.prototype = {
+ __proto__: Calendar.Responder.prototype,
+
+ /**
+ * Sends a request to create an account.
+ *
+ * @param {Calendar.Models.Account} model account details.
+ * @param {Function} callback fired when entire transaction is complete.
+ */
+ send: function(model, callback) {
+ var self = this;
+ var accountStore = this.app.store('Account');
+ var calendarStore = this.app.store('Calendar');
+
+ // begin by persisting the account
+ accountStore.verifyAndPersist(model, function(accErr, id, result) {
+
+ if (accErr) {
+ // we bail when we cannot create the account
+ // but also give custom error events.
+ self.emit('authorizeError', accErr);
+ callback(accErr);
+ return;
+ }
+
+
+ self.emit('authorize', result);
+
+ // finally sync the account so when
+ // we exit the request the user actually
+ // has some calendars. This should not take
+ // too long (compared to event sync).
+ accountStore.sync(result, function(syncErr) {
+ if (syncErr) {
+ self.emit('calendarSyncError', syncErr);
+ callback(syncErr);
+ return;
+ }
+
+ self.emit('calendarSync');
+
+ // begin sync of calendars
+ var calendars = calendarStore.remotesByAccount(
+ result._id
+ );
+
+ // note we don't wait for any of this to complete
+ // we just begin the sync and let the event handlers
+ // on the sync controller do the work.
+ for (var key in calendars) {
+ self.app.syncController.calendar(
+ result,
+ calendars[key]
+ );
+ }
+
+ callback(null, result);
+ });
+ });
+ }
+ };
+
+ return AccountCreation;
+}());
Oops, something went wrong.

0 comments on commit b664b4c

Please sign in to comment.