# HG changeset patch # User Atul Varma # Date 1277506815 25200 # Node ID 03c5651a371e85138e6ca44db19c7e953d7140ad # Parent 3197696debbe857f388a0620a84f2b0701ebc2cc added banner image, uni-form, Attendees global diff -r 3197696debbe -r 03c5651a371e static-files/banner.png Binary file static-files/banner.png has changed diff -r 3197696debbe -r 03c5651a371e static-files/default.uni-form.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static-files/default.uni-form.css Fri Jun 25 16:00:15 2010 -0700 @@ -0,0 +1,153 @@ +/* ------------------------------------------------------------------------------ + + UNI-FORM DEFAULT by DRAGAN BABIC (v2) | Wed, 31 Mar 10 + + ------------------------------------------------------------------------------ + + Copyright (c) 2010, Dragan Babic + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + ------------------------------------------------------------------------------ */ + +.uniForm{} + + .uniForm legend{ font-weight: bold; font-size: 100%; margin: 0; padding: 1.5em 0; } + + .uniForm .ctrlHolder{ padding: 1em; border-bottom: 1px solid #efefef; } + .uniForm .ctrlHolder.focused{ background: #fffcdf; } + + .uniForm .inlineLabels .noLabel{} + + .uniForm .buttonHolder{ background: #efefef; text-align: right; margin: 1.5em 0 0 0; padding: 1.5em; + /* CSS3 */ + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -khtml-border-radius: 4px; + } + .uniForm .buttonHolder .primaryAction{ padding: 10px 22px; line-height: 1; background: #254a86; border: 1px solid #163362; font-size: 12px; font-weight: bold; color: #fff; + /* CSS3 */ + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -khtml-border-radius: 4px; + box-shadow: 1px 1px 0 #fff; + -webkit-box-shadow: 1px 1px 0 #fff; + -moz-box-shadow: 1px 1px 0 #fff; + text-shadow: -1px -1px 0 rgba(0,0,0,.25); + } + .uniForm .buttonHolder .primaryAction:active{ position: relative; top: 1px; } + .uniForm .secondaryAction { text-align: left; } + .uniForm button.secondaryAction { background: transparent; border: none; color: #777; margin: 1.25em 0 0 0; padding: 0; } + + .uniForm .inlineLabels label em, + .uniForm .inlineLabels .label em{ font-style: normal; font-weight: bold; } + .uniForm label small{ font-size: .75em; color: #777; } + + .uniForm .textInput, + .uniForm textarea { padding: 4px 2px; border: 1px solid #aaa; background: #fff; } + .uniForm textarea { height: 12em; } + .uniForm select {} + .uniForm .fileUpload {} + + .uniForm ul{} + .uniForm li{} + .uniForm ul li label{ font-size: .85em; } + + .uniForm .small {} + .uniForm .medium{} + .uniForm .large {} /* Large is default and should match the value you set for .textInput, textarea or select */ + .uniForm .auto {} + .uniForm .small, + .uniForm .medium, + .uniForm .auto{} + + /* Get rid of the 'glow' effect in WebKit, optional */ + .uniForm .ctrlHolder .textInput:focus, + .uniForm .ctrlHolder textarea:focus{ outline: none; } + + .uniForm .formHint { font-size: .85em; color: #777; } + .uniForm .inlineLabels .formHint { padding-top: .5em; } + .uniForm .ctrlHolder.focused .formHint{ color: #333; } + +/* ----------------------------------------------------------------------------- */ +/* ############################### Messages #################################### */ +/* ----------------------------------------------------------------------------- */ + + /* Error message at the top of the form */ + .uniForm #errorMsg{ background: #ffdfdf; border: 1px solid #f3afb5; margin: 0 0 1.5em 0; padding: 0 1.5em; + /* CSS3 */ + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -khtml-border-radius: 4px; + } + .uniForm #errorMsg h3{} /* Feel free to use a heading level suitable to your page structure */ + .uniForm #errorMsg ol{ margin: 0 0 1.5em 0; padding: 0; } + .uniForm #errorMsg ol li{ margin: 0 0 3px 1.5em; padding: 7px; background: #f6bec1; position: relative; font-size: .85em; + /* CSS3 */ + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -khtml-border-radius: 4px; + } + + .uniForm .ctrlHolder.error, + .uniForm .ctrlHolder.focused.error{ background: #ffdfdf; border: 1px solid #f3afb5; + /* CSS3 */ + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -khtml-border-radius: 4px; + } + .uniForm .ctrlHolder.error input.error, + .uniForm .ctrlHolder.error select.error, + .uniForm .ctrlHolder.error textarea.error{ color: #af4c4c; margin: 0 0 6px 0; padding: 4px; } + + /* Success messages at the top of the form */ + .uniForm #okMsg{ background: #c8ffbf; border: 1px solid #a2ef95; margin: 0 0 1.5em 0; padding: 0 1.5em; text-align: center; + /* CSS3 */ + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -khtml-border-radius: 4px; + } + .uniForm #OKMsg p{ margin: 0; } + +/* ----------------------------------------------------------------------------- */ +/* ############################### Columns ##################################### */ +/* ----------------------------------------------------------------------------- */ + + .uniForm .col{} + .uniForm .col.first{} + .uniForm .col.last{} + .uniForm .col{ margin-bottom: 1.5em; } + /* Use .first and .last classes to control the layout/spacing of your columns */ + .uniForm .col.first{ width: 49%; float: left; clear: none; } + .uniForm .col.last { width: 49%; float: right; clear: none; margin-right: 0; } \ No newline at end of file diff -r 3197696debbe -r 03c5651a371e static-files/index.html --- a/static-files/index.html Fri Jun 25 20:33:01 2010 +0000 +++ b/static-files/index.html Fri Jun 25 16:00:15 2010 -0700 @@ -1,59 +1,133 @@ Mozilla Summit Identity Pal + + +
-

