From 39c3b83d3f402300521e9be380b6c2dc59df8bbb Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Tue, 8 Mar 2011 18:02:33 -0600 Subject: [PATCH] Implemented edit and update for entries. - Added ts_entry:delete/1 to delete an entry from the database. - Implemented ts_api:delete_entry/3. - Added a form to facilitate editing individual entries. - Moved the small show/hide functions directly into the HTML. - Wired up the update timeline form. - Wired up the edit and update entry form. --- db/test/DECISION_TAB.LOG | Bin 153 -> 156 bytes db/test/LATEST.LOG | Bin 92 -> 92 bytes db/test/id_counter.DCD | Bin 130 -> 130 bytes db/test/id_counter.DCL | Bin 169 -> 0 bytes db/test/ts_entry.DCD | Bin 2615 -> 278 bytes db/test/ts_entry.DCL | Bin 200 -> 859 bytes src/ts_api.erl | 17 ++++++- src/ts_entry.erl | 5 +- www/css/ts-screen.css | 9 +++- www/css/ts-screen.scss | 15 +++++- www/js/ts.js | 97 ++++++++++++++++++++++++++++----------- www/ts/index.yaws | 54 ++++++++++++++++------ 12 files changed, 150 insertions(+), 47 deletions(-) delete mode 100644 db/test/id_counter.DCL diff --git a/db/test/DECISION_TAB.LOG b/db/test/DECISION_TAB.LOG index 9c6ae28d9c58c0d74b08cdb7807c8928a32da97f..b27af2211f86729971455b5850e1a23620f39057 100644 GIT binary patch delta 29 kcmbQqIEQgUI1lH9&q)j%37rfK45ky4joFeI7#Q`k0Dlq(X8-^I delta 26 hcmbQkIFoTgI1h)sYZ3#S;YS7r2BV3|#>|O#vjAGK2PFUi diff --git a/db/test/LATEST.LOG b/db/test/LATEST.LOG index 874dd040fa9ad05c6ce705a01e699c30473009d5..ffa11e23d51e49a5585ea62d5b6257b7183e015f 100644 GIT binary patch delta 13 Ucma!vnGnLkIpK2>1AAU103YWBVE_OC delta 13 Ucma!vnGnLkA@7>Rz`Elm02#sr2><{9 diff --git a/db/test/id_counter.DCD b/db/test/id_counter.DCD index 7a3d9f7315a8a426dfe720e389f88da28a01e5ca..ab5b8072192f0b66ddcacd089c8392c92e68fee8 100644 GIT binary patch delta 20 bcmZo-Y+{@c#KAe?a}oo4Ud+TObw*VHL3ah{ delta 20 bcmZo-Y+{@c#K9pqF^PfAwR&QdI-?>0H){n1 diff --git a/db/test/id_counter.DCL b/db/test/id_counter.DCL deleted file mode 100644 index 54c43c268d14bcc7877892c7797e5d7436ebf94b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169 zcmZQ%VrEH>@a1M;VDL%`_i=2_U`t`(%E?cU&qz&7Ni9lYU{6WTi3bW~GcX(K8DulC zndq758Jear@aE;`<)@@NYTyl4gnhP25Sm^9p!@>m(fjb0z)%Vv=D4Dm?KDX>y-%_~VQ z%FIhwD9KFDPAw_c%Vv=B%P&zVN=?kksnk>ODlINiNXsu$D9*?)*8>{m1~N)X8EDje dGq6#jA(^?U!6k{g1*t_=3L&Y*B|zi!vH+#mDp~*l literal 2615 zcmbuB%WG3X6vn4bU+E)lZL6)R?F0okC0eK`K1hpwcuOB>0x7ttlRJ~#+ndaUdnb+A zh#;=qxpD786huK6K0(}wAcB8{E(F)EJu_3PD8(s(kdTn?H{W^8Ik%-X*5+=k_8^3o z3;C6~TV4l6-DOeQ^cbNmq^Og+bQ69EP;5GVGC&6!HODT?~I;DWMQE<6!QFIGUP zeW-xCk`LhR-gzLd8e%&|T{7BaT!sxVMp1l=7FfthNGWQoi!dOFx1+1>*AIyR_2pP3 zvHmZfPQ&*ssZ`4hb0Jxj2580&4<`kXo|V4q7C7KzK!TVTCx%Z>qi;E`q@%l=^(?*R|ch>lSD z6^84+^h`V{I5T5=W*eOO!&X<=+#rGr8&Vf`hPHFs7B&K~ih*_Hy+$UZ(_&rogCL)Jt<#cRC5-~ZqzF?P6YLTf zieC4tES=VtW^FAU0%qAT`*UIA?@XVw<%|O7v*C2l!BWyy*H)}Y(ikAV8ANA+lu3yb zRjSLj77l~{+8dpo!MsPLZeXEWP;eO7ec7sCEH-{GNb9an0{E2yCmh)QBC0Z1`husF zzYDhh#sQOgtNrz^FnK(}loe{`jykrGBLKN+Afvk-J!Mv9kukMIbk^r>ffE3H`cAtV za$w#2Jirbv`qvr7zSI%kv1LsH>!V?fI(XihPo;nbpLo&PSeVC7PCcc}X6uYe7*QmQ z)biUBaJOMayP_6Gs$4$DWnW5oRto*?TA4}6l&EuDX<+>X0!g@a1M;VDL%`_i=2_U`t`(%E?cU&qz&7Ni9lYU{6WTi3bW~GcX(K8DulC zndq758Jear@aE;`<)@@N#R&jKC<1o? delta 56 zcmcc3c7kz25D$mEYZ3$Njyntt3~3YNv=|j9b}Gv#=CLxQAANa@FPnkgKTn|~zd$i7 Mg@LuaD6=FL0N;EOH~;_u diff --git a/src/ts_api.erl b/src/ts_api.erl index e40f760..b7cc81d 100644 --- a/src/ts_api.erl +++ b/src/ts_api.erl @@ -482,7 +482,22 @@ post_entry(YArg, Username, TimelineId, EntryId) -> _Error -> make_json_500(YArg) end. -delete_entry(_YArg, _Username, _TimelineId, _EntryId) -> todo. +delete_entry(YArg, Username, TimelineId, EntryId) -> + + % find the record to delete + case ts_entry:lookup(Username, TimelineId, EntryId) of + + Record -> + % try to delete + case ts_entry:delete(Record) of + ok -> {status, 200}; + Error -> + io:format("Error occurred deleting entry record: ~p", [Error]), + make_json_500(YArg) + end; + + no_record -> make_json_404(YArg) + end. % ============================== % % ======== UTIL METHODS ======== % diff --git a/src/ts_entry.erl b/src/ts_entry.erl index 525077a..8fe9072 100644 --- a/src/ts_entry.erl +++ b/src/ts_entry.erl @@ -1,5 +1,5 @@ -module(ts_entry). --export([create_table/1, new/1, update/1, lookup/3, list_asc/3, list_desc/3]). +-export([create_table/1, new/1, update/1, delete/1, lookup/3, list_asc/3, list_desc/3]). -include("ts_db_records.hrl"). -include_lib("stdlib/include/qlc.hrl"). @@ -35,6 +35,9 @@ lookup(Username, TimelineId, EntryId) -> [Entry] -> Entry end. +delete(ER = #ts_entry{}) -> mnesia:dirty_delete_object(ER). + + list({Username, Timeline}, Start, Length, OrderFun) when is_integer(Start) and is_integer(Length) -> diff --git a/www/css/ts-screen.css b/www/css/ts-screen.css index cffb29f..8189c2a 100644 --- a/www/css/ts-screen.css +++ b/www/css/ts-screen.css @@ -211,7 +211,7 @@ body { background: #b34c2b; color: #c5c5b9; font-weight: bold; - min-width: 2em; + width: 2em; text-align: right; } .entry-bar .details { float: left; } @@ -223,6 +223,13 @@ body { .entry-bar .details .entry-notes { display: none; padding-left: 1.5em; } + .entry-bar .entry-edit { + display: none; } + .entry-bar .entry-edit .id { + width: 2em; + padding: 0.2em 0.5em 0.2em 0.5em; } + .entry-bar .entry-edit .entry-notes { + padding: 0; } .top-entry { -moz-border-radius-topleft: 0.5em; diff --git a/www/css/ts-screen.scss b/www/css/ts-screen.scss index 14d5f7c..a294e05 100644 --- a/www/css/ts-screen.scss +++ b/www/css/ts-screen.scss @@ -264,7 +264,7 @@ body { background: $obor; color: lighten($greyTxt, 40%); font-weight: bold; - min-width: 2em; + width: 2em; text-align: right; } @@ -283,6 +283,19 @@ body { padding-left: 1.5em; } } + + .entry-edit { + display: none; + + .id { + width: 2em; + padding: 0.2em 0.5em 0.2em 0.5em; + } + + .entry-notes { + padding: 0; + } + } } .top-entry { diff --git a/www/js/ts.js b/www/js/ts.js index fc062f6..753d3c5 100644 --- a/www/js/ts.js +++ b/www/js/ts.js @@ -25,6 +25,9 @@ $(document).ready(function(){ buttons: { Login: function(){login()} } }); + // TODO: add a hook to AJAX requests to check for 401 unauth + // and re-display the login dialog. + // try to load user information for an authenticated user $.ajax({ url: "/ts_api/users/", @@ -109,6 +112,7 @@ function loadUser(username) { // update the timeline display $("#timeline-name").text(activeTimeline.timeline_id + " |"); $("#timeline-desc").text(activeTimeline.description); + $("#timeline-desc-input").val(activeTimeline.description); // TODO: populate the drop-down list for the available timeline // choices @@ -205,27 +209,12 @@ function displayOlderEntries(entries) { }); } -/* Show/hide the editable user-info panel. */ -function toggleUserInfo(event) { - $("#user-info").slideToggle("slow"); - event.preventDefault(); -} - -/* Show/hide the password change controls. */ -function showChangePwd(event) { $("#change-pwd").slideToggle("slow"); } - /* Update the user information based on the editable user-info panel. */ function updateUser(event) { alert("TODO: update user via AJAX."); event.preventDefault(); } -/* Show/hide the editable timeline-info panel. */ -function toggleTimelineInfo(event) { - $("#timeline-info").slideToggle("slow"); - event.preventDefault(); -} - /* Show the change timeline menu. */ function showTimelineMenu(event) { alert("TODO: show other timelines via a popup menu"); @@ -234,22 +223,24 @@ function showTimelineMenu(event) { /* Update the timeline details based on the editable timeline-info panel. */ function updateTimeline(event) { - alert("TODO: update timeline via AJAX."); - event.preventDefault(); -} + var desc = $("#timeline-desc-input").val(); -/* Show/hide the add notes panel. */ -function showNewNotes(event) { $("#add-notes").slideToggle("slow"); } + $.ajax({url: "/ts_api/timelines/" + user.username + + "/" + activeTimeline.timeline_id, + type: "POST", + data: JSON.stringify({desc: desc, created: activeTimeline.created}), -function toggleEntryNotes(event, entryId) { - var selector = "#" + entryId + " .entry-notes"; - $(selector).slideToggle("slow"); - event.preventDefault(); -} + error: function(jqXHR, textStatus, error) { + // TODO: better error handling + alert("Error updating timeline: \n" + jqXHR.responseText); }, + + success: function(data, testStatus, jqXHR) { + // TODO: check for appropriate data.status value + + // update display + $("#timeline-desc").text(data.timeline.description); + }}); -function editEntry(event, entryId) { - var selector = "#" + entryId; - alert("TODO: implement edit entry. Called for '" + selector + "'"); event.preventDefault(); } @@ -293,9 +284,59 @@ function newEntry(event) { event.preventDefault(); } +function toggleEditEntry(event, entryId) { + $("#entry-" + entryId + " .entry-display").toggle(); + $("#entry-" + entryId + " .entry-edit").toggle(); + event.preventDefault(); +} + +function updateEntry(event, entryId) { + + var mark = $("#entry-" + entryId + "-mark-input").val(); + var notes = $("#entry-" + entryId + "-notes-input").val(); + var timestamp = getUTCTimestamp(); // TODO: define and read from input element + + var payload = JSON.stringify( + { mark: mark, notes: notes, timestamp: timestamp }); + + $.ajax({url: "/ts_api/entries/" + user.username + + "/" + activeTimeline.timeline_id + + "/" + entryId, + type: "POST", + data: payload, + + error: function(jqXHR, textStatus, error) { + // TODO: error handling + alert("Error updating entry: \n" + jqXHR.responseText); }, + + success: function(data, textStatus, jqXHR) { + // TODO: check that data.status is appropriate + + // update the entry display + $("#entry-" + entryId + " .entry-mark").text(data.entry.mark); + $("#entry-" + entryId + " .entry-notes").text(data.entry.notes); + }}); + + toggleEditEntry(event, entryId); +} + /* Delete an entry. */ function deleteEntry(event, entryId) { + $.ajax({url: "/ts_api/entries/" + user.username + + "/" + activeTimeline.timeline_id + + "/" + entryId, + type: "DELETE", + + error: function(jqXHR, textStatus, error) { + // TODO: error handling + alert("Error updating entry: \n" + jqXHR.responseText); }, + success: function(data, textStatus, jqXHR) { + $("#entry-" + entryId).slideUp('slow', + function() {$("#entry-" + entryId).remove(); }); + }}); + + event.preventDefault(); } /* Generate a UTC timestamp string in ISO format. diff --git a/www/ts/index.yaws b/www/ts/index.yaws index 5254a4e..57fc4c4 100644 --- a/www/ts/index.yaws +++ b/www/ts/index.yaws @@ -16,18 +16,39 @@ @@ -40,7 +61,8 @@ - no_user @@ -74,7 +96,7 @@ @@ -93,7 +115,8 @@ timeline description @@ -122,7 +145,8 @@ class="form-submit" type="submit" value="create entry"/>