Fixing problems introduced by the model change.
* Many calls to ``ts_ext_data:get_properties/1`` from ``ts_api`` were passing the record reference, not the record itself. Fixed. * Created ``ts_api:put_user/2`` which updates a ``ts_user`` record. This is needed specifically for updating the ``liat_timeline`` extended data property. * Removed unreachable code in ``ts_api:post_entry/3`` * Fixed return value of some ``ts_user`` functions to use the ``{Status, Value}`` convention. TODO: make sure all calls are using the same convention. * Fixed error message formatting in ``ts_ext_data:set_property/3``. * Added clauses to ``ts_json:ejson_to_record/2``, ``ts_json:ejson_to_record_strict/2`` and ``ts_json:construct_record/3`` to handle the ``ts_user`` record type. * Added code to ``AppView.loadInitialData`` and ``AppView.selectTimeline`` to support the ``last_timeline`` extended data property.
This commit is contained in:
parent
3999e736be
commit
cd182d54c3
@ -1,6 +1,6 @@
|
|||||||
let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0
|
let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0
|
||||||
argglobal
|
argglobal
|
||||||
edit ~/projects/jdb-labs/timestamper/web-app/www/js/ts.js
|
edit /mnt/secure/projects/jdb-labs/timestamper/web-app/www/index.yaws
|
||||||
setlocal keymap=
|
setlocal keymap=
|
||||||
setlocal noarabic
|
setlocal noarabic
|
||||||
setlocal autoindent
|
setlocal autoindent
|
||||||
@ -26,8 +26,8 @@ setlocal nodiff
|
|||||||
setlocal equalprg=
|
setlocal equalprg=
|
||||||
setlocal errorformat=
|
setlocal errorformat=
|
||||||
setlocal expandtab
|
setlocal expandtab
|
||||||
if &filetype != 'javascript'
|
if &filetype != 'erlang'
|
||||||
setlocal filetype=javascript
|
setlocal filetype=erlang
|
||||||
endif
|
endif
|
||||||
setlocal foldcolumn=0
|
setlocal foldcolumn=0
|
||||||
setlocal foldenable
|
setlocal foldenable
|
||||||
@ -83,8 +83,8 @@ setlocal statusline=
|
|||||||
setlocal suffixesadd=
|
setlocal suffixesadd=
|
||||||
setlocal swapfile
|
setlocal swapfile
|
||||||
setlocal synmaxcol=3000
|
setlocal synmaxcol=3000
|
||||||
if &syntax != 'javascript'
|
if &syntax != 'erlang'
|
||||||
setlocal syntax=javascript
|
setlocal syntax=erlang
|
||||||
endif
|
endif
|
||||||
setlocal tabstop=4
|
setlocal tabstop=4
|
||||||
setlocal tags=
|
setlocal tags=
|
||||||
@ -95,48 +95,13 @@ setlocal nowinfixwidth
|
|||||||
setlocal wrap
|
setlocal wrap
|
||||||
setlocal wrapmargin=0
|
setlocal wrapmargin=0
|
||||||
silent! normal! zE
|
silent! normal! zE
|
||||||
9,18fold
|
let s:l = 1 - ((0 * winheight(0) + 36) / 72)
|
||||||
20,28fold
|
|
||||||
30,43fold
|
|
||||||
45,61fold
|
|
||||||
63,81fold
|
|
||||||
86,288fold
|
|
||||||
290,348fold
|
|
||||||
350,418fold
|
|
||||||
420,457fold
|
|
||||||
459,557fold
|
|
||||||
559,618fold
|
|
||||||
620,656fold
|
|
||||||
9
|
|
||||||
normal zc
|
|
||||||
20
|
|
||||||
normal zc
|
|
||||||
30
|
|
||||||
normal zc
|
|
||||||
45
|
|
||||||
normal zc
|
|
||||||
63
|
|
||||||
normal zc
|
|
||||||
86
|
|
||||||
normal zc
|
|
||||||
290
|
|
||||||
normal zc
|
|
||||||
350
|
|
||||||
normal zc
|
|
||||||
420
|
|
||||||
normal zc
|
|
||||||
459
|
|
||||||
normal zc
|
|
||||||
559
|
|
||||||
normal zc
|
|
||||||
620
|
|
||||||
normal zc
|
|
||||||
let s:l = 3 - ((2 * winheight(0) + 23) / 47)
|
|
||||||
if s:l < 1 | let s:l = 1 | endif
|
if s:l < 1 | let s:l = 1 | endif
|
||||||
exe s:l
|
exe s:l
|
||||||
normal! zt
|
normal! zt
|
||||||
3
|
1
|
||||||
normal! 0
|
normal! 0
|
||||||
|
lcd /mnt/secure/projects/jdb-labs/timestamper/web-app/www
|
||||||
let &so = s:so_save | let &siso = s:siso_save
|
let &so = s:so_save | let &siso = s:siso_save
|
||||||
doautoall SessionLoadPost
|
doautoall SessionLoadPost
|
||||||
" vim: set ft=vim :
|
" vim: set ft=vim :
|
185
.ide/vim-views/ts_api.erl.view
Normal file
185
.ide/vim-views/ts_api.erl.view
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0
|
||||||
|
argglobal
|
||||||
|
edit /mnt/secure/projects/jdb-labs/timestamper/web-app/src/ts_api.erl
|
||||||
|
setlocal keymap=
|
||||||
|
setlocal noarabic
|
||||||
|
setlocal autoindent
|
||||||
|
setlocal balloonexpr=
|
||||||
|
setlocal nobinary
|
||||||
|
setlocal bufhidden=
|
||||||
|
setlocal buflisted
|
||||||
|
setlocal buftype=
|
||||||
|
setlocal nocindent
|
||||||
|
setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e
|
||||||
|
setlocal cinoptions=
|
||||||
|
setlocal cinwords=if,else,while,do,for,switch
|
||||||
|
setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-
|
||||||
|
setlocal commentstring=/*%s*/
|
||||||
|
setlocal complete=.,w,b,u,t,i
|
||||||
|
setlocal completefunc=
|
||||||
|
setlocal nocopyindent
|
||||||
|
setlocal nocursorcolumn
|
||||||
|
setlocal nocursorline
|
||||||
|
setlocal define=
|
||||||
|
setlocal dictionary=
|
||||||
|
setlocal nodiff
|
||||||
|
setlocal equalprg=
|
||||||
|
setlocal errorformat=
|
||||||
|
setlocal expandtab
|
||||||
|
if &filetype != 'erlang'
|
||||||
|
setlocal filetype=erlang
|
||||||
|
endif
|
||||||
|
setlocal foldcolumn=0
|
||||||
|
setlocal foldenable
|
||||||
|
setlocal foldexpr=0
|
||||||
|
setlocal foldignore=#
|
||||||
|
setlocal foldlevel=0
|
||||||
|
setlocal foldmarker={{{,}}}
|
||||||
|
setlocal foldmethod=manual
|
||||||
|
setlocal foldminlines=1
|
||||||
|
setlocal foldnestmax=20
|
||||||
|
setlocal foldtext=foldtext()
|
||||||
|
setlocal formatexpr=
|
||||||
|
setlocal formatoptions=tcq
|
||||||
|
setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s*
|
||||||
|
setlocal grepprg=
|
||||||
|
setlocal iminsert=2
|
||||||
|
setlocal imsearch=2
|
||||||
|
setlocal include=
|
||||||
|
setlocal includeexpr=
|
||||||
|
setlocal indentexpr=
|
||||||
|
setlocal indentkeys=0{,0},:,0#,!^F,o,O,e
|
||||||
|
setlocal noinfercase
|
||||||
|
setlocal iskeyword=@,48-57,_,192-255
|
||||||
|
setlocal keywordprg=
|
||||||
|
setlocal nolinebreak
|
||||||
|
setlocal nolisp
|
||||||
|
setlocal nolist
|
||||||
|
setlocal makeprg=
|
||||||
|
setlocal matchpairs=(:),{:},[:]
|
||||||
|
setlocal nomodeline
|
||||||
|
setlocal modifiable
|
||||||
|
setlocal nrformats=octal,hex
|
||||||
|
setlocal number
|
||||||
|
setlocal numberwidth=4
|
||||||
|
setlocal omnifunc=
|
||||||
|
setlocal path=
|
||||||
|
setlocal nopreserveindent
|
||||||
|
setlocal nopreviewwindow
|
||||||
|
setlocal quoteescape=\\
|
||||||
|
setlocal noreadonly
|
||||||
|
setlocal norightleft
|
||||||
|
setlocal rightleftcmd=search
|
||||||
|
setlocal noscrollbind
|
||||||
|
setlocal shiftwidth=4
|
||||||
|
setlocal noshortname
|
||||||
|
setlocal nosmartindent
|
||||||
|
setlocal softtabstop=0
|
||||||
|
setlocal nospell
|
||||||
|
setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+
|
||||||
|
setlocal spellfile=
|
||||||
|
setlocal spelllang=en
|
||||||
|
setlocal statusline=
|
||||||
|
setlocal suffixesadd=
|
||||||
|
setlocal swapfile
|
||||||
|
setlocal synmaxcol=3000
|
||||||
|
if &syntax != 'erlang'
|
||||||
|
setlocal syntax=erlang
|
||||||
|
endif
|
||||||
|
setlocal tabstop=4
|
||||||
|
setlocal tags=
|
||||||
|
setlocal textwidth=80
|
||||||
|
setlocal thesaurus=
|
||||||
|
setlocal nowinfixheight
|
||||||
|
setlocal nowinfixwidth
|
||||||
|
setlocal wrap
|
||||||
|
setlocal wrapmargin=0
|
||||||
|
silent! normal! zE
|
||||||
|
7,28fold
|
||||||
|
35,51fold
|
||||||
|
55,73fold
|
||||||
|
77,92fold
|
||||||
|
96,126fold
|
||||||
|
130,161fold
|
||||||
|
167,196fold
|
||||||
|
198,202fold
|
||||||
|
204,239fold
|
||||||
|
241,248fold
|
||||||
|
250,267fold
|
||||||
|
269,301fold
|
||||||
|
303,310fold
|
||||||
|
312,331fold
|
||||||
|
335,421fold
|
||||||
|
423,429fold
|
||||||
|
431,453fold
|
||||||
|
455,469fold
|
||||||
|
471,486fold
|
||||||
|
492,499fold
|
||||||
|
502,506fold
|
||||||
|
508,515fold
|
||||||
|
517,525fold
|
||||||
|
528,539fold
|
||||||
|
541,552fold
|
||||||
|
554,563fold
|
||||||
|
7
|
||||||
|
normal zc
|
||||||
|
35
|
||||||
|
normal zc
|
||||||
|
55
|
||||||
|
normal zc
|
||||||
|
77
|
||||||
|
normal zc
|
||||||
|
96
|
||||||
|
normal zc
|
||||||
|
130
|
||||||
|
normal zc
|
||||||
|
167
|
||||||
|
normal zc
|
||||||
|
198
|
||||||
|
normal zc
|
||||||
|
204
|
||||||
|
normal zo
|
||||||
|
241
|
||||||
|
normal zc
|
||||||
|
250
|
||||||
|
normal zc
|
||||||
|
269
|
||||||
|
normal zc
|
||||||
|
303
|
||||||
|
normal zc
|
||||||
|
312
|
||||||
|
normal zo
|
||||||
|
335
|
||||||
|
normal zc
|
||||||
|
423
|
||||||
|
normal zc
|
||||||
|
431
|
||||||
|
normal zc
|
||||||
|
455
|
||||||
|
normal zc
|
||||||
|
471
|
||||||
|
normal zc
|
||||||
|
492
|
||||||
|
normal zc
|
||||||
|
502
|
||||||
|
normal zc
|
||||||
|
508
|
||||||
|
normal zc
|
||||||
|
517
|
||||||
|
normal zc
|
||||||
|
528
|
||||||
|
normal zc
|
||||||
|
541
|
||||||
|
normal zc
|
||||||
|
554
|
||||||
|
normal zc
|
||||||
|
let s:l = 250 - ((25 * winheight(0) + 35) / 71)
|
||||||
|
if s:l < 1 | let s:l = 1 | endif
|
||||||
|
exe s:l
|
||||||
|
normal! zt
|
||||||
|
250
|
||||||
|
normal! 0
|
||||||
|
let &so = s:so_save | let &siso = s:siso_save
|
||||||
|
doautoall SessionLoadPost
|
||||||
|
" vim: set ft=vim :
|
||||||
|
syntax on
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -22,6 +22,7 @@ out(YArg) ->
|
|||||||
{'EXIT', Err} ->
|
{'EXIT', Err} ->
|
||||||
% TODO: log error internally
|
% TODO: log error internally
|
||||||
error_logger:error_report("TimeStamper: ~p", [Err]),
|
error_logger:error_report("TimeStamper: ~p", [Err]),
|
||||||
|
io:format("Error: ~n~p", [Err]),
|
||||||
make_json_500(YArg, Err);
|
make_json_500(YArg, Err);
|
||||||
Other -> Other
|
Other -> Other
|
||||||
end.
|
end.
|
||||||
@ -211,7 +212,7 @@ get_user_summary(YArg, Username) ->
|
|||||||
User ->
|
User ->
|
||||||
|
|
||||||
% get user extended data properties
|
% get user extended data properties
|
||||||
UserExtData = ts_ext_data:get_properties(Username),
|
UserExtData = ts_ext_data:get_properties(User),
|
||||||
% convert to intermediate JSON form
|
% convert to intermediate JSON form
|
||||||
EJSONUser = ts_json:record_to_ejson(User, UserExtData),
|
EJSONUser = ts_json:record_to_ejson(User, UserExtData),
|
||||||
|
|
||||||
@ -223,7 +224,7 @@ get_user_summary(YArg, Username) ->
|
|||||||
lists:map(
|
lists:map(
|
||||||
fun(Timeline) ->
|
fun(Timeline) ->
|
||||||
ts_json:record_to_ejson(Timeline,
|
ts_json:record_to_ejson(Timeline,
|
||||||
ts_ext_data:get_properties(Timeline#ts_timeline.ref))
|
ts_ext_data:get_properties(Timeline))
|
||||||
end,
|
end,
|
||||||
Timelines)},
|
Timelines)},
|
||||||
|
|
||||||
@ -246,6 +247,25 @@ get_user(YArg, Username) ->
|
|||||||
User -> make_json_200(YArg, User)
|
User -> make_json_200(YArg, User)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
put_user(YArg, Username) ->
|
||||||
|
|
||||||
|
% parse the POST data
|
||||||
|
EJSON = parse_json_body(YArg),
|
||||||
|
|
||||||
|
{UR, ExtData} =
|
||||||
|
try ts_user:ejson_to_record_strict(#ts_user{username=Username}, EJSON)
|
||||||
|
catch throw:{InputError, StackTrace} ->
|
||||||
|
error_logger:error_report("Bad input in put_user/2: ~p",
|
||||||
|
[InputError]),
|
||||||
|
throw(make_json_400(YArg, [{request_error, InputError}]))
|
||||||
|
end,
|
||||||
|
|
||||||
|
% update the record (we do not support creating users via the API right now
|
||||||
|
{ok, UpdatedRec} = ts_user:update(UR, ExtData),
|
||||||
|
|
||||||
|
% return a 200
|
||||||
|
make_json_200(YArg, UpdatedRec).
|
||||||
|
|
||||||
list_timelines(YArg, Username) ->
|
list_timelines(YArg, Username) ->
|
||||||
% pull out the POST data
|
% pull out the POST data
|
||||||
QueryData = yaws_api:parse_query(YArg),
|
QueryData = yaws_api:parse_query(YArg),
|
||||||
@ -270,7 +290,7 @@ list_timelines(YArg, Username) ->
|
|||||||
EJSONTimelines = {array, lists:map(
|
EJSONTimelines = {array, lists:map(
|
||||||
fun (Timeline) ->
|
fun (Timeline) ->
|
||||||
ts_json:record_to_ejson(Timeline,
|
ts_json:record_to_ejson(Timeline,
|
||||||
ts_ext_data:get_properties(Timeline#ts_timeline.ref))
|
ts_ext_data:get_properties(Timeline))
|
||||||
end,
|
end,
|
||||||
Timelines)},
|
Timelines)},
|
||||||
|
|
||||||
@ -301,7 +321,7 @@ put_timeline(YArg, Username, TimelineId) ->
|
|||||||
% we can not parse it, tell the user
|
% we can not parse it, tell the user
|
||||||
catch throw:{InputError, _StackTrace} ->
|
catch throw:{InputError, _StackTrace} ->
|
||||||
error_logger:error_report("Bad input: ~p", [InputError]),
|
error_logger:error_report("Bad input: ~p", [InputError]),
|
||||||
throw(make_json_400(YArg, {request_error, InputError}))
|
throw(make_json_400(YArg, [{request_error, InputError}]))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
% write the changes.
|
% write the changes.
|
||||||
@ -355,7 +375,7 @@ list_entries(YArg, Username, TimelineId) ->
|
|||||||
EJSONEntries = {array, lists:map(
|
EJSONEntries = {array, lists:map(
|
||||||
fun (Entry) ->
|
fun (Entry) ->
|
||||||
ts_json:record_to_ejson(Entry,
|
ts_json:record_to_ejson(Entry,
|
||||||
ts_ext_data:get_properties(Entry#ts_entry.ref))
|
ts_ext_data:get_properties(Entry))
|
||||||
end,
|
end,
|
||||||
Entries)},
|
Entries)},
|
||||||
|
|
||||||
@ -391,7 +411,7 @@ list_entries(YArg, Username, TimelineId) ->
|
|||||||
EJSONEntries = {array, lists:map(
|
EJSONEntries = {array, lists:map(
|
||||||
fun (Entry) ->
|
fun (Entry) ->
|
||||||
ts_json:record_to_ejson(Entry,
|
ts_json:record_to_ejson(Entry,
|
||||||
ts_ext_data:get_properties(Entry#ts_entry.ref))
|
ts_ext_data:get_properties(Entry))
|
||||||
end,
|
end,
|
||||||
Entries)},
|
Entries)},
|
||||||
|
|
||||||
@ -418,7 +438,7 @@ post_entry(YArg, Username, TimelineId) ->
|
|||||||
#ts_entry{ref = {Username, TimelineId, undefined}}, EJSON)
|
#ts_entry{ref = {Username, TimelineId, undefined}}, EJSON)
|
||||||
catch _:InputError ->
|
catch _:InputError ->
|
||||||
error_logger:error_report("Bad input: ~p", [InputError]),
|
error_logger:error_report("Bad input: ~p", [InputError]),
|
||||||
throw(make_json_400(YArg, {request_error, InputError}))
|
throw(make_json_400(YArg, [{request_error, InputError}]))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
case ts_entry:new(ER, ExtData) of
|
case ts_entry:new(ER, ExtData) of
|
||||||
@ -427,14 +447,8 @@ post_entry(YArg, Username, TimelineId) ->
|
|||||||
|
|
||||||
[{status, 201}, make_json_200(YArg, CreatedRecord)];
|
[{status, 201}, make_json_200(YArg, CreatedRecord)];
|
||||||
|
|
||||||
% will not create, record exists
|
|
||||||
{error, {record_exists, ExistingRecord}} ->
|
|
||||||
JSONResponse = json:encode(ts_json:record_to_ejson(ExistingRecord)),
|
|
||||||
|
|
||||||
{content, "application/json", JSONResponse};
|
|
||||||
|
|
||||||
OtherError ->
|
OtherError ->
|
||||||
error_logger:error_report("TimeStamper: Could not create entry: ~p", [OtherError]),
|
error_logger:error_report("Could not create entry: ~p", [OtherError]),
|
||||||
make_json_500(YArg, OtherError)
|
make_json_500(YArg, OtherError)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -486,8 +500,9 @@ parse_json_body(YArg) ->
|
|||||||
|
|
||||||
%% Create a JSON 200 response.
|
%% Create a JSON 200 response.
|
||||||
make_json_200(_YArg, Record) ->
|
make_json_200(_YArg, Record) ->
|
||||||
RecordExtData = ts_ext_data:get_properties(element(2, Record)),
|
RecordExtData = ts_ext_data:get_properties(Record),
|
||||||
JSONResponse = json:encode(ts_json:record_to_ejson(Record, RecordExtData)),
|
EJSON = ts_json:record_to_ejson(Record, RecordExtData),
|
||||||
|
JSONResponse = json:encode(EJSON),
|
||||||
{content, "application/json", JSONResponse}.
|
{content, "application/json", JSONResponse}.
|
||||||
|
|
||||||
make_json_400(YArg) -> make_json_400(YArg, []).
|
make_json_400(YArg) -> make_json_400(YArg, []).
|
||||||
@ -532,14 +547,14 @@ make_json_405(_YArg, Fields) ->
|
|||||||
end,
|
end,
|
||||||
|
|
||||||
% add the path they requested
|
% add the path they requested
|
||||||
% F2 = F1 ++ [{path, io_lib:format("~s", [(YArg#arg.req)#http_request.path])}],
|
% F2 = F1 ++ [{path, io_lib:format("~p", [(YArg#arg.req)#http_request.path])}],
|
||||||
|
|
||||||
[{status, 405}, {content, "application/json", json:encode({struct, F1})}].
|
[{status, 405}, {content, "application/json", json:encode({struct, F1})}].
|
||||||
|
|
||||||
make_json_500(_YArg, Error) ->
|
make_json_500(_YArg, Error) ->
|
||||||
EJSON = {struct, [
|
EJSON = {struct, [
|
||||||
{status, "internal server error"},
|
{status, "internal server error"},
|
||||||
{error, io_lib:format("~s", [Error])}]},
|
{error, lists:flatten(io_lib:format("~p", [Error]))}]},
|
||||||
[{status, 500}, {content, "application/json", json:encode(EJSON)}].
|
[{status, 500}, {content, "application/json", json:encode(EJSON)}].
|
||||||
|
|
||||||
make_json_500(_YArg) ->
|
make_json_500(_YArg) ->
|
||||||
|
@ -100,10 +100,9 @@ list(Query, Start, Length) ->
|
|||||||
|
|
||||||
% should be wrapped in a transaction
|
% should be wrapped in a transaction
|
||||||
do_set_ext_data(Record, ExtData) when is_list(ExtData) ->
|
do_set_ext_data(Record, ExtData) when is_list(ExtData) ->
|
||||||
Ref = element(2, Record),
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Key, Val}) ->
|
fun({Key, Val}) ->
|
||||||
{atomic, ok} = ts_ext_data:set_property(Ref, Key, Val)
|
{atomic, ok} = ts_ext_data:set_property(Record, Key, Val)
|
||||||
end,
|
end,
|
||||||
ExtData),
|
ExtData),
|
||||||
ok.
|
ok.
|
||||||
|
@ -19,7 +19,7 @@ new(ER = #ts_entry{}, ExtData) when is_list(ExtData) ->
|
|||||||
NewRow = do_new(ER),
|
NewRow = do_new(ER),
|
||||||
ts_common:do_set_ext_data(ER, ExtData),
|
ts_common:do_set_ext_data(ER, ExtData),
|
||||||
NewRow end),
|
NewRow end),
|
||||||
NewRow.
|
{ok, NewRow}.
|
||||||
|
|
||||||
do_new(ER = #ts_entry{}) ->
|
do_new(ER = #ts_entry{}) ->
|
||||||
{Username, TimelineId, _} = ER#ts_entry.ref,
|
{Username, TimelineId, _} = ER#ts_entry.ref,
|
||||||
|
@ -21,8 +21,8 @@ set_property(Rec=#ts_timeline{}, entry_exclusions, ExclusionList) ->
|
|||||||
do_set_property(Rec#ts_timeline.ref, entry_exclusions, ExclusionList);
|
do_set_property(Rec#ts_timeline.ref, entry_exclusions, ExclusionList);
|
||||||
|
|
||||||
set_property(Rec, Key, _Value) ->
|
set_property(Rec, Key, _Value) ->
|
||||||
throw(io_lib:format("Property '~s' not available for a ~s record.",
|
throw(lists:flatten(io_lib:format("Property '~s' not available for a ~s record.",
|
||||||
[Key, element(1, Rec)])).
|
[Key, element(1, Rec)]))).
|
||||||
|
|
||||||
get_property(Ref, PropKey) ->
|
get_property(Ref, PropKey) ->
|
||||||
{atomic, Result} = mnesia:transaction(fun() ->
|
{atomic, Result} = mnesia:transaction(fun() ->
|
||||||
|
@ -81,6 +81,16 @@ ejson_to_record(Empty, Ref, EJSON) ->
|
|||||||
Constructed = ejson_to_record(Empty, EJSON),
|
Constructed = ejson_to_record(Empty, EJSON),
|
||||||
setelement(2, Constructed, Ref).
|
setelement(2, Constructed, Ref).
|
||||||
|
|
||||||
|
ejson_to_record_strict(Empty=#ts_user{}, EJSON) ->
|
||||||
|
Constructed = ejson_to_record(Empty, EJSON),
|
||||||
|
case Constructed of
|
||||||
|
#ts_user{name = undefined} -> throw("Missing user 'name' field.");
|
||||||
|
#ts_user{email = undefined} -> throw("Missing user 'email' field.");
|
||||||
|
#ts_user{join_date = undefined} ->
|
||||||
|
throw("Missing user 'join_date' field.");
|
||||||
|
_Other -> Constructed
|
||||||
|
end;
|
||||||
|
|
||||||
ejson_to_record_strict(Empty=#ts_timeline{}, EJSON) ->
|
ejson_to_record_strict(Empty=#ts_timeline{}, EJSON) ->
|
||||||
Constructed = ejson_to_record(Empty, EJSON),
|
Constructed = ejson_to_record(Empty, EJSON),
|
||||||
case Constructed of
|
case Constructed of
|
||||||
@ -107,22 +117,55 @@ ejson_to_record_strict(Empty, Ref, EJSON) ->
|
|||||||
Constructed = ejson_to_record_strict(Empty, EJSON),
|
Constructed = ejson_to_record_strict(Empty, EJSON),
|
||||||
setelement(2, Constructed, Ref).
|
setelement(2, Constructed, Ref).
|
||||||
|
|
||||||
construct_record(Timeline=#ts_timeline{}, [{Key, Val}|Fields], ExtData) ->
|
construct_record(User=#ts_user{}, [{Key, Value}|Fields], ExtData) ->
|
||||||
case Key of
|
case Key of
|
||||||
created -> construct_record(
|
id -> construct_record(User#ts_user{username = Value},
|
||||||
Timeline#ts_timeline{created = decode_datetime(Val)},
|
|
||||||
Fields, ExtData);
|
Fields, ExtData);
|
||||||
description -> construct_record(Timeline#ts_timeline{desc = Val},
|
name -> construct_record(User#ts_user{name = Value}, Fields, ExtData);
|
||||||
|
join_date -> construct_record(
|
||||||
|
User#ts_user{join_date = decode_datetime(Value)},
|
||||||
Fields, ExtData);
|
Fields, ExtData);
|
||||||
_Other ->
|
_Other ->
|
||||||
ExtDataProp = ejson_to_ext_data({Key, Val}),
|
ExtDataProp = ejson_to_ext_data({Key, Value}),
|
||||||
|
construct_record(User, Fields, [ExtDataProp|ExtData])
|
||||||
|
end;
|
||||||
|
|
||||||
|
construct_record(Timeline=#ts_timeline{}, [{Key, Value}|Fields], ExtData) ->
|
||||||
|
case Key of
|
||||||
|
user_id ->
|
||||||
|
{_, TimelineId} = Timeline#ts_timeline.ref,
|
||||||
|
construct_record(Timeline#ts_timeline{ref = {Value, TimelineId}},
|
||||||
|
Fields, ExtData);
|
||||||
|
id ->
|
||||||
|
{Username, _} = Timeline#ts_timeline.ref,
|
||||||
|
construct_record(Timeline#ts_timeline{ref = {Username, Value}},
|
||||||
|
Fields, ExtData);
|
||||||
|
created -> construct_record(
|
||||||
|
Timeline#ts_timeline{created = decode_datetime(Value)},
|
||||||
|
Fields, ExtData);
|
||||||
|
description -> construct_record(Timeline#ts_timeline{desc = Value},
|
||||||
|
Fields, ExtData);
|
||||||
|
_Other ->
|
||||||
|
ExtDataProp = ejson_to_ext_data({Key, Value}),
|
||||||
construct_record(Timeline, Fields, [ExtDataProp|ExtData])
|
construct_record(Timeline, Fields, [ExtDataProp|ExtData])
|
||||||
end;
|
end;
|
||||||
|
|
||||||
construct_record(Entry=#ts_entry{}, [{Key, Value}|Fields], ExtData) ->
|
construct_record(Entry=#ts_entry{}, [{Key, Value}|Fields], ExtData) ->
|
||||||
case Key of
|
case Key of
|
||||||
|
user_id ->
|
||||||
|
{_, TimelineId, EntryId} = Entry#ts_entry.ref,
|
||||||
|
construct_record(Entry#ts_entry{ref = {Value, TimelineId, EntryId}},
|
||||||
|
Fields, ExtData);
|
||||||
|
timeline_id ->
|
||||||
|
{Username, _, EntryId} = Entry#ts_entry.ref,
|
||||||
|
construct_record(Entry#ts_entry{ref = {Username, Value, EntryId}},
|
||||||
|
Fields, ExtData);
|
||||||
|
id ->
|
||||||
|
{Username, TimelineId, _} = Entry#ts_entry.ref,
|
||||||
|
construct_record(Entry#ts_entry{ref = {Username, TimelineId, Value}},
|
||||||
|
Fields, ExtData);
|
||||||
timestamp -> construct_record(
|
timestamp -> construct_record(
|
||||||
Entry#ts_entry{timestamp = calendar:datetime_to_gregoraian_seconds(
|
Entry#ts_entry{timestamp = calendar:datetime_to_gregorian_seconds(
|
||||||
decode_datetime(Value))},
|
decode_datetime(Value))},
|
||||||
Fields, ExtData);
|
Fields, ExtData);
|
||||||
mark -> construct_record(Entry#ts_entry{mark=Value}, Fields, ExtData);
|
mark -> construct_record(Entry#ts_entry{mark=Value}, Fields, ExtData);
|
||||||
|
@ -13,31 +13,34 @@ create_table(TableOpts) ->
|
|||||||
% expects the password in clear
|
% expects the password in clear
|
||||||
new(UR = #ts_user{}) ->
|
new(UR = #ts_user{}) ->
|
||||||
{atomic, Result} = mnesia:transaction(fun() -> do_new(UR) end),
|
{atomic, Result} = mnesia:transaction(fun() -> do_new(UR) end),
|
||||||
Result.
|
{ok, Result}.
|
||||||
|
|
||||||
new(UR = #ts_user{}, ExtData) ->
|
new(UR = #ts_user{}, ExtData) ->
|
||||||
{atomic, Result} = mnesia:transaction(fun() ->
|
{atomic, Result} = mnesia:transaction(fun() ->
|
||||||
NewUser = do_new(UR),
|
NewUser = do_new(UR),
|
||||||
ts_common:do_set_ext_data(UR, ExtData),
|
ts_common:do_set_ext_data(UR, ExtData),
|
||||||
NewUser end),
|
NewUser end),
|
||||||
Result.
|
{ok, Result}.
|
||||||
|
|
||||||
do_new(UR = #ts_user{}) ->
|
do_new(UR = #ts_user{}) ->
|
||||||
case mnesia:read(ts_user, UR#ts_user.username) of
|
case mnesia:read(ts_user, UR#ts_user.username) of
|
||||||
[ExistingRecord] -> {error, {record_exists, ExistingRecord}};
|
[ExistingRecord] -> {error, {record_exists, ExistingRecord}};
|
||||||
[] -> mnesia:write(hash_input_record(UR))
|
[] ->
|
||||||
|
NewRec = hash_input_record(UR),
|
||||||
|
mnesia:write(NewRec),
|
||||||
|
NewRec
|
||||||
end.
|
end.
|
||||||
|
|
||||||
update(UR = #ts_user{}) ->
|
update(UR = #ts_user{}) ->
|
||||||
{atomic, Result} = mnesia:transaction(fun() -> do_update(UR) end),
|
{atomic, Result} = mnesia:transaction(fun() -> do_update(UR) end),
|
||||||
Result.
|
{ok, Result}.
|
||||||
|
|
||||||
update(UR = #ts_user{}, ExtData) ->
|
update(UR = #ts_user{}, ExtData) ->
|
||||||
{atomic, Result} = mnesia:transaction(fun() ->
|
{atomic, Result} = mnesia:transaction(fun() ->
|
||||||
UpdatedUser = do_update(UR),
|
UpdatedUser = do_update(UR),
|
||||||
ts_common:do_set_ext_data(UR, ExtData),
|
ts_common:do_set_ext_data(UR, ExtData),
|
||||||
UpdatedUser end),
|
UpdatedUser end),
|
||||||
Result.
|
{ok, Result}.
|
||||||
|
|
||||||
do_update(UR = #ts_user{}) ->
|
do_update(UR = #ts_user{}) ->
|
||||||
case mnesia:read(ts_user, UR#ts_user.username) of
|
case mnesia:read(ts_user, UR#ts_user.username) of
|
||||||
@ -48,7 +51,8 @@ do_update(UR = #ts_user{}) ->
|
|||||||
undefined -> UpdatedRecord;
|
undefined -> UpdatedRecord;
|
||||||
_Password -> hash_input_record(UpdatedRecord)
|
_Password -> hash_input_record(UpdatedRecord)
|
||||||
end,
|
end,
|
||||||
mnesia:write(HashedRecord)
|
mnesia:write(HashedRecord),
|
||||||
|
HashedRecord
|
||||||
end.
|
end.
|
||||||
|
|
||||||
lookup(Username) ->
|
lookup(Username) ->
|
||||||
|
@ -535,7 +535,10 @@ $(document).ready(function(){
|
|||||||
url: '/ts_api/app/user_summary/' + username,
|
url: '/ts_api/app/user_summary/' + username,
|
||||||
async: false}).responseText);
|
async: false}).responseText);
|
||||||
|
|
||||||
data.initialTimelineId = data.timelines[0].id;
|
// look for the last used timeline, default to first timeline
|
||||||
|
data.initialTimelineId =
|
||||||
|
data.user.last_timeline || data.timelines[0].id
|
||||||
|
|
||||||
data.entries = jQuery.parseJSON($.ajax({
|
data.entries = jQuery.parseJSON($.ajax({
|
||||||
url: '/ts_api/entries/' + username + '/' +
|
url: '/ts_api/entries/' + username + '/' +
|
||||||
data.initialTimelineId,
|
data.initialTimelineId,
|
||||||
@ -555,6 +558,10 @@ $(document).ready(function(){
|
|||||||
// set the timeline on the EntryList
|
// set the timeline on the EntryList
|
||||||
this.entries.collection.timeline = tl;
|
this.entries.collection.timeline = tl;
|
||||||
|
|
||||||
|
// update the last_timeline field of the user model
|
||||||
|
this.user.model.set('last_timeline', tl.get('id');
|
||||||
|
this.user.model.save();
|
||||||
|
|
||||||
// refresh TimelineListView
|
// refresh TimelineListView
|
||||||
this.timelines.view.render();
|
this.timelines.view.render();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user