Further updates to page. Small update to internal API.
Internal API update functions now accept partial updates, allowing one to selectively update only some fields of a particular record.
This commit is contained in:
		| @@ -1,5 +1,5 @@ | |||||||
| -module(ts_common). | -module(ts_common). | ||||||
| -export([new/1, update/1, list/3, order_datetimes/2]). | -export([new/1, update/1, update_record/2, list/3, order_datetimes/2]). | ||||||
|  |  | ||||||
| -include_lib("stdlib/include/qlc.hrl"). | -include_lib("stdlib/include/qlc.hrl"). | ||||||
|  |  | ||||||
| @@ -25,9 +25,22 @@ update(Record) -> | |||||||
|         % record does not exist, cannot update |         % record does not exist, cannot update | ||||||
|         [] -> no_record; |         [] -> no_record; | ||||||
|         % record does exist, update |         % record does exist, update | ||||||
|         [_ExistingRecord] -> mnesia:dirty_write(Record) |         [ExistingRecord] -> | ||||||
|  |             mnesia:dirty_write(update_record(ExistingRecord, Record)) | ||||||
|     end. |     end. | ||||||
|  |  | ||||||
|  | update_record(Record, UpdateData) -> | ||||||
|  |     update_record(tuple_to_list(Record), tuple_to_list(UpdateData), []). | ||||||
|  |      | ||||||
|  | update_record([], [], Updated) -> list_to_tuple(lists:reverse(Updated)); | ||||||
|  | update_record([Field|RecordFields], [FieldReplacement|UpdateData], Acc) -> | ||||||
|  |     UpdatedField = case FieldReplacement of | ||||||
|  |         undefined -> Field; | ||||||
|  |         NewValue -> NewValue | ||||||
|  |     end, | ||||||
|  |  | ||||||
|  |     update_record(RecordFields, UpdateData, [UpdatedField|Acc]). | ||||||
|  |  | ||||||
| %% list <Length> number of records, skipping the first <Start> | %% list <Length> number of records, skipping the first <Start> | ||||||
| list(Table, Start, Length) | list(Table, Start, Length) | ||||||
| when is_atom(Table) and is_integer(Start) and is_integer(Length) -> | when is_atom(Table) and is_integer(Start) and is_integer(Length) -> | ||||||
|   | |||||||
| @@ -25,7 +25,8 @@ update(ER = #ts_entry{}) -> | |||||||
|         % record does not exist |         % record does not exist | ||||||
|         [] -> no_record; |         [] -> no_record; | ||||||
|         % record exists, update it |         % record exists, update it | ||||||
|         [_Record] -> mnesia:dirty_write(ER) |         [ExistingRecord] -> | ||||||
|  |             mnesia:dirty_write(ts_common:update_record(ExistingRecord, ER)) | ||||||
|     end. |     end. | ||||||
|  |  | ||||||
| lookup(Username, TimelineId, EntryId) -> | lookup(Username, TimelineId, EntryId) -> | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ ejson_to_record(_Empty=#ts_timeline{}, EJSON) -> | |||||||
|     {struct, Fields} = EJSON, |     {struct, Fields} = EJSON, | ||||||
|  |  | ||||||
|     #ts_timeline{ |     #ts_timeline{ | ||||||
|         ref = {undef, undef}, |         ref = {undefined, undefined}, | ||||||
|         created = decode_datetime(element(2, lists:keyfind(created, 1, Fields))), |         created = decode_datetime(element(2, lists:keyfind(created, 1, Fields))), | ||||||
|         desc = element(2, lists:keyfind(description, 1, Fields))}; |         desc = element(2, lists:keyfind(description, 1, Fields))}; | ||||||
|  |  | ||||||
| @@ -55,7 +55,7 @@ ejson_to_record(_Empty=#ts_entry{}, EJSON) -> | |||||||
|     {struct, Fields} = EJSON, |     {struct, Fields} = EJSON, | ||||||
|  |  | ||||||
|     #ts_entry{ |     #ts_entry{ | ||||||
|         ref = {undef, undef, undef}, |         ref = {undefined, undefined, undefined}, | ||||||
|         timestamp = calendar:datetime_to_gregorian_seconds(decode_datetime( |         timestamp = calendar:datetime_to_gregorian_seconds(decode_datetime( | ||||||
|             element(2, lists:keyfind(timestamp, 1, Fields)))), |             element(2, lists:keyfind(timestamp, 1, Fields)))), | ||||||
|         mark = element(2, lists:keyfind(mark, 1, Fields)), |         mark = element(2, lists:keyfind(mark, 1, Fields)), | ||||||
|   | |||||||
| @@ -102,7 +102,16 @@ form { | |||||||
|   form div.form-submit { |   form div.form-submit { | ||||||
|     float: left; |     float: left; | ||||||
|     width: 100%; |     width: 100%; | ||||||
|     overflow: hidden; } |     overflow: hidden; | ||||||
|  |     padding: 0.5em 2em 0.5em 2em; | ||||||
|  |     position: relative; } | ||||||
|  |     form div.form-submit div { | ||||||
|  |       position: relative; | ||||||
|  |       float: right; | ||||||
|  |       left: -50%; } | ||||||
|  |       form div.form-submit div input { | ||||||
|  |         position: relative; | ||||||
|  |         left: 50%; } | ||||||
|   form div.form-submit input, form input.form-submit { |   form div.form-submit input, form input.form-submit { | ||||||
|     border: 1px solid #979681; |     border: 1px solid #979681; | ||||||
|     background: #f6f3ea; } |     background: #f6f3ea; } | ||||||
| @@ -125,16 +134,6 @@ form { | |||||||
|     color: #626150; } |     color: #626150; } | ||||||
|   #user #change-pwd { |   #user #change-pwd { | ||||||
|     display: none; } |     display: none; } | ||||||
|   #user #user-info .form-submit { |  | ||||||
|     padding: 0.5em 2em 0.5em 2em; |  | ||||||
|     position: relative; } |  | ||||||
|     #user #user-info .form-submit div { |  | ||||||
|       position: relative; |  | ||||||
|       float: right; |  | ||||||
|       left: -50%; } |  | ||||||
|       #user #user-info .form-submit div input { |  | ||||||
|         position: relative; |  | ||||||
|         left: 50%; } |  | ||||||
|  |  | ||||||
| #timeline #timeline-name, #timeline #timeline-desc { | #timeline #timeline-name, #timeline #timeline-desc { | ||||||
|   font-weight: bold; } |   font-weight: bold; } | ||||||
| @@ -142,10 +141,6 @@ form { | |||||||
|   color: #626150; } |   color: #626150; } | ||||||
| #timeline .control-links { | #timeline .control-links { | ||||||
|   padding-top: 0.2em; } |   padding-top: 0.2em; } | ||||||
| #timeline #timeline-info .form-submit { |  | ||||||
|   width: auto; |  | ||||||
|   float: right; |  | ||||||
|   overflow: inline; } |  | ||||||
|  |  | ||||||
| #user-info, #timeline-info { | #user-info, #timeline-info { | ||||||
|   display: none; |   display: none; | ||||||
| @@ -159,6 +154,7 @@ form { | |||||||
| #new-entry input { | #new-entry input { | ||||||
|   color: #626150; } |   color: #626150; } | ||||||
| #new-entry #add-notes { | #new-entry #add-notes { | ||||||
|   display: none; } |   display: none; | ||||||
|  |   padding: 0.5em 0 0.5em 2em; } | ||||||
| #new-entry #new-entry-input { | #new-entry #new-entry-input { | ||||||
|   margin-right: 1em; } |   margin-right: 1em; } | ||||||
|   | |||||||
| @@ -127,8 +127,22 @@ form { | |||||||
|         float: left; |         float: left; | ||||||
|         width: 100%; |         width: 100%; | ||||||
|         overflow: hidden; |         overflow: hidden; | ||||||
|  |         padding: 0.5em 2em 0.5em 2em; | ||||||
|  |         position: relative; | ||||||
|  |          | ||||||
|  |         div { | ||||||
|  |             position: relative; | ||||||
|  |             float: right; | ||||||
|  |             left: -50%; | ||||||
|  |  | ||||||
|  |             input { | ||||||
|  |                 position: relative; | ||||||
|  |                 left: 50%; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     div.form-submit input, input.form-submit {  |     div.form-submit input, input.form-submit {  | ||||||
|         border: 1px solid $bbor; |         border: 1px solid $bbor; | ||||||
|         background: lighten($bbg, 10%); |         background: lighten($bbg, 10%); | ||||||
| @@ -156,19 +170,6 @@ form { | |||||||
|     #change-pwd { display: none; } |     #change-pwd { display: none; } | ||||||
|  |  | ||||||
|     #user-info .form-submit { |     #user-info .form-submit { | ||||||
|         padding: 0.5em 2em 0.5em 2em; |  | ||||||
|         position: relative; |  | ||||||
|          |  | ||||||
|         div { |  | ||||||
|             position: relative; |  | ||||||
|             float: right; |  | ||||||
|             left: -50%; |  | ||||||
|  |  | ||||||
|             input { |  | ||||||
|                 position: relative; |  | ||||||
|                 left: 50%; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -180,12 +181,6 @@ form { | |||||||
|  |  | ||||||
|     .control-links { padding-top: 0.2em; } |     .control-links { padding-top: 0.2em; } | ||||||
|  |  | ||||||
|     #timeline-info .form-submit { |  | ||||||
|         width: auto; |  | ||||||
|         float: right; |  | ||||||
|         overflow: inline; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #user-info, #timeline-info { | #user-info, #timeline-info { | ||||||
| @@ -204,6 +199,10 @@ form { | |||||||
|  |  | ||||||
|     input { color: $greyTxt; } |     input { color: $greyTxt; } | ||||||
|  |  | ||||||
|     #add-notes { display: none; } |     #add-notes { | ||||||
|  |         display: none; | ||||||
|  |         padding: 0.5em 0 0.5em 2em; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #new-entry-input { margin-right: 1em; } |     #new-entry-input { margin-right: 1em; } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,9 +2,11 @@ | |||||||
| <html> | <html> | ||||||
|  |  | ||||||
|     <head> |     <head> | ||||||
|  |         <title>TimeStamper - Simple Time Tracking</title> | ||||||
|         <link rel="stylesheet" media="screen" href="../css/ts-screen.css" type="text/css"/> |         <link rel="stylesheet" media="screen" href="../css/ts-screen.css" type="text/css"/> | ||||||
|         <script type="text/javascript" src="../js/jquery-1.5.min.js"></script> |         <script type="text/javascript" src="../js/jquery-1.5.min.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" /> | ||||||
|     </head> |     </head> | ||||||
|  |  | ||||||
|     <body> |     <body> | ||||||
| @@ -21,32 +23,33 @@ | |||||||
|             <div id="user-info"> |             <div id="user-info"> | ||||||
|                 <form action="/ts/update-user.yaws" onsubmit="updateUser(event)"> |                 <form action="/ts/update-user.yaws" onsubmit="updateUser(event)"> | ||||||
|                     <div class="form-col"> |                     <div class="form-col"> | ||||||
|                         <label for="fullname"><span>name:</span> |                         <label for="fullname-input"><span>name:</span> | ||||||
|                             <input id="fullname-input" name="fullname" |                             <input id="fullname-input" name="fullname" | ||||||
|                                 class="text-input" type="text"/> |                                 class="text-input" type="text"/> | ||||||
|                         </label> |                         </label> | ||||||
|                         <label for="email"><span>email:</span> |                         <label for="email-input"><span>email:</span> | ||||||
|                             <input id="email-input" name="email" |                             <input id="email-input" name="email" | ||||||
|                                 class="text-input" type="text"/> |                                 class="text-input" type="text"/> | ||||||
|                         </label> |                         </label> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="form-col"> |                     <div class="form-col"> | ||||||
|                        <div id="change-pwd"> |                        <div id="change-pwd"> | ||||||
|                             <label for="old-pwd"><span>password:</span> |                             <label for="old-pwd-input"><span>password:</span> | ||||||
|                                 <input id="old-pwd-input" name="old-pwd" |                                 <input id="old-pwd-input" name="old-pwd" | ||||||
|                                     class="text-input" type="password"/> |                                     class="text-input" type="password"/> | ||||||
|                             </label> |                             </label> | ||||||
|                             <label for="new-pwd"><span>new pwd:</span> |                             <label for="new-pwd-input"><span>new pwd:</span> | ||||||
|                                 <input id="new-pwd-input" name="new-pwd" |                                 <input id="new-pwd-input" name="new-pwd" | ||||||
|                                     class="text-input" type="password"/> |                                     class="text-input" type="password"/> | ||||||
|                             </label> |                             </label> | ||||||
|                             <label for="new-pwd-conf"><span>confirm:</span> |                             <label for="new-pwd-conf-input"><span>confirm:</span> | ||||||
|                                 <input id="new-pwd-conf-input" name="new-pwd-conf" |                                 <input id="new-pwd-conf-input" name="new-pwd-conf" | ||||||
|                                     class="text-input" type="password"/> |                                     class="text-input" type="password"/> | ||||||
|                             </label> |                             </label> | ||||||
|                         </div> |                         </div> | ||||||
|                         <label for="enable-pwd-change"> |                         <label for="enable-pwd-change-input"> | ||||||
|                             <input name="enable-pwd-change" type="checkbox" |                             <input name="enable-pwd-change" type="checkbox" | ||||||
|  |                                 id="enable-pwd-change-input" | ||||||
|                                 onclick="showChangePwd(event)"/> |                                 onclick="showChangePwd(event)"/> | ||||||
|                                 change password |                                 change password | ||||||
|                         </label> |                         </label> | ||||||
| @@ -74,13 +77,13 @@ | |||||||
|             <div id="timeline-info"> |             <div id="timeline-info"> | ||||||
|                 <form action="/ts/update-timeline.yaws" |                 <form action="/ts/update-timeline.yaws" | ||||||
|                     onsubmit="updateTimeline(event); false"> |                     onsubmit="updateTimeline(event); false"> | ||||||
|                     <label for="timeline-desc"><span>description:</span> |                     <label for="timeline-desc-input"><span>description:</span> | ||||||
|                         <input id="timeline-desc-input" class="text-input" |                         <input id="timeline-desc-input" class="text-input" | ||||||
|                             name="timeline-desc" type="text"/> |                             name="timeline-desc" type="text"/> | ||||||
|                     </label> |                     </label> | ||||||
|                     <div class="form-submit"> |                     <div class="form-submit"> | ||||||
|                         <input name="submit-timeline" type="submit" |                         <div><input name="submit-timeline" type="submit" | ||||||
|                             value="save changes"/> |                             value="save changes"/></div> | ||||||
|                     </div> |                     </div> | ||||||
|                 </form> |                 </form> | ||||||
|             </div> |             </div> | ||||||
| @@ -88,20 +91,19 @@ | |||||||
|  |  | ||||||
|         <div id="new-entry" class="bar last-bar"> |         <div id="new-entry" class="bar last-bar"> | ||||||
|             <form action="/ts/new-entry.yaws" onsubmit="newEntry(event)"> |             <form action="/ts/new-entry.yaws" onsubmit="newEntry(event)"> | ||||||
|                 <span for="new-entry">begin a new activity: |                 begin a new activity: | ||||||
|                     <input name="new-entry" id="new-entry-input" |                 <input name="new-entry" id="new-entry-input" | ||||||
|                         class="text-input" type="text"/> |                     class="text-input" type="text"/> | ||||||
|                     <input name=submit-entry" id="submit-entry" |                 <input name="submit-entry" id="submit-entry" | ||||||
|                         class="form-submit" type="submit" value="create entry"/> |                     class="form-submit" type="submit" value="create entry"/> | ||||||
|                     <div class="control-links"> |                 <div class="control-links"> | ||||||
|                         <a id="show-notes" href="#" |                     <a id="show-notes" href="#" | ||||||
|                             onclick="showNewNotes(event)"/>add notes</a> |                         onclick="showNewNotes(event)">add notes</a> | ||||||
|                     </div> |                 </div> | ||||||
|                 </span> |                 <div id="add-notes" class="form-col"> | ||||||
|                 <div id="add-notes"> |                     <label for="new-notes-input">notes:</label> | ||||||
|                     <label for="new-notes">notes:</label> |                     <textarea name="new-notes" id="new-notes-input" | ||||||
|                     <input name="new-notes" id="new-notes-input" |                         class="text-input" rows="8" cols="40" ></textarea> | ||||||
|                         class="text-input" type="textarea"/> |  | ||||||
|                 </div> |                 </div> | ||||||
|             </form> |             </form> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user