Bug 999480 - Panel to use a router & templated views, r=Standard8

This commit is contained in:
Nicolas Perriault 2014-05-29 21:13:45 +01:00
parent b148744fb0
commit c7eeff1458
3 changed files with 106 additions and 66 deletions

View File

@ -7,21 +7,42 @@
Components.utils.import("resource://gre/modules/Services.jsm");
var loop = loop || {};
loop.panel = (function(mozL10n) {
loop.panel = (function(_, mozL10n) {
"use strict";
var baseServerUrl = Services.prefs.getCharPref("loop.server"),
panelView,
sharedViews = loop.shared.views,
// aliasing translation function as __ for concision
__ = mozL10n.get;
/**
* Panel view.
*
* XXX view layout changes should be handled by a router really.
* Panel router.
* @type {loop.shared.router.BaseRouter}
*/
var PanelView = Backbone.View.extend({
el: "#default-view",
var router;
/**
* Panel view.
*/
var PanelView = sharedViews.BaseView.extend({
template: _.template([
'<div class="description">',
' <p data-l10n-id="get_link_to_share"></p>',
'</div>',
'<div class="action">',
' <p class="invite">',
' <input type="text" name="caller" data-l10n-id="caller">',
' <a class="get-url btn btn-success disabled" href=""',
' data-l10n-id="get_a_call_url"></a>',
' </p>',
' <p class="result hide">',
' <input id="call-url" type="url" readonly>',
' <a class="go-back btn btn-info" href="" data-l10n-id="new_url"></a>',
' </p>',
'</div>',
].join("")),
className: "share generate-url",
events: {
"keyup input[name=caller]": "changeButtonState",
@ -29,18 +50,23 @@ loop.panel = (function(mozL10n) {
"click a.go-back": "goBack"
},
initialize: function() {
initialize: function(options) {
options = options || {};
if (!options.notifier) {
throw new Error("missing required notifier");
}
this.notifier = options.notifier;
this.client = new loop.shared.Client({
baseServerUrl: baseServerUrl
});
this.notifier = new loop.shared.views.NotificationListView({
el: this.$(".messages")
}).render();
},
getNickname: function() {
return this.$("input[name=caller]").val();
},
getCallUrl: function(event) {
event.preventDefault();
var nickname = this.$("input[name=caller]").val();
var callback = function(err, callUrl) {
if (err) {
this.notifier.errorL10n("unable_retrieve_url");
@ -49,7 +75,7 @@ loop.panel = (function(mozL10n) {
this.onCallUrlReceived(callUrl);
}.bind(this);
this.client.requestCallUrl(nickname, callback);
this.client.requestCallUrl(this.getNickname(), callback);
},
goBack: function(event) {
@ -76,16 +102,29 @@ loop.panel = (function(mozL10n) {
}
});
var PanelRouter = loop.shared.router.BaseRouter.extend({
routes: {
"": "home"
},
home: function() {
this.loadView(new PanelView({notifier: this._notifier}));
}
});
/**
* Panel initialisation.
*/
function init() {
panelView = new PanelView();
panelView.render();
router = new PanelRouter({
notifier: new sharedViews.NotificationListView({el: "#messages"})
});
Backbone.history.start();
}
return {
init: init,
PanelView: PanelView
PanelView: PanelView,
PanelRouter: PanelRouter
};
})(document.mozL10n);
})(_, document.mozL10n);

View File

@ -9,29 +9,11 @@
<link rel="stylesheet" type="text/css" href="shared/css/common.css">
<link rel="stylesheet" type="text/css" href="shared/css/panel.css">
</head>
<body onload="loop.panel.init();">
<!-- XXX (n1k0): i10n tbd later as these are temporary texts. -->
<div id="default-view" class="share generate-url">
<div class="description">
<p data-l10n-id="get_link_to_share">
Get a link to share with a friend to Video Chat.
</p>
</div>
<div class="action">
<div class="messages"></div>
<p class="invite">
<input type="text" name="caller" data-l10n-id="caller">
<a class="get-url btn btn-success disabled" href=""
data-l10n-id="get_a_call_url">Get a call url</a>
</p>
<p class="result hide">
<input id="call-url" type="url" readonly>
<a class="go-back btn btn-info" href="" data-l10n-id="new_url">
New url
</a>
</p>
</div>
</div>
<body class="panel" onload="loop.panel.init();">
<div id="messages"></div>
<div id="main"></div>
<!-- XXX (adam): Should we import our own version of Webl10n?
What we have here is a copy of the version from pdf.js
@ -46,6 +28,7 @@
<script type="text/javascript" src="shared/libs/backbone-1.1.2.js"></script>
<script type="text/javascript" src="shared/js/client.js"></script>
<script type="text/javascript" src="shared/js/models.js"></script>
<script type="text/javascript" src="shared/js/router.js"></script>
<script type="text/javascript" src="shared/js/views.js"></script>
<script type="text/javascript" src="js/panel.js"></script>
</body>

View File

@ -9,7 +9,7 @@ var expect = chai.expect;
describe("loop.panel", function() {
"use strict";
var sandbox, fakeXHR, requests = [];
var sandbox, notifier, fakeXHR, requests = [];
beforeEach(function() {
sandbox = sinon.sandbox.create();
@ -19,6 +19,14 @@ describe("loop.panel", function() {
fakeXHR.xhr.onCreate = function (xhr) {
requests.push(xhr);
};
notifier = {
clear: sandbox.spy(),
notify: sandbox.spy(),
warn: sandbox.spy(),
warnL10n: sandbox.spy(),
error: sandbox.spy(),
errorL10n: sandbox.spy()
};
});
afterEach(function() {
@ -26,34 +34,46 @@ describe("loop.panel", function() {
sandbox.restore();
});
describe("loop.panel.PanelRouter", function() {
describe("#constructor", function() {
it("should require a notifier", function() {
expect(function() {
new loop.panel.PanelRouter();
}).to.Throw(Error, /missing required notifier/);
});
});
describe("constructed", function() {
var router;
beforeEach(function() {
router = new loop.panel.PanelRouter({notifier: notifier});
sandbox.stub(router, "loadView");
});
describe("#home", function() {
it("should load the PanelView", function() {
router.home();
sinon.assert.calledOnce(router.loadView);
sinon.assert.calledWithExactly(router.loadView,
sinon.match.instanceOf(loop.panel.PanelView));
});
});
});
});
describe("loop.panel.PanelView", function() {
beforeEach(function() {
$("#fixtures").append([
'<div id="default-view" class="share generate-url">',
' <div class="description">',
' <p>Get a link to share with a friend to Video Chat.</p>',
' </div>',
' <div class="action">',
' <div class="messages"></div>',
' <p class="invite">',
' <input type="text" placeholder="Nickname of the future caller"',
' name="caller" value="foo"/>',
' <a class="get-url" href="">Get a call url</a>',
' </p>',
' <p class="result hide">',
' <input id="call-url" type="url" readonly>',
' <a class="get-url" href="">Renew</a>',
' </p>',
' </div>',
'</div>'
].join(""));
$("#fixtures").append('<div id="messages"></div><div id="main"></div>');
});
describe("#getCallUrl", function() {
it("should request a call url to the server", function() {
var requestCallUrl = sandbox.stub(loop.shared.Client.prototype,
"requestCallUrl");
var view = new loop.panel.PanelView();
var view = new loop.panel.PanelView({notifier: notifier});
sandbox.stub(view, "getNickname").returns("foo");
view.getCallUrl({preventDefault: sandbox.spy()});
@ -66,8 +86,7 @@ describe("loop.panel", function() {
loop.shared.Client.prototype, "requestCallUrl", function(_, cb) {
cb("fake error");
});
var view = new loop.panel.PanelView();
sandbox.stub(view.notifier, "errorL10n");
var view = new loop.panel.PanelView({notifier: notifier});
view.getCallUrl({preventDefault: sandbox.spy()});
@ -79,7 +98,7 @@ describe("loop.panel", function() {
describe("#onCallUrlReceived", function() {
it("should update the text field with the call url", function() {
var view = new loop.panel.PanelView();
var view = new loop.panel.PanelView({notifier: notifier});
view.render();
view.onCallUrlReceived("http://call.me/");
@ -88,8 +107,7 @@ describe("loop.panel", function() {
});
it("should reset all pending notifications", function() {
var view = new loop.panel.PanelView().render();
sandbox.stub(view.notifier, "clear");
var view = new loop.panel.PanelView({notifier: notifier}).render();
view.onCallUrlReceived("http://call.me/");