Trying to tighten up the design. More functionality implemented.

This commit is contained in:
Jonathan Bernard 2011-05-03 12:50:03 -05:00
parent cf5153c90b
commit dd3387a0f1
4 changed files with 420 additions and 258 deletions

View File

@ -4,19 +4,29 @@
*/ */
/* _rounded.scss */ /* _rounded.scss */
* { * {
color: #222222; color: inherit;
margin: 0; margin: 0;
padding: 0; } padding: 0; }
body { body {
width: 70%; color: #222222;
width: 75%;
margin: auto; } margin: auto; }
input {
border: solid thin #555555;
-webkit-box-shadow: inset 0px 2px 4px #CCC;
box-shadow: inset 0px 2px 4px #CCC;
margin-bottom: 0.5em;
font-family: Cantarell; }
#top { #top {
background: #222222;
color: #eeeeee;
padding: 0.5rem 0;
position: fixed; position: fixed;
top: 0px; top: 0px;
background: white; width: 75%; }
width: 70%; }
#top #fade-bar { #top #fade-bar {
background: url("img/fade.png") repeat-x; background: url("img/fade.png") repeat-x;
height: 32px; height: 32px;
@ -24,35 +34,32 @@ body {
#user { #user {
font-family: "Josefin Sans"; font-family: "Josefin Sans";
margin-top: -0.3rem;
padding: 0 2rem;
width: 100%; } width: 100%; }
#user .fullname, #user .username { #user .fullname, #user .username {
display: inline-block; display: inline-block;
font-size: larger; } font-size: larger; }
#user .fullname-input { #user .fullname-input {
display: none; } display: none; }
#user.fullname-edit .fullname-input { #user.edit-fullname .fullname-input {
display: inline-block; } display: inline-block; }
#user.fullname-edit .fullname { #user.edit-fullname .fullname {
display: none; } display: none; }
#user .drop-menu { #user .drop-menu {
display: inline-block; } display: inline-block; }
#user .drop-menu .drop-menu-items { #user .drop-menu .drop-menu-items {
float: right; margin-top: -0.5em;
list-style: none; } text-align: right;
#user .drop-menu .drop-menu-items li { right: 0;
float: right; list-style: none;
text-align: center; width: 10em; }
padding-right: 1em; }
#user a {
display: inline-block;
text-decoration: none; }
#user a:hover {
text-decoration: underline; }
#timeline { #timeline {
border-bottom: thin solid black; border-bottom: thin solid #eeeeee;
font-family: Arvo; font-family: Arvo;
font-size: 1.5em; } font-size: 1.5em;
padding: 0 2rem; }
#timeline .timeline-desc { #timeline .timeline-desc {
display: inline-block; display: inline-block;
width: 70%; } width: 70%; }
@ -76,32 +83,24 @@ body {
width: 29%; } width: 29%; }
#timeline .drop-menu .drop-menu-items { #timeline .drop-menu .drop-menu-items {
text-align: right; text-align: right;
right: 0; } right: 0;
width: 172.41%; }
#timeline .drop-menu .drop-menu-items .timeline-link {
font-size: medium; }
#entry-list {
margin-top: 6rem;
padding-bottom: 1rem; }
#new-entry { #new-entry {
margin-top: 5.5em; margin-top: 0.5rem;
padding: 0.5em 0.5em; } padding: 0 2rem; }
#new-entry .mark-input, #new-entry .timestamp-input {
border: solid thin #555555;
-webkit-box-shadow: inset 0px 2px 4px #CCC;
box-shadow: inset 0px 2px 4px #CCC;
margin-bottom: 0.5em;
font-family: Cantarell; }
#new-entry .mark-input { #new-entry .mark-input {
width: 78%; } width: 78%; }
#new-entry .edit-mark .mark-input {
display: inline-block; }
#new-entry .edit-mark .mark {
display: none; }
#new-entry .edit-timestamp .timestamp-input {
display: inline-block; }
#new-entry .edit-timestamp .timestamp {
display: none; }
#entries { #entries .entry {
padding: 0.5em 0.5em; } font-family: Cantarell;
#entries .entry { padding: 0 2rem; }
font-family: Cantarell; }
#entries .entry div { #entries .entry div {
display: inline-block; } display: inline-block; }
#entries .entry .timestamp, #entries .entry .timestamp-input { #entries .entry .timestamp, #entries .entry .timestamp-input {
@ -114,27 +113,49 @@ body {
display: none; } display: none; }
#entries .entry .notes { #entries .entry .notes {
display: none; } display: none; }
#entries .entry.edit-mark .mark-input {
display: inline-block; }
#entries .entry.edit-mark .mark {
display: none; }
#entries .entry.edit-timestamp .timestamp-input {
display: inline-block; }
#entries .entry.edit-timestamp .timestamp {
display: none; }
.day-seperator {
background: #cccccc;
color: #222222;
font-family: Cantarell;
font-weight: bold;
margin-top: 1rem;
padding: 0 2rem; }
.drop-menu { .drop-menu {
position: relative; } position: relative; }
.drop-menu .drop-menu-items { .drop-menu .drop-menu-items {
background: white;
display: none; display: none;
list-style: none; list-style: none;
position: absolute; } position: absolute; }
.drop-menu .drop-menu-items li {
display: inline-block;
padding-left: 0.5em; }
.drop-menu:hover .drop-menu-items, .drop-menu .drop-menu-items:hover { .drop-menu:hover .drop-menu-items, .drop-menu .drop-menu-items:hover {
display: block; } display: block; }
.drop-menu a {
display: inline-block;
text-decoration: none; }
.drop-menu a:hover {
text-decoration: underline; }
.footer { .footer {
border-top: thin solid black; background: #222222;
color: #888888; color: #eeeeee;
font-family: Bentham; font-family: Bentham;
margin: 1em 0; padding: 1rem 0;
padding-top: 1em;
text-align: center; text-align: center;
width: 100%; } width: 100%; }
.footer a { .footer a {
color: #888888; color: white;
text-decoration: none; } text-decoration: none; }
.footer a:hover { .footer a:hover {
text-decoration: underline; } text-decoration: underline; }

View File

@ -5,24 +5,39 @@
@import "rounded"; @import "rounded";
$txtClr: #222; $darkTxt: #222;
$lightTxt: #eee;
$darkBg: #222;
$lightBg: #eee;
$medBg: #CCC;
* { * {
color: $txtClr; color: inherit;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
body { body {
width: 70%; color: $darkTxt;
width: 75%;
margin: auto; margin: auto;
} }
input {
border: solid thin lighten($darkTxt, 20%);
-webkit-box-shadow: inset 0px 2px 4px #CCC;
box-shadow: inset 0px 2px 4px #CCC;
margin-bottom: 0.5em;
font-family: Cantarell;
}
#top { #top {
background: $darkBg;
color: $lightTxt;
padding: 0.5rem 0;
position: fixed; position: fixed;
top: 0px; top: 0px;
background: white; width: 75%;
width: 70%;
#fade-bar { #fade-bar {
background: url('img/fade.png') repeat-x; background: url('img/fade.png') repeat-x;
@ -34,6 +49,8 @@ body {
#user { #user {
font-family: "Josefin Sans"; font-family: "Josefin Sans";
margin-top: -0.3rem;
padding: 0 2rem;
width: 100%; width: 100%;
.fullname, .username { .fullname, .username {
@ -43,7 +60,7 @@ body {
.fullname-input { display: none; } .fullname-input { display: none; }
&.fullname-edit { &.edit-fullname{
.fullname-input { display: inline-block; } .fullname-input { display: inline-block; }
.fullname { display: none; } .fullname { display: none; }
} }
@ -51,33 +68,22 @@ body {
.drop-menu { display: inline-block; } .drop-menu { display: inline-block; }
.drop-menu .drop-menu-items { .drop-menu .drop-menu-items {
margin-top: -0.5em;
float: right; text-align: right;
right: 0;
list-style: none; list-style: none;
width: 10em;
li {
float: right;
text-align: center;
//margin-top: -0.5em;
padding-right: 1em;
}
} }
a {
display: inline-block;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
} }
#timeline { #timeline {
border-bottom: thin solid black; border-bottom: thin solid $lightBg;
font-family: Arvo; font-family: Arvo;
font-size: 1.5em; font-size: 1.5em;
padding: 0 2rem;
.timeline-desc { .timeline-desc {
display: inline-block; display: inline-block;
@ -108,42 +114,34 @@ body {
.drop-menu-items { .drop-menu-items {
text-align: right; text-align: right;
right: 0; right: 0;
width: 172.41%;
.timeline-link {
font-size: medium;
}
} }
} }
} }
#new-entry { #entry-list {
margin-top: 5.5em; margin-top: 6rem;
padding: 0.5em 0.5em; padding-bottom: 1rem;
}
.mark-input, .timestamp-input { #new-entry {
border: solid thin lighten($txtClr, 20%); margin-top: 0.5rem;
-webkit-box-shadow: inset 0px 2px 4px #CCC; padding: 0 2rem;
box-shadow: inset 0px 2px 4px #CCC;
margin-bottom: 0.5em;
font-family: Cantarell;
}
.mark-input { width: 78%; } .mark-input { width: 78%; }
.edit-mark {
.mark-input { display: inline-block; }
.mark { display: none; }
}
.edit-timestamp {
.timestamp-input { display: inline-block; }
.timestamp { display: none; }
}
} }
#entries { #entries {
padding: 0.5em 0.5em;
.entry { .entry {
font-family: Cantarell; font-family: Cantarell;
padding: 0 2rem;
div { display: inline-block; } div { display: inline-block; }
@ -157,38 +155,66 @@ body {
.notes { display: none; } .notes { display: none; }
&.edit-mark {
.mark-input { display: inline-block; }
.mark { display: none; }
} }
&.edit-timestamp {
.timestamp-input { display: inline-block; }
.timestamp { display: none; }
}
}
}
.day-seperator {
background: $medBg;
color: $darkBg;
font-family: Cantarell;
font-weight: bold;
margin-top: 1rem;
padding: 0 2rem;
} }
.drop-menu { .drop-menu {
position: relative; position: relative;
.drop-menu-items { .drop-menu-items {
background: white;
display: none; display: none;
list-style: none; list-style: none;
position: absolute; position: absolute;
li {
display: inline-block;
padding-left: 0.5em;
}
} }
&:hover .drop-menu-items, .drop-menu-items:hover { &:hover .drop-menu-items, .drop-menu-items:hover { display: block; }
display: block;
}
a {
display: inline-block;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
} }
.footer { .footer {
border-top: thin solid black; background: $darkBg;
color: lighten($txtClr, 40%); color: $lightTxt;
font-family: Bentham; font-family: Bentham;
margin: 1em 0; padding: 1rem 0;
padding-top: 1em;
text-align: center; text-align: center;
width: 100%; width: 100%;
a { a {
color: lighten($txtClr, 40%); color: lighten($lightTxt, 20%);
text-decoration: none; text-decoration: none;
&:hover { text-decoration: underline; } &:hover { text-decoration: underline; }

View File

@ -20,67 +20,100 @@
<script type="text/javascript" src="/js/ICanHaz.js"></script> <script type="text/javascript" src="/js/ICanHaz.js"></script>
<script type="text/javascript" src="/js/backbone.js"></script> <script type="text/javascript" src="/js/backbone.js"></script>
<script type="text/javascript" src="/js/ts.js"></script> <script type="text/javascript" src="/js/ts.js"></script>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <script type="text/javascript">
<erl>
out(YArg) ->
Session = ts_api_session:get_session(YArg),
case Session of not_logged_in -> {html, "//not logged in"}; session_expired -> {html, "//session expired"};
_S ->
Username = element(2, Session),
<script id="timelineLink" type="text/html"> % get the user
<li class="timeline-link"><a href="#">{{id}}</a></li> {content, _, UserJSON} = ts_api:get_user(YArg, Username),
UserRecord = ts_user:lookup(Username),
% get the timelines
{content, _, TimelineListJSON} = ts_api:list_timelines(YArg, Username),
% get the selected timeline
SelectedTimeline = case lists:keyfind(
selected_timeline, 1, element(8, UserRecord)) of
false -> ts_timeline:list(Username, 0, 1);
T -> T
end,
% get entries for this timeline
{content, _, EntryListJSON} =
ts_api:list_entries(YArg, Username, SelectedTimeline),
{html, f(
"function bootstrap() {~n"
" var data = {};~n"
" data.user = ~p;~n"
" data.timelines = ~p;~n"
" data.initialTimelineId = ~p;~n"
" data.entries = ~p;~n"
" return data;~n"
"};",
[UserJSON, TimelineListJSON, SelectedTimeline, EntryListJSON])}
end.
</erl>
</script> </script>
<script id="entry" type="text/html"> <script type="text/html" id="userTemplate">
<div class="entry"> <div class="fullname">{{name}}</div>
<div class="mark">{{mark}}</div> <input class='fullname-input' type='text' value='{{name}}'/></div>
<input class="mark-input" type="text">{{mark}}</input>
<div class="timestamp">{{timestamp}}</div>
<input class="timestamp-input" type="text">{{timestamp}}</input>
<div class="duration">4<span class="tick-tock">:</span>03<span class="tick-tock">:</span>57</div>
<div class="notes">{{notes}}</div>
</div>
</script>
</head>
<body>
<div id="top">
<div id="timeline">
<span class="timeline-desc">No timeline loaded.</span>
<input class="timeline-desc-input" type="text"/>
<div class="drop-menu">
<div class="timeline-id">(&nbsp;none&nbsp;)</div>
<input class="timeline-id-input" type="text"/>
<ul class="drop-menu-items">
</ul>
</div>
</div>
<div id="user">
<div class="fullname">Not Logged In</div>
<input class='fullname-input' type='text'/>
<div class='drop-menu'> <div class='drop-menu'>
<div class="username"> - not_logged_in</div> <div class="username"> - {{id}}</div>
<ul class="drop-menu-items"> <ul class="drop-menu-items">
<li><a href="#">logout</a></li> <li><a href="#">logout</a></li>
<li><a href="#">user info</a></li> <li><a href="#">user info</a></li>
</ul> </ul>
</div> </div>
</script>
<script type="text/html" id="timelineTemplate">
<span class="timeline-desc">{{description}}</span>
<input class="timeline-desc-input" type="text" value='{{description}}'/>
<div class="drop-menu">
<div class="timeline-id">(&nbsp;{{id}}&nbsp;)</div>
<input class="timeline-id-input" type="text" value='{{id}}'/>
<ul class="drop-menu-items">
</ul>
</div> </div>
</script>
<script type="text/html" id="timelineLinkTemplate">
<li class="timeline-link"><a href="#">{{id}}</a></li>
</script>
<script type="text/html" id="entryTemplate">
<div class="mark">{{mark}}</div>
<input class="mark-input" type="text" value="{{mark}}"/>
<div class="timestamp">{{timestamp}}</div>
<input class="timestamp-input" type="text" value="{{timestamp}}"/>
<!-- TODO <div class="duration">4<span class="tick-tock">:</span>03<span class="tick-tock">:</span>57</div>-->
<div class="notes">{{notes}}</div>
</script>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<div id="top">
<!-- == TIMELINE == -->
<div id="timeline"><!-- rendered by app --></div>
<!-- == USER == -->
<div id="user"><!-- rendered by app --></div>
</div> </div>
<div id="entry-list"> <div id="entry-list">
<div class="day-seperator">Today</div>
<div id="new-entry"> <div id="new-entry">
<input id="new-entry-input" class="mark-input" <input id="new-entry-input" class="mark-input"
placeholder="Start a new task..." type="text" /> placeholder="Start a new task..." type="text" />
</div> </div>
<div id="entries"> <div id="entries"></div>
<div class="entry">
<div class="mark">ITHelp: Entering tickets.</div>
<input class="mark-input" type="text"/>
<div class="timestamp">12:32</div>
<input class="timestamp-input" type="text"/>
<div class="duration">4<span class="tick-tock">:</span>03<span class="tick-tock">:</span>57</div>
<div class="notes">Some notes should go here, but they should be hidden by default</div>
</div>
</div>
</div> </div>
<div class="footer"> <div class="footer">
@ -100,6 +133,7 @@
</form> </form>
<p class="validate-tips"></p> <p class="validate-tips"></p>
</div> </div>
</body> </body>
</html> </html>

View File

@ -20,7 +20,7 @@ $(document).ready(function(){
/* Timeline model. /* Timeline model.
* Attributes: * Attributes:
* - id * - id
* - desc * - description
* - created * - created
*/ */
TS.TimelineModel = Backbone.Model.extend({ TS.TimelineModel = Backbone.Model.extend({
@ -56,7 +56,7 @@ $(document).ready(function(){
}, },
url: function() { url: function() {
return "/entries/" + this.timeline.get('user_id') + "/" + this.timeline.get('id'); return "/ts_api/entries/" + this.timeline.get('user_id') + "/" + this.timeline.get('id');
} }
}); });
@ -89,6 +89,8 @@ $(document).ready(function(){
model: TS.EntryModel, model: TS.EntryModel,
className: 'entry',
events: { events: {
"dblclick div.mark" : "editMark", "dblclick div.mark" : "editMark",
"dblclick div.timestamp" : "editTimestamp", "dblclick div.timestamp" : "editTimestamp",
@ -104,7 +106,7 @@ $(document).ready(function(){
}, },
render: function() { render: function() {
$(this.el).html(ich.entry(this.model.toJSON())); $(this.el).html(ich.entryTemplate(this.model.toJSON()));
return this; return this;
}, },
@ -125,6 +127,7 @@ $(document).ready(function(){
mark: this.$('.mark-input').val(), mark: this.$('.mark-input').val(),
timestamp: this.$('.timestamp-input').val()}); timestamp: this.$('.timestamp-input').val()});
$(this.el).removeClass('edit-mark edit-timestamp'); $(this.el).removeClass('edit-mark edit-timestamp');
this.render();
}, },
updateOnEnter: function(e) { updateOnEnter: function(e) {
@ -137,7 +140,7 @@ $(document).ready(function(){
el: $("#entry-list"), el: $("#entry-list"),
events: { events: {
"#new-entry" : "createNewEntry" "keypress #new-entry-input" : "createNewEntryOnEnter"
}, },
initialize: function() { initialize: function() {
@ -153,10 +156,18 @@ $(document).ready(function(){
this.entryContainer.prepend(entry.view.render().el); this.entryContainer.prepend(entry.view.render().el);
}, },
createNewEntry: function() { createNewEntryOnEnter: function(e) {
if (e.keyCode == 13) {
// grab the mark data
var entryMark = this.$("#new-entry-input").val(); var entryMark = this.$("#new-entry-input").val();
var newEntry = TS.EntryModel({mark: entryMark});
this.collection.create({mark: entryMark}).fetch(); // create the mark. Immediately fetch to get server-side timestamp
this.collection.create({mark: entryMark,
notes: '',
timestamp: getUTCTimestamp()}).fetch();
}
}, },
render: function() { render: function() {
@ -165,11 +176,10 @@ $(document).ready(function(){
} }
}); });
TS.TimelineView = Backbone.View.extend({ TS.TimelineListView = Backbone.View.extend({
el: $("#timeline"), el: $("#timeline"),
model: TS.TimelineModel, collection: TS.TimelineList,
events: { events: {
"dblclick .timeline-id" : "editId", "dblclick .timeline-id" : "editId",
@ -178,18 +188,31 @@ $(document).ready(function(){
"keypress .timeline-desc-input" : "updateOnEnter" "keypress .timeline-desc-input" : "updateOnEnter"
}, },
initialize: function() { initialize: function(options) {
_.bindAll(this, 'render', 'close', 'editId', 'editDesc', _.bindAll(this, 'render', 'renderOne', 'editId',
'updateOnEnter'); 'editDesc', 'updateOnEnter');
this.model.bind('change', this.render);
this.model.view = this; if (options.initialTimelineId == undefined) {
throw "Can not create a TimelineListView without an initial timeline."
} else {
this.selected = this.collection.get(options.initialTimelineId);
}
this.collection.bind('add', this.renderOne);
this.collection.bind('refresh', this.render);
},
renderOne: function(timeline) {
this.$('.drop-menu-items').append(
ich.timelineLinkTemplate(timeline.toJSON()));
}, },
render: function() { render: function() {
this.$('.timeline-id').html('(&nbsp;' + // render the basic template
this.model.get('id') + '&nbsp;)'); $(this.el).html(ich.timelineTemplate(this.selected.toJSON()));
this.$('.timeline-desc').text(this.model.get('desc'));
return this; // render the selection list
_.each(this.collection.without([this.selected]), this.renderOne);
}, },
editId: function() { editId: function() {
@ -205,39 +228,17 @@ $(document).ready(function(){
}, },
close: function() { close: function() {
this.model.save({ this.selected.save({
id: this.$('timeline-id-input').val(), id: this.$('.timeline-id-input').val(),
desc: this.$('.timeline-desc-input').val()}); description: this.$('.timeline-desc-input').val()});
$(this.el).removeClass('.edit-id .edit-desc'); $(this.el).removeClass('edit-id edit-desc');
this.render();
}, },
updateOnEnter: function(e) { updateOnEnter: function(e) {
if (e.keyCode == 13) this.close(); if (e.keyCode == 13) this.close();
} }
});
TS.TimelineListView = Backbone.View.extend({
el: $("#timeline .drop-menu-items"),
collection: TS.TimelineList,
initialize: function() {
_.bindAll(this, 'render', 'renderOne');
this.collection.bind('add', this.renderOne);
this.collection.bind('refresh', this.render);
this.collection.view = this;
},
renderOne: function(timeline) {
if (!timeline.view) { new TS.TimelineView(timeline); }
$(this.el).append(ich.timelineLink(timeline.toJSON()));
},
render: function() {
$(this.el).remove(".timeline-link");
this.collection.each(this.renderOne);
return this;
}
}); });
TS.UserView = Backbone.View.extend({ TS.UserView = Backbone.View.extend({
@ -258,25 +259,24 @@ $(document).ready(function(){
}, },
render: function() { render: function() {
this.$('.fullname').text(this.model.get('name')); $(this.el).html(ich.userTemplate(this.model.toJSON()));
this.$('.username').text(" - " + this.model.get('id'));
return this; return this;
}, },
editFullname: function() { editFullname: function() {
$(this.el).addClass('.edit-fullname'); $(this.el).addClass('edit-fullname');
this.$('.fullname-input').focus(); this.$('.fullname-input').focus();
return this; return this;
}, },
close: function() { close: function() {
this.model.set({name: this.$('.fullname-input').val()}); this.model.set({name: this.$('fullname-input').val()});
this.model.save(); this.model.save();
$(this.el).removeClass('.edit-fullname'); $(this.el).removeClass('edit-fullname');
}, },
updateOnEnter: function(e) { updateOnEnter: function(e) {
if (keyCode == 13) this.close(); if (e.keyCode == 13) this.close();
} }
}); });
@ -285,36 +285,110 @@ $(document).ready(function(){
el: $("body"), el: $("body"),
events: { events: {
'click #timeline .drop-menu-items a': 'selectTimeline', 'click #timeline .drop-menu-items a': 'selectTimeline'
'keypress #new-entry-input' : 'newTimestamp',
}, },
initialize: function() { initialize: function() {
_.bindAll(this, 'render');
_.bindAll(this, 'initializeViews', 'loadInitialData');
appThis = this;
// create the login dialog
this.loginDialog = new TS.LoginView
if (window.bootstrap) { this.initializeData(window.bootstrap()) }
else {
// this is async (waiting for user input)
this.loginDialog.authenticate(function() {
appThis.initializeData(appThis.loadInitialData())});
}
}, },
renderTimelineList: function() { initializeData: function(data) {
var tlUL = this.$('#timeline ul.drop-menu-items');
//var curTimeline = // create user data
//var remTimelines = TS.user.timelines.filter(function(timeline) this.user = {};
} this.user.model = new TS.UserModel(data.user);
this.user.view = new TS.UserView({model: this.user.model});
// create timeline models from the bootstrapped data
var tlModels = _.map(data.timelines, function(timeline) {
return new TS.TimelineModel(timeline);
}); });
// wire the login dialog using jQuery UI // create the timeline list collection
$("#login-dialog").dialog({ this.timelines = {};
this.timelines.collection = new TS.TimelineList(
tlModels, {user: this.user.model});
this.timelines.view = new TS.TimelineListView(
{collection: this.timelines.collection,
initialTimelineId: data.initialTimelineId});
// create entry models from the bootstrapped data
var entryModels = _.map(data.entries, function(entry) {
return new TS.EntryModel(entry);
});
// create the entry collection
this.entries = {};
this.entries.collection = new TS.EntryList(entryModels,
{timeline: this.timelines.view.selected});
this.entries.view = new TS.EntryListView(
{collection: this.entries.collection});
// render views
this.user.view.render();
this.timelines.view.render();
this.entries.view.render();
},
loadInitialData: function() {
// assume we are authenticated
var username = $("#login-name").val(); // hackish
var data = jQuery.parseJSON($.ajax({
url: '/ts_api/app/user_summary/' + username,
async: false}).responseText);
data.initialTimelineId = data.timelines[0].id;
data.entries = jQuery.parseJSON($.ajax({
url: '/ts_api/entries/' + username + '/' +
data.initialTimelineId,
async: false}).responseText);
return data;
}
});
TS.LoginView = Backbone.View.extend({
el: $("#login-dialog"),
initialize: function() {
_.bindAll(this, 'doLogin', 'authenticate');
var viewThis = this;
$(this.el).dialog({
autoOpen: false, autoOpen: false,
height: 400, height: 400,
width: 400, width: 400,
modal: true, modal: true,
buttons: { Login: function(){login()} } buttons: { Login: viewThis.doLogin}
}); });
},
$('#login-dialog').dialog('open'); action: function() {},
}) authenticate: function(nextAction) {
this.action = nextAction;
$(this.el).dialog("open");
},
function login() { doLogin: function(){
// lookup the login dialog elements var viewThis = this;
var name = $("#login-name"); var name = $("#login-name");
var pwd = $("#login-password"); var pwd = $("#login-password");
@ -324,6 +398,7 @@ function login() {
processData: false, processData: false,
data: JSON.stringify({username: name.val(), password: pwd.val()}), data: JSON.stringify({username: name.val(), password: pwd.val()}),
type: "POST", type: "POST",
async: false,
error: function(jqXHR, textStatus, error) { error: function(jqXHR, textStatus, error) {
// assuming bad credentials (possible server error or bad request, // assuming bad credentials (possible server error or bad request,
@ -335,21 +410,27 @@ function login() {
}, },
success: function(data, textStatus, jqXHR) { success: function(data, textStatus, jqXHR) {
$(viewThis.el).dialog("close");
viewThis.action()
}
});
}
});
// initialize the app data TS.app = new TS.AppView;
// TODO: possiblty replace by script generated server-side
// create the user model })
TS.user = new TS.UserModel({
id: name.val(),
name: '' });
// fetch the initial user data from the server function getUTCTimestamp() {
TS.user.fetch(); var d = new Date();
// create the user view function pad(n){return n<10 ? '0'+n : n}
new TS.UserView({model: TS.user});
TS.user.view.render();
}}); return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z';
} }