You don't seem to be logged in!

-

Enter your email address and press enter:

-
- -
-
-

Fail! Maybe you entered an email address that isn't - registered for the summit, or maybe there's a bug - in this app.

-
+

Welcome to the Mozilla Summit Identity Pal!

+

Here you can enter information about yourself for sharing only + with other Summit-goers. It's a great way to find out who + will be at the Summit.

+
+
+
+ + +

This should be the same email address you + receive your Summit Newsletter at.

+
+
+ Alas, something didn't work. Maybe you entered an email address that isn't + registered for the Summit? +
+
+
+

An email was sent to you. Check your inbox and click the link in the email to log in.

+
+
-

Fail! Maybe the email was sent too long ago, or this - verification URL was already visited before, or there's - a bug in this app.

+ Fail! Maybe the email was sent too long ago, or this + verification URL was already visited before?
-
Something messed up. Start - over!
+
+
+

Hi! You are logged in as .

-
Log Out
+

Please fill out some of the fields below. This information will + be made available only to other summit attendees and their cool + mashups and web apps.

+
+
+
+ + +

What should people call you?

+
+ +
+ + +

If you have a picture of yourself somewhere, + paste in its URL here. It's expected to have square dimensions.

+
+ +
+ + +

If you use Bugzilla, enter your email here.

+
+ +
+ Great success! Your information has been updated. +
+ +
+ Fail! Maybe you're not connected to the internet? +
+ +
+
+
+
+ diff -r 3197696debbe -r 03c5651a371e static-files/index.js --- a/static-files/index.js Fri Jun 25 20:33:01 2010 +0000 +++ b/static-files/index.js Fri Jun 25 16:00:15 2010 -0700 @@ -25,42 +25,89 @@ observers: [] }; -var Api = { - postJSON: function Api_postJSON(path, obj, cb) { - var options = { - url: path, - type: "POST", - contentType: "application/json", - data: JSON.stringify(obj), - dataType: "json", - success: function(data) { - cb(true, data); - }, - error: function(req, textStatus, errorThrown) { - var data = null; - if (req.getResponseHeader("Content-Type") == "application/json") { - try { - data = JSON.parse(req.responseText); - } catch (e) {} - } - cb(false, data); - } - }; - return jQuery.ajax(options); - } -}; - ( - // This anonymous closure sets up the UI. + // Config initialization code. function(window) { function ensureStateIsValid() { if (!('state' in Config.value)) Config.setValue({state: "login"}); } + Config.observers.push(ensureStateIsValid); + + $(window).ready(ensureStateIsValid); + } +)(window); + +( + // Attendee initialization code. + function(window) { + var req; + + var Attendees = { + refresh: function refresh() { + if (req) + return; + var self = this; + if (Config.value.token) { + req = jQuery.getJSON( + "/profile", + {token: Config.value.token}, + function(data, textStatus) { + // TODO: Might need to add a failure callback too? + req = null; + if (textStatus == "success") { + self.value = data.contents; + self.observers.forEach(function(cb) { cb(); }); + } else { + // TODO: Raise an error? + } + }); + } + }, + value: null, + observers: [] + }; + + function refreshAttendees() { + if (Config.value.state == "logged-in" && !Attendees.users) + Attendees.refresh(); + } + + Config.observers.push(refreshAttendees); + $(window).ready(refreshAttendees); + + window.Attendees = Attendees; + } +)(window); + +jQuery.postJSON = function postJSON(path, obj, cb) { + var options = { + url: path, + type: "POST", + contentType: "application/json", + data: JSON.stringify(obj), + dataType: "json", + success: function(data) { + cb(true, data); + }, + error: function(req, textStatus, errorThrown) { + var data = null; + if (req.getResponseHeader("Content-Type") == "application/json") { + try { + data = JSON.parse(req.responseText); + } catch (e) {} + } + cb(false, data); + } + }; + return jQuery.ajax(options); +}; + +( + // This anonymous closure sets up the UI. + function(window) { function updateUI() { - ensureStateIsValid(); - $(".screen").hide(); $("#" + Config.value.state).show(); switch (Config.value.state) { @@ -74,6 +121,17 @@ } } + function fillUserInfo() { + var userInfo = Attendees.value[Config.value.userID]; + if (!userInfo) + userInfo = {}; + $("#name").val(userInfo.name || ""); + $("#profile-image").val(userInfo.profileImage || ""); + $("#bugzilla-email").val(userInfo.bugzillaEmail || ""); + } + + Attendees.observers.push(fillUserInfo); + function bindConfigToUI() { var lastChanged = Config.lastChanged; @@ -96,15 +154,17 @@ } function initUI() { - ensureStateIsValid(); - - $(".start-over").click(function() { Config.wipe(); }); + $(".start-over").submit( + function(event) { + event.preventDefault(); + Config.wipe(); + }); $("#login form").submit( function(event) { event.preventDefault(); $("#login .error").hide(); - Api.postJSON( + jQuery.postJSON( "/challenge/request", {email: $(this).find("#email").val() }, function(success, data) { @@ -116,11 +176,36 @@ }); }); + $("#logged-in form").submit( + function(event) { + event.preventDefault(); + $("#logged-in .success").hide(); + $("#logged-in .error").hide(); + + var contents = { + name: $("#name").val(), + profileImage: $("#profile-image").val(), + bugzillaEmail: $("#bugzilla-email").val() + }; + + jQuery.postJSON( + "/profile", + {token: Config.value.token, + contents: contents}, + function(success, data) { + if (success) { + $("#logged-in .success").slideDown(); + } else { + $("#logged-in .error").slideDown(); + } + }); + }); + var verify = window.location.hash.match(/#verify=(.+)/); if (verify && Config.value.state != "logged-in") { verify = verify[1]; Config.setValue({state: "wait-for-verify"}); - Api.postJSON( + jQuery.postJSON( "/challenge/respond", {token: verify}, function(success, data) { @@ -129,6 +214,7 @@ if (success) { Config.setValue({state: "logged-in", token: data.token, + userID: data.user_id, email: data.email}); } else { $("#wait-for-verify .error").slideDown(); @@ -145,6 +231,8 @@ ( // Set up the postMessage API. function(window) { + var attendeeCallbacks = []; + var myOrigin = window.location.protocol + "//" + window.location.host; var handlers = { getAllUsers: function(options, cb, origin) { @@ -160,18 +248,20 @@ return; } - jQuery.getJSON( - "/profile", - {token: Config.value.token}, - function(data, textStatus) { - if (textStatus == "success") - cb({users: data}); - else - cb({error: "an error occurred retrieving user data."}); - }); + if (Attendees.value) { + cb({users: Attendees.value}); + } else + attendeeCallbacks.push(cb); } }; var server = new Summit.Server(handlers); + + Attendees.observers.push( + function() { + var cbs = []; + attendeeCallbacks = []; + cbs.forEach(function(cb) { cb({users: Attendees.value}); }); + }); } )(window); diff -r 3197696debbe -r 03c5651a371e static-files/uni-form.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static-files/uni-form.css Fri Jun 25 16:00:15 2010 -0700 @@ -0,0 +1,154 @@ +/* ------------------------------------------------------------------------------ + + Copyright (c) 2010, Dragan Babic + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + ------------------------------------------------------------------------------ */ +/* ############################# GENERALS ################################### */ +/* ------------------------------------------------------------------------------ */ + +.uniForm{ margin: 0; padding: 0; position: relative; z-index: 1; } /* reset stuff */ + + /* Some generals and more resets */ + .uniForm fieldset{ border: none; margin: 0; padding: 0; } + .uniForm fieldset legend{ margin: 0; padding: 0; } + + /* This are the main units that contain form elements */ + .uniForm .ctrlHolder, + .uniForm .buttonHolder{ margin: 0; padding: 0; clear: both; } + + /* Clear all floats */ + .uniForm:after, + .uniForm .buttonHolder:after, + .uniForm .ctrlHolder:after, + .uniForm .ctrlHolder .multiField:after, + .uniForm .inlineLabel:after{ content: "."; display: block; height: 0; line-height: 0; font-size: 0; clear: both; min-height: 0; visibility: hidden; } + + .uniForm label, + .uniForm button{ cursor: pointer; } + +/* ------------------------------------------------------------------------------ */ +/* ########################## DEFAULT LAYOUT ################################ */ +/* ------------------------------------------------------------------------------ */ +/* Styles for form controls where labels are above the input elements */ +/* ------------------------------------------------------------------------------ */ + + .uniForm label, + .uniForm .label{ display: block; float: none; margin: 0 0 .5em 0; padding: 0; line-height: 100%; width: auto; } + + /* Float the input elements */ + .uniForm .textInput, + .uniForm .fileUpload, + .uniForm .selectInput, + .uniForm select, + .uniForm textarea{ float: left; width: 53%; margin: 0; } + + /* Postition the hints */ + .uniForm .formHint{ float: right; width: 43%; margin: 0; clear: none; } + + /* Position the elements inside combo boxes (multiple inputs/selects/checkboxes/radio buttons per unit) */ + .uniForm ul{ float: left; width: 53%; margin: 0; padding: 0; } + .uniForm ul li{ margin: 0 0 .5em 0; list-style: none; } + .uniForm ul li label{ margin: 0; float: none; display: block; overflow: visible; } + /* Alternate layout */ + .uniForm ul.alternate li{ float: left; width: 30%; margin-right: 3%; } + .uniForm ul.alternate li label{ float: none; display: block; width: 98%; } + .uniForm ul .textInput, + .uniForm ul .selectInput, + .uniForm ul select, + .uniForm ul.alternate .textInput, + .uniForm ul.alternate .selectInput, + .uniForm ul.alternate select{ width: 98%; margin-top: .5em; display: block; float: none; } + + /* Required fields asterisk styling */ + .uniForm label em, + .uniForm .label em{ float: left; width: 1em; margin: 0 0 0 -1em; } + +/* ------------------------------------------------------------------------------ */ +/* ######################### ALTERNATE LAYOUT ############################### */ +/* ------------------------------------------------------------------------------ */ +/* Styles for form controls where labels are in line with the input elements */ +/* Set the class of the parent (preferably to a fieldset) to .inlineLabels */ +/* ------------------------------------------------------------------------------ */ + + .uniForm .inlineLabels label, + .uniForm .inlineLabels .label{ float: left; margin: .3em 2% 0 0; padding: 0; line-height: 1; position: relative; width: 32%; } + + /* Float the input elements */ + .uniForm .inlineLabels .textInput, + .uniForm .inlineLabels .fileUpload, + .uniForm .inlineLabels .selectInput, + .uniForm .inlineLabels select, + .uniForm .inlineLabels textarea{ float: left; width: 64%; } + + /* Postition the hints */ + .uniForm .inlineLabels .formHint{ clear: both; float: none; width: auto; margin-left: 34%; position: static; } + + /* Position the elements inside combo boxes (multiple inputs/selects/checkboxes/radio buttons per unit) */ + .uniForm .inlineLabels ul{ float: left; width: 66%; } + .uniForm .inlineLabels ul li{ margin: .5em 0; } + .uniForm .inlineLabels ul li label{ float: none; display: block; width: 100%; } + /* Alternate layout */ + .uniForm .inlineLabels ul.alternate li{ margin-right: 3%; margin-top: .25em; } + .uniForm .inlineLabels ul li label .textInput, + .uniForm .inlineLabels ul li label textarea, + .uniForm .inlineLabels ul li label select{ float: none; display: block; width: 98%; } + + /* Required fields asterisk styling */ + .uniForm .inlineLabels label em, + .uniForm .inlineLabels .label em{ display: block; float: none; margin: 0; position: absolute; right: 0; } + +/* ----------------------------------------------------------------------------- */ +/* ########################### Additional Stuff ################################ */ +/* ----------------------------------------------------------------------------- */ + + /* Generals */ + .uniForm legend{ color: inherit; } + + .uniForm .secondaryAction{ float: left; } + + /* .inlineLabel is used for inputs within labels - checkboxes and radio buttons */ + .uniForm .inlineLabel input, + .uniForm .inlineLabels .inlineLabel input, + .uniForm .blockLabels .inlineLabel input, + /* class .inlineLabel is depreciated */ + .uniForm label input{ float: none; display: inline; margin: 0; padding: 0; border: none; } + + .uniForm .buttonHolder .inlineLabel, + .uniForm .buttonHolder label{ float: left; margin: .5em 0 0 0; width: auto; max-width: 60%; text-align: left; } + + /* When you don't want to use a label */ + .uniForm .inlineLabels .noLabel ul{ margin-left: 34%; /* Match to width of label + gap to field */ } + + /* Classes for control of the widths of the fields */ + .uniForm .small { width: 30% !important; } + .uniForm .medium{ width: 45% !important; } + .uniForm .large { } /* Large is default and should match the value you set for .textInput, textarea or select */ + .uniForm .auto { width: auto !important; } + .uniForm .small, + .uniForm .medium, + .uniForm .auto{ margin-right: 4px; } + +/* Columns */ +.uniForm .col{ float: left; } +.uniForm .col{ width: 50%; } \ No newline at end of file diff -r 3197696debbe -r 03c5651a371e static-files/uni-form.jquery.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static-files/uni-form.jquery.js Fri Jun 25 16:00:15 2010 -0700 @@ -0,0 +1,27 @@ +// Author: Ilija Studen for the purposes of Uni–Form +// Modified by Aris Karageorgos to use the parents function + +jQuery.fn.uniform = function(settings) { + settings = jQuery.extend({ + valid_class : 'valid', + invalid_class : 'invalid', + focused_class : 'focused', + holder_class : 'ctrlHolder', + field_selector : 'input, select, textarea' + }, settings); + + return this.each(function() { + var form = jQuery(this); + // Select form fields and attach them higlighter functionality + form.find(settings.field_selector).focus(function() { + form.find('.' + settings.focused_class).removeClass(settings.focused_class); + $(this).parents().filter('.'+settings.holder_class+':first').addClass(settings.focused_class); + }).blur(function() { + form.find('.' + settings.focused_class).removeClass(settings.focused_class); + }); + }); +}; +// Auto set on page load... +$(document).ready(function() { + jQuery('form.uniForm').uniform(); +}); \ No newline at end of file diff -r 3197696debbe -r 03c5651a371e summitidp/app.py --- a/summitidp/app.py Fri Jun 25 20:33:01 2010 +0000 +++ b/summitidp/app.py Fri Jun 25 16:00:15 2010 -0700 @@ -162,12 +162,14 @@ ) email = chaltok['email'] self.challenge_tokens.revoke(body['token']) + user_id = self.emails.index(email) token = self.auth_tokens.create( email=email, - user_id=self.emails.index(email) + user_id=user_id ) return req.json_response('200 OK', {'token': token, + 'user_id': user_id, 'email': email}) return req.json_response('400 Bad Request', {'error': 'invalid body'}) diff -r 3197696debbe -r 03c5651a371e tests/test_app.py --- a/tests/test_app.py Fri Jun 25 20:33:01 2010 +0000 +++ b/tests/test_app.py Fri Jun 25 16:00:15 2010 -0700 @@ -95,6 +95,7 @@ resp = post_json(server.respond_to_challenge_path, {'token': token}) assert resp.json == {'email': 'bob@foo.com', + 'user_id': 0, 'token': 'my auth token'} assert server.auth_tokens.get('my auth token') == { 'email': 'bob@foo.com', @@ -116,6 +117,7 @@ resp = post_json(server.respond_to_challenge_path, {'token': token}) assert resp.json == {'email': 'bob@foo.com', + 'user_id': 0, 'token': 'my auth token'} post_json(server.respond_to_challenge_path, {'token': token},