Duration display, time formatting, UI tweaks.
Client Behaviour (ts.js) ======================== - Created EntryView.getViewModel: translates model data to view data, specifically synthesizes the start time and duration from the timestamp. - Added nextModel option to EntryView, needed for calculating the entry duration. - Created EntryView.formatStart: given the timestamp, return the start time, in HH:MM format. Code is written for both 24hr and 12hr format, still need to write a selector mechanism. For now, uses 12hr format. - Created EntryView.formatDuration: Get the duration of the entry based on this entry's timestamp and and the next entry's timestamp in a display-able form. If nextModel is `null` or `undefined` it is assumed that `model` is the most recent model and duration is calculated against the current time. - Changed EntryView.render to use getViewModel. - Added 'blur' listeners to the mark and timestamp input fields to close them without persisting the changes. - Created EntryView.update: Refresh the display based on the model using the existing DOM elements. - EntryView.save() now uses EntryView.update() instead of EntryView.render() and no longer includes an implicit close() - EntryView.close() has been split into seperate save() and close() functions, to persist the changes and hide the input dialogs, respectively. - EntryListView.addOne now passes the nextModel to EntryViews is creates. - EntryListView.createNewEntryOnEnter() now clear the new intry input after creating a new entry. - EntryListView.render() now uses a for-structure to traverse the entry collection and passes the nextModel (if there is one) to EntryListView.addOne. Client UI (ts-screen.scss) ========================== - Font size, family, and color adjusted on timeline and user input fields. - Day seperator secondary header colors adjusted. - Mark column width shortened, timestamp and duration columns widened. - Styles added for notes UI Client UI (index.yaws) ====================== - Markup changes needed for getViewModel chanes. - Expanded day seperator.
This commit is contained in:
parent
b22c10c6c2
commit
036177cfed
@ -47,6 +47,9 @@ input {
|
|||||||
#timeline .timeline-id {
|
#timeline .timeline-id {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
#timeline .timeline-desc-input, #timeline .timeline-id-input {
|
#timeline .timeline-desc-input, #timeline .timeline-id-input {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
color: #222222;
|
||||||
display: none; }
|
display: none; }
|
||||||
#timeline.edit-id .timeline-id-input {
|
#timeline.edit-id .timeline-id-input {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
@ -117,6 +120,9 @@ input {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: larger; }
|
font-size: larger; }
|
||||||
#user .fullname-input {
|
#user .fullname-input {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
color: #222222;
|
||||||
display: none; }
|
display: none; }
|
||||||
#user.edit-fullname .fullname-input {
|
#user.edit-fullname .fullname-input {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
@ -147,6 +153,8 @@ input {
|
|||||||
padding: 0 2rem; }
|
padding: 0 2rem; }
|
||||||
#entry-list .day-seperator h4, #entry-list .day-seperator h5 {
|
#entry-list .day-seperator h4, #entry-list .day-seperator h5 {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
|
#entry-list .day-seperator h5 {
|
||||||
|
color: #667; }
|
||||||
#entry-list #new-entry {
|
#entry-list #new-entry {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
padding: 0 2em;
|
padding: 0 2em;
|
||||||
@ -154,9 +162,9 @@ input {
|
|||||||
padding: 0 2rem; }
|
padding: 0 2rem; }
|
||||||
#entry-list .timestamp, #entry-list .timestamp-input, #entry-list .duration {
|
#entry-list .timestamp, #entry-list .timestamp-input, #entry-list .duration {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
width: 10%; }
|
width: 14%; }
|
||||||
#entry-list .mark, #entry-list .mark-input {
|
#entry-list .mark, #entry-list .mark-input {
|
||||||
width: 78%; }
|
width: 70%; }
|
||||||
#entry-list .entry {
|
#entry-list .entry {
|
||||||
font-family: Cantarell;
|
font-family: Cantarell;
|
||||||
padding: 0 2em;
|
padding: 0 2em;
|
||||||
@ -165,7 +173,7 @@ input {
|
|||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
#entry-list .entry .mark-input, #entry-list .entry .timestamp-input {
|
#entry-list .entry .mark-input, #entry-list .entry .timestamp-input {
|
||||||
display: none; }
|
display: none; }
|
||||||
#entry-list .entry .notes {
|
#entry-list .entry .notes, #entry-list .entry .notes-input {
|
||||||
display: none; }
|
display: none; }
|
||||||
#entry-list .entry.edit-mark .mark-input {
|
#entry-list .entry.edit-mark .mark-input {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
@ -175,6 +183,8 @@ input {
|
|||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
#entry-list .entry.edit-timestamp .timestamp {
|
#entry-list .entry.edit-timestamp .timestamp {
|
||||||
display: none; }
|
display: none; }
|
||||||
|
#entry-list .entry.edit-notes .notes-input {
|
||||||
|
display: block; }
|
||||||
|
|
||||||
.drop-menu {
|
.drop-menu {
|
||||||
position: relative; }
|
position: relative; }
|
||||||
|
@ -65,7 +65,12 @@ input {
|
|||||||
|
|
||||||
.timeline-id { display: inline-block; }
|
.timeline-id { display: inline-block; }
|
||||||
|
|
||||||
.timeline-desc-input, .timeline-id-input { display: none; }
|
.timeline-desc-input, .timeline-id-input {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
color: $darkBg;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.edit-id {
|
&.edit-id {
|
||||||
.timeline-id-input { display: inline-block; }
|
.timeline-id-input { display: inline-block; }
|
||||||
@ -165,7 +170,12 @@ input {
|
|||||||
font-size: larger;
|
font-size: larger;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullname-input { display: none; }
|
.fullname-input {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
color: $darkBg;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.edit-fullname{
|
&.edit-fullname{
|
||||||
.fullname-input { display: inline-block; }
|
.fullname-input { display: inline-block; }
|
||||||
@ -204,6 +214,8 @@ input {
|
|||||||
padding: 0 2rem;
|
padding: 0 2rem;
|
||||||
|
|
||||||
h4, h5 { display: inline-block; }
|
h4, h5 { display: inline-block; }
|
||||||
|
|
||||||
|
h5 { color: #667; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#new-entry {
|
#new-entry {
|
||||||
@ -216,10 +228,10 @@ input {
|
|||||||
|
|
||||||
.timestamp, .timestamp-input, .duration {
|
.timestamp, .timestamp-input, .duration {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
width: 10%;
|
width: 14%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mark, .mark-input { width: 78%; }
|
.mark, .mark-input { width: 70%; }
|
||||||
|
|
||||||
.entry {
|
.entry {
|
||||||
|
|
||||||
@ -231,7 +243,7 @@ input {
|
|||||||
|
|
||||||
.mark-input, .timestamp-input { display: none; }
|
.mark-input, .timestamp-input { display: none; }
|
||||||
|
|
||||||
.notes { display: none; }
|
.notes, .notes-input { display: none; }
|
||||||
|
|
||||||
&.edit-mark {
|
&.edit-mark {
|
||||||
.mark-input { display: inline-block; }
|
.mark-input { display: inline-block; }
|
||||||
@ -243,6 +255,8 @@ input {
|
|||||||
.timestamp { display: none; }
|
.timestamp { display: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.edit-notes .notes-input { display: block; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
89
www/js/ts.js
89
www/js/ts.js
@ -98,18 +98,31 @@ $(document).ready(function(){
|
|||||||
"keypress .timestamp-input" : "updateOnEnter"
|
"keypress .timestamp-input" : "updateOnEnter"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function(options) {
|
||||||
_.bindAll(this, 'render', 'close', 'editTImestamp',
|
_.bindAll(this, 'render', 'close', 'editTImestamp',
|
||||||
'editMark', 'updateOnEnter');
|
'editMark', 'updateOnEnter', 'getViewModel');
|
||||||
this.model.bind('change', this.render);
|
this.model.bind('change', this.render);
|
||||||
this.model.view = this;
|
this.model.view = this;
|
||||||
|
|
||||||
|
this.nextModel = options.nextModel;
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
$(this.el).html(ich.entryTemplate(this.model.toJSON()));
|
$(this.el).html(ich.entryTemplate(this.getViewModel()));
|
||||||
|
this.$(".mark-input").bind('blur', this.close);
|
||||||
|
this.$(".timestamp-input").bind('blur', this.close);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: function() {
|
||||||
|
var data = this.getViewModel();
|
||||||
|
this.$('.mark').text(data.mark);
|
||||||
|
this.$('.mark-input').val(data.mark);
|
||||||
|
this.$('.timestamp').text(data.start);
|
||||||
|
this.$('.timestamp-input').val(data.timestamp);
|
||||||
|
this.$('.duration').text(data.duration);
|
||||||
|
},
|
||||||
|
|
||||||
editMark: function() {
|
editMark: function() {
|
||||||
$(this.el).addClass('edit-mark');
|
$(this.el).addClass('edit-mark');
|
||||||
this.$('.mark-input').focus();
|
this.$('.mark-input').focus();
|
||||||
@ -122,16 +135,62 @@ $(document).ready(function(){
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getViewModel: function() {
|
||||||
|
var data = this.model.toJSON();
|
||||||
|
|
||||||
|
// create start and duration values
|
||||||
|
var tsDate = new Date(data.timestamp);
|
||||||
|
data.start = this.formatStart(tsDate);
|
||||||
|
data.duration = this.formatDuration(this.model, this.nextModel);
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
close: function() {
|
close: function() {
|
||||||
|
$(this.el).removeClass('edit-mark edit-timestamp');
|
||||||
|
},
|
||||||
|
|
||||||
|
save: function() {
|
||||||
this.model.save({
|
this.model.save({
|
||||||
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.update();
|
||||||
this.render();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateOnEnter: function(e) {
|
updateOnEnter: function(e) {
|
||||||
if(e.keyCode == 13) this.close();
|
if(e.keyCode == 13) { this.save(); this.close(); }
|
||||||
|
},
|
||||||
|
|
||||||
|
formatStart: function(startDate) {
|
||||||
|
// 24 hour
|
||||||
|
// return startDate.getHours() + ":" + startDate.getMinutes();
|
||||||
|
|
||||||
|
// 12 hour
|
||||||
|
var hour = startDate.getHours() % 12;
|
||||||
|
return (hour == 0 ? 12 : hour) + ":" + startDate.getMinutes() +
|
||||||
|
" " + (startDate.getHours() > 11 ? "pm" : "am");
|
||||||
|
},
|
||||||
|
|
||||||
|
formatDuration: function(model, nextModel) {
|
||||||
|
var d1 = new Date(model.get('timestamp'));
|
||||||
|
var d2, diff;
|
||||||
|
var day, hr, min;
|
||||||
|
|
||||||
|
// if no next model, assume it's an onoing task
|
||||||
|
if (nextModel) { d2 = new Date(nextModel.get('timestamp')); }
|
||||||
|
else { d2 = new Date(); }
|
||||||
|
|
||||||
|
diff= d2.getTime() - d1.getTime();
|
||||||
|
day = Math.floor(diff / 86400000); // milliseconds in a day
|
||||||
|
diff %= 86400000;
|
||||||
|
|
||||||
|
hr = Math.floor(diff / 3600000); // millis in an hour
|
||||||
|
diff %= 3600000;
|
||||||
|
|
||||||
|
min = Math.floor(diff / 60000); // millis in a minute
|
||||||
|
|
||||||
|
return (day > 0 ? day + "d " : "") +
|
||||||
|
(hr > 0 ? hr + "hr " : "") +
|
||||||
|
min + "m ";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -151,8 +210,9 @@ $(document).ready(function(){
|
|||||||
this.entryContainer = this.$("#entries")
|
this.entryContainer = this.$("#entries")
|
||||||
},
|
},
|
||||||
|
|
||||||
addOne: function(entry) {
|
addOne: function(entry, nextEntry) {
|
||||||
if (!entry.view) { new TS.EntryView({model: entry}); }
|
if (!entry.view) { new TS.EntryView({model: entry}); }
|
||||||
|
entry.view.nextModel = nextEntry
|
||||||
this.entryContainer.prepend(entry.view.render().el);
|
this.entryContainer.prepend(entry.view.render().el);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -167,12 +227,21 @@ $(document).ready(function(){
|
|||||||
this.collection.create({mark: entryMark,
|
this.collection.create({mark: entryMark,
|
||||||
notes: '',
|
notes: '',
|
||||||
timestamp: getUTCTimestamp()}).fetch();
|
timestamp: getUTCTimestamp()}).fetch();
|
||||||
}
|
|
||||||
|
// clear the input for the next entry
|
||||||
|
this.$("#new-entry-input").val("");
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
this.entryContainer.empty();
|
this.entryContainer.empty();
|
||||||
this.collection.each(this.addOne);
|
for (var i = 0, len = this.collection.length; i < len; i++) {
|
||||||
|
var entry = this.collection.at(i);
|
||||||
|
var nextEntry = (i + 1 < len ? this.collection.at(i + 1) : null);
|
||||||
|
|
||||||
|
this.addOne(entry, nextEntry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -236,7 +305,7 @@ $(document).ready(function(){
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateOnEnter: function(e) {
|
updateOnEnter: function(e) {
|
||||||
if (e.keyCode == 13) this.close();
|
if (e.keyCode == 13) { this.close(); this.save() }
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user