From f3ef7db088c0b6871ddc7b6f54cabb53254d9860 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Fri, 17 Jun 2011 16:02:26 -0500 Subject: [PATCH] Work on front-side UI. * Resolved D0003: Add day separators. * Created ``daySeparatorTemplate`` for ICanHaz templating. * Refactored ``EntryListView.render`` to spit out day separators in between days on the timeline. Fixed the "Today" separator to the top of the entry container. We no longer prepend entries to the entry container, we now put them after the top separator in the entry container. * Created ``EntryListView.formatDaySeparator`` to format the labels according to the relative time to today: "Yesterday", "Last Monday", "Friday, May 28" for example. * Removed the cludgier ``toWords``, ``daysApart``, and `` capitalize`` functions that were going to serve the same purpose. * Resolved D0021: Constrain notes width to mark. --- .ide/vim-views/index.yaws.view | 6 +- .ide/vim-views/ts-screen.scss.view | 16 +-- db/test/DECISION_TAB.LOG | Bin 156 -> 156 bytes db/test/LATEST.LOG | Bin 812 -> 331 bytes db/test/id_counter.DCD | Bin 130 -> 130 bytes db/test/id_counter.DCL | Bin 0 -> 169 bytes db/test/ts_entry.DCD | Bin 3692 -> 4267 bytes db/test/ts_entry.DCL | Bin 0 -> 494 bytes db/test/ts_ext_data.DCD | Bin 316 -> 320 bytes db/test/ts_ext_data.DCL | Bin 594 -> 0 bytes db/test/ts_user.DCD | Bin 257 -> 257 bytes db/test/ts_user.DCL | Bin 492 -> 0 bytes .../desktop/{0003tn3.rst => 0003ts3.rst} | 7 +- doc/issues/desktop/0009tn3.rst | 3 + .../desktop/{0021tn5.rst => 0021ts5.rst} | 2 +- doc/issues/desktop/0022bn5.rst | 2 + doc/issues/desktop/0024tn5.rst | 11 ++ doc/issues/desktop/0025tn5.rst | 21 ++++ doc/issues/desktop/0026fn4.rst | 16 +++ doc/issues/desktop/0027fn4.rst | 12 ++ www/css/ts-screen.css | 3 +- www/css/ts-screen.scss | 1 + www/index.yaws | 13 +- www/js/ts.js | 116 ++++++++---------- 24 files changed, 147 insertions(+), 82 deletions(-) create mode 100644 db/test/id_counter.DCL create mode 100644 db/test/ts_entry.DCL delete mode 100644 db/test/ts_ext_data.DCL delete mode 100644 db/test/ts_user.DCL rename doc/issues/desktop/{0003tn3.rst => 0003ts3.rst} (68%) rename doc/issues/desktop/{0021tn5.rst => 0021ts5.rst} (88%) create mode 100644 doc/issues/desktop/0024tn5.rst create mode 100644 doc/issues/desktop/0025tn5.rst create mode 100644 doc/issues/desktop/0026fn4.rst create mode 100644 doc/issues/desktop/0027fn4.rst diff --git a/.ide/vim-views/index.yaws.view b/.ide/vim-views/index.yaws.view index d626383..5d0f577 100644 --- a/.ide/vim-views/index.yaws.view +++ b/.ide/vim-views/index.yaws.view @@ -95,12 +95,12 @@ setlocal nowinfixwidth setlocal wrap setlocal wrapmargin=0 silent! normal! zE -let s:l = 1 - ((0 * winheight(0) + 36) / 72) +let s:l = 104 - ((59 * winheight(0) + 35) / 71) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -1 -normal! 0 +104 +normal! 038l lcd /mnt/secure/projects/jdb-labs/timestamper/web-app/www let &so = s:so_save | let &siso = s:siso_save doautoall SessionLoadPost diff --git a/.ide/vim-views/ts-screen.scss.view b/.ide/vim-views/ts-screen.scss.view index 9ef293d..8238af8 100644 --- a/.ide/vim-views/ts-screen.scss.view +++ b/.ide/vim-views/ts-screen.scss.view @@ -1,6 +1,6 @@ let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 argglobal -edit ~/projects/jdb-labs/timestamper/web-app/www/css/ts-screen.scss +edit /mnt/secure/projects/jdb-labs/timestamper/web-app/www/css/ts-screen.scss setlocal keymap= setlocal noarabic setlocal autoindent @@ -26,8 +26,8 @@ setlocal nodiff setlocal equalprg= setlocal errorformat= setlocal expandtab -if &filetype != 'scss' -setlocal filetype=scss +if &filetype != '' +setlocal filetype= endif setlocal foldcolumn=0 setlocal foldenable @@ -83,8 +83,8 @@ setlocal statusline= setlocal suffixesadd= setlocal swapfile setlocal synmaxcol=3000 -if &syntax != 'scss' -setlocal syntax=scss +if &syntax != 'sass' +setlocal syntax=sass endif setlocal tabstop=4 setlocal tags= @@ -95,12 +95,12 @@ setlocal nowinfixwidth setlocal wrap setlocal wrapmargin=0 silent! normal! zE -let s:l = 120 - ((39 * winheight(0) + 23) / 46) +let s:l = 392 - ((46 * winheight(0) + 35) / 71) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -120 -normal! 012l +392 +normal! 022l let &so = s:so_save | let &siso = s:siso_save doautoall SessionLoadPost " vim: set ft=vim : diff --git a/db/test/DECISION_TAB.LOG b/db/test/DECISION_TAB.LOG index ad60397f198dc7ba7bafd853ec47e34328423e9d..e20cccec403ecbd51f00df89b0de88f01555bfbd 100644 GIT binary patch delta 22 ecmbQkIEQgUI0vhJd=dl4&KDEot(ZB#X8{0DNC$5K delta 22 dcmbQkIEQgUI0p;+mLvv7==C}?_*Nu=EzD((#=UsDo*sC{Dw(Z h9f_aE$`EE#aGWojfhD*kzaT4xfwjCSvm`YO2mqY88;$?~ literal 812 zcmbVKJ!n)x5T1KK_wEuBgou^G6=`e^j8|wQNfZPLX%bB#<~f&Hv-|eF-LSitc#Vx< zl{8iXYb#5QU?o<;(oPf zd6+EmoAxX-!#nbX;CJ!D&wc#W?)}rZ)+avio&UPM{BHimm*)@qWn%L2Wb4kGrFd~l z?Z1}yF7G@#=x2*BKgomrtEYAzZaurX`SGcQ6IZlC$5FK|;kuyKY$dCNiJuZruNEls zws(aG18bAF7+}Oh9L00!-LJ&T{PVo;|IcXOxior2khj05TzPN<*9YbbDy98n5-p+?+Y&w*!Buu@;o zHGqS_(;`!l;Efj^>4<^$RIFy;UN literal 0 HcmV?d00001 diff --git a/db/test/ts_entry.DCD b/db/test/ts_entry.DCD index 1141c0b97836f058bfba930c26e0c6520d02886e..2a952c804108be41f325d19c3e6f4844e5818f30 100644 GIT binary patch delta 375 zcmY+Aze)o^5Qk65VUQqNXr(f0aTXGyA)tp%H2!NWlAw)+=k1s~&+M$bd&E=*pTL;M zu!=r}4-q@D^Br_9f?zlNKIR*K^R@82{8%rzzPWVrFYAuuJPc+EE5lyoPMl{`zc;n9 zCtYXho!+Js$7{xIY}lZ!Q2S6Tl}cqFszQJWx?oTRIwdL6m_e2&Ex z)~(I$a(bE@yK)Un>YB+YBlk5Xiyvb$f80F68|A|p=_HmdSl!wzZx<8isgAcP8Vi;H z@4}l@AlL}O)09eq0z%Rfwef(IjY-0lrZ$ikoIz?bm5pKpieoCm30W|yM(7~ygn z%md2=S;j}g2*U(Av5lZAZA7vQod_lH%@$e%u`K>o+vft`pZ}|kOV1uK8J1P{z~9n8 DGm&)r delta 32 ocmZ3j_(ok diff --git a/db/test/ts_entry.DCL b/db/test/ts_entry.DCL new file mode 100644 index 0000000000000000000000000000000000000000..23a3c9d6d12bdffd9501c29d95e562888c291c39 GIT binary patch literal 494 zcmb8rF;2rU6b9f&)06;$6EOG!jgqP$(Jnwc&Jpkg99LO z1ula{hccnCKE3xo{r_Gk=`J7djsRfJ9&WE*Wsk$5!RJZ}%7x>w&zGi(0}V-;7aDrQ ze3+L54#yTPa&c)5C^OE?IZ?{eeWkmEoZcv7$-jQ9N%PhMgdNatdu0(oW!JJ03^ZJ6r5de5?~d?0XV~opd0{N1Qi8H2rPTw6W-X^$bKl$&~POVh$R}RfSPvx z)3mA^uP=H4XZGs+^v%r)dm-Ix$A&l)7BmK30S~nrjy&e;VLhyl3CoybB0h=9r6NvQ zV0LKHE#57fe!nKZekLl{5_&0`pGA`q<64j14O!07WFj1Jl>AcZF+7zi#p2W-4WYI* u9y@n8m*rN{!4%OlJ#d&J|1{yd+N0a1?7y`B+wUI@a1M;VDL%`_i=2_U`t`(%E?cU&qz&7Ni9lYU{6WTi3bW~GcX(K8DulC zndq7585*T9@aE;`<)@@NELpO;vYk(j68l313R zqTmFvGMhmdZoNZ#ZenJRUUGhJ1{2u%?6(t{5?L~s6S)&D5`jKsEicL}NgXyG0RU%3 Bu3-QG diff --git a/doc/issues/desktop/0003tn3.rst b/doc/issues/desktop/0003ts3.rst similarity index 68% rename from doc/issues/desktop/0003tn3.rst rename to doc/issues/desktop/0003ts3.rst index 4e68438..fa9d5b0 100644 --- a/doc/issues/desktop/0003tn3.rst +++ b/doc/issues/desktop/0003ts3.rst @@ -4,7 +4,12 @@ Generate day seperators. When generating EventViews in the EventListView, we need to automatically create and insert day seperators (see prototype). +Resolution +---------- + +Day separators are added to the timeline by EntryListView.render. + ========= ========== Created: 2011-05-15 -Resolved: YYYY-MM-DD +Resolved: 2011-05-17 ========= ========== \ No newline at end of file diff --git a/doc/issues/desktop/0009tn3.rst b/doc/issues/desktop/0009tn3.rst index 07d4856..cd6ad74 100644 --- a/doc/issues/desktop/0009tn3.rst +++ b/doc/issues/desktop/0009tn3.rst @@ -2,6 +2,9 @@ Implement correct start time editor. ==================================== The start time input field needs to look the same as the start time view. +Alternatively, use a date picker. + +---- ========= ========== Created: 2011-05-15 diff --git a/doc/issues/desktop/0021tn5.rst b/doc/issues/desktop/0021ts5.rst similarity index 88% rename from doc/issues/desktop/0021tn5.rst rename to doc/issues/desktop/0021ts5.rst index 81aaf2f..4d7fd24 100644 --- a/doc/issues/desktop/0021tn5.rst +++ b/doc/issues/desktop/0021ts5.rst @@ -3,5 +3,5 @@ Constrain width of notes fields to width of mark. ========= ========== Created: 2011-06-10 -Resolved: YYYY-MM-DD +Resolved: 2011-06-17 ==================== \ No newline at end of file diff --git a/doc/issues/desktop/0022bn5.rst b/doc/issues/desktop/0022bn5.rst index cecafa7..9e90f28 100644 --- a/doc/issues/desktop/0022bn5.rst +++ b/doc/issues/desktop/0022bn5.rst @@ -4,6 +4,8 @@ Deleting an entry should cascade delete extended data. Currently the data remains in the database. It should not cause any problems, but it is wasting space. +---- + ========= ========== Created: 2011-06-15 Resolved: YYYY-MM-DD diff --git a/doc/issues/desktop/0024tn5.rst b/doc/issues/desktop/0024tn5.rst new file mode 100644 index 0000000..9505e35 --- /dev/null +++ b/doc/issues/desktop/0024tn5.rst @@ -0,0 +1,11 @@ +Hide day separators when all entries that day are excluded. +=========================================================== + +We should hide headings when there is no visible data. + +---- + +========= ========== +Created: 2011-06-17 +Resolved: YYYY-MM-DD +========= ========== \ No newline at end of file diff --git a/doc/issues/desktop/0025tn5.rst b/doc/issues/desktop/0025tn5.rst new file mode 100644 index 0000000..2088fe6 --- /dev/null +++ b/doc/issues/desktop/0025tn5.rst @@ -0,0 +1,21 @@ +Never animate excluded entries. +=============================== + +We need to have some visible indication when a user enters an +exlucded item that it was added, but it looks ugly and dirty when +we first render the list. + +Part of this is motivated by the fact that entering an excluded +entry is the excpected way for a user to stop the timer on an item +without having an explicit next item. + +If we choose to implement *D0026* this would free up the UI a bit. +In that case, we could gently flash the 'Show/Hide Excluded Items' +button (*D0027*). + +---- + +========= ========== +Created: 2011-06-17 +Resolved: YYYY-MM-DD +========= ========== \ No newline at end of file diff --git a/doc/issues/desktop/0026fn4.rst b/doc/issues/desktop/0026fn4.rst new file mode 100644 index 0000000..24985b8 --- /dev/null +++ b/doc/issues/desktop/0026fn4.rst @@ -0,0 +1,16 @@ +Add a default 'stop' behaviour. +=============================== + +It might be more natural to allow the user to hit a button on +the current entry to stop the timer on it than to explicitly +create a new excluded entry. + +Maybe have a default exclusion for all users, "ENTRY STOP" for example, +and have the button automatically add this entry. + +---- + +========= ========== +Created: 2011-06-17 +Resolved: YYYY-MM-DD +========= ========== \ No newline at end of file diff --git a/doc/issues/desktop/0027fn4.rst b/doc/issues/desktop/0027fn4.rst new file mode 100644 index 0000000..83e7b5e --- /dev/null +++ b/doc/issues/desktop/0027fn4.rst @@ -0,0 +1,12 @@ +Create a way to unhide excluded entries. +======================================== + +A button somewhere would be a good way to allow users to +show/hide excluded entries. + +---- + +========= ========== +Created: 2011-06-17 +Resolved: YYYY-MM-DD +========= ========== \ No newline at end of file diff --git a/www/css/ts-screen.css b/www/css/ts-screen.css index e2e1601..319656a 100644 --- a/www/css/ts-screen.css +++ b/www/css/ts-screen.css @@ -297,7 +297,8 @@ input { font-family: Cantarell; font-size: small; margin: 0; - padding: 0 0 0 1em; } + padding: 0 0 0 1em; + width: 70%; } #entry-list .entry .notes :first-child { margin-top: 0; } #entry-list .entry .notes .notes-input, #entry-list .entry .notes pre, #entry-list .entry .notes code { diff --git a/www/css/ts-screen.scss b/www/css/ts-screen.scss index c0526c4..2d7f4e0 100644 --- a/www/css/ts-screen.scss +++ b/www/css/ts-screen.scss @@ -389,6 +389,7 @@ input { font-size: small; margin: 0; padding: 0 0 0 1em; + width: 70%; :first-child { margin-top: 0; } diff --git a/www/index.yaws b/www/index.yaws index 62dab6f..d0caebb 100644 --- a/www/index.yaws +++ b/www/index.yaws @@ -99,6 +99,14 @@ out(YArg) -> + + @@ -145,11 +153,6 @@ out(YArg) ->
-
-

Today

-
start
-
duration
-
diff --git a/www/js/ts.js b/www/js/ts.js index 8a9eca1..7e6f300 100644 --- a/www/js/ts.js +++ b/www/js/ts.js @@ -355,8 +355,8 @@ $(document).ready(function(){ // render the element var el = entry.view.render().el; - // add it to the container - this.entryContainer.prepend(el); + // add it to the container after the topmost separator ("Today") + this.topSeparator.after(el); // hide it if excluded if (excluded) { @@ -401,21 +401,67 @@ $(document).ready(function(){ this.entryContainer.empty(); // last day we have printed a separator for - var currentDay = null; - var today = new Date(); + var today = new Date() + var currentDay = this.collection.at(0) ? + this.collection.at(0).get("timestamp"): today; + + // add the top-most day separator + this.topSeparator = ich.daySeparatorTemplate({ + separatorLabel: this.formatDaySeparator(today, today) }); + this.entryContainer.prepend(this.topSeparator); // iterate through the collection and render the elements. 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); - if (currentDay != entry.get('timestamp').getDate()) { - currentDay = entry.get('timestamp').getDate(); - + // we are rendering buttom up, which means we need to insert the + // day separator before the first entry of the *next* period + if (currentDay.getDate() != entry.get("timestamp").getDate()) { + this.topSeparator.after(ich.daySeparatorTemplate( + {separatorLabel: this.formatDaySeparator(today, currentDay)})); + currentDay = entry.get('timestamp'); } this.renderOne(entry, nextEntry); } + }, + + formatDaySeparator: function(today, labelDay) { + + var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', + 'Friday', 'Saturday']; + var months = ['January', 'February', 'March', 'April', 'May', + 'June', 'July', 'August', 'September', 'October', + 'November', 'December']; + + var yearDiff = today.getFullYear() - labelDay.getFullYear(); + var monthDiff = today.getMonth() - labelDay.getMonth(); + var dayDiff = today.getDate() - labelDay.getDate(); + + // more than a calendar year old + if (yearDiff > 0) { + + return days[labelDay.getDay()] + ", " + + months[labelDay.getMonth()] + " " + labelDay.getDate() + + ", " + labelDay.getFullYear(); } + + // same calendar year, more than a week ago + else if (monthDiff > 0 || dayDiff > 7) { + + return days[labelDay.getDay()] + ", " + + months[labelDay.getMonth()] + " " + labelDay.getDate(); } + + // less than a week ago, more than yesterday + else if (dayDiff > 1) { + return "Last " + days[labelDay.getDay()]; } + + // yesterday + else if (dayDiff == 1) { return "Yesterday"; } + + // today + else if (dayDiff == 0) { return "Today"; } + } }); @@ -757,59 +803,3 @@ function dateToJSON(d) { + pad(d.getUTCMinutes())+':' + pad(d.getUTCSeconds())+'Z'; } - -function daysApart(d1, d2) { - var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30]; - - days1 = (d1.getFullYear() * 365) + daysInMonth[d1.getMonth()] + d1.getDate(); - days2 = (d2.getFullYear() * 365) + daysInMonth[d2.getMonth()] + d2.getDate(); - - return days1 - days2; -} - -function getEnglishDate(d) { - if (typeof getEnglishDate.today == 'undefined') { - getEnglishDate.today = new Date() }; - - var yearDiff = today.getFullYear() - d.getFullYear(); - var monthDiff = today.getMonth() - d.getMonth(); - var dayDiff = today.getDate() - d.getDate(); - - if (yearDiff > 1) { return capitalize(toWords(yearDiff)) + " years ago."; } - else if (yearDiff > 0) { return "Last year"; } - else if (monthDiff > 1) { - return capitalize(toWords(monthDiff)) + "months ago."; } - else if (monthDiff > 0) { return "Last month."; } - else if (dayDiff > 0) { - // weeks as 7-day periods - var weekDiff = Math.ceil(dayDiff / 7) - - // adjust for the hard boundary of the weekend - if (today.getDay() > d.getDay()) { weekDiff--; } - - if (weekDiff > 1) { - return capitalize(toWords(weekDiff)) + " weeks ago."; } - else if (weekDiff > 0) { return "Last week."; } - else { return capitalize(toWords(dayDiff)) + " days ago."; } - - } else if (yearDiff < 0 || monthDiff < 0 || daysDiff < 0) { - return "In the future."; } - else { return "Today."; } -} - - -function toWords(i) { - if (typeof toWords.words == 'undefined') { - toWords.words = ['zero','one','two','three','four', 'five','six', - 'seven','eight','nine','ten','eleven','twelve', - 'thirteen', 'fourteen','fifteen','sixteen', - 'seventeen','eighteen','nineteen' ]; - } - - if (i < 20) { return toWords.words[i]; } - else { return i.toString(); } -} - -function capitalize(s) { - return s.slice(0, 1).toUpperCase() + s.slice(1); -}