diff --git a/.ide/vim-views/ts.js.view b/.ide/vim-views/ts.js.view new file mode 100644 index 0000000..54dd060 --- /dev/null +++ b/.ide/vim-views/ts.js.view @@ -0,0 +1,143 @@ +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/www/js/ts.js +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 != 'javascript' +setlocal filetype=javascript +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 != 'javascript' +setlocal syntax=javascript +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=80 +setlocal thesaurus= +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +9,18fold +20,28fold +30,43fold +45,62fold +64,82fold +87,289fold +291,378fold +380,448fold +450,487fold +489,603fold +605,664fold +666,702fold +9 +normal zc +20 +normal zc +30 +normal zc +45 +normal zo +64 +normal zc +87 +normal zc +291 +normal zo +380 +normal zc +450 +normal zc +489 +normal zo +605 +normal zc +666 +normal zc +let s:l = 334 - ((273 * winheight(0) + 35) / 71) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +334 +normal! 042l +let &so = s:so_save | let &siso = s:siso_save +doautoall SessionLoadPost +" vim: set ft=vim : +syntax on diff --git a/db/test/DECISION_TAB.LOG b/db/test/DECISION_TAB.LOG index 7c8ee32..ad60397 100644 Binary files a/db/test/DECISION_TAB.LOG and b/db/test/DECISION_TAB.LOG differ diff --git a/db/test/LATEST.LOG b/db/test/LATEST.LOG index f3762f1..6625cd8 100644 Binary files a/db/test/LATEST.LOG and b/db/test/LATEST.LOG differ diff --git a/db/test/id_counter.DCD b/db/test/id_counter.DCD index 8715eeb..b009917 100644 Binary files a/db/test/id_counter.DCD and b/db/test/id_counter.DCD differ diff --git a/db/test/ts_entry.DCD b/db/test/ts_entry.DCD index ebd97c1..1141c0b 100644 Binary files a/db/test/ts_entry.DCD and b/db/test/ts_entry.DCD differ diff --git a/db/test/ts_ext_data.DCD b/db/test/ts_ext_data.DCD index 4d049a2..836eebb 100644 Binary files a/db/test/ts_ext_data.DCD and b/db/test/ts_ext_data.DCD differ diff --git a/db/test/ts_ext_data.DCL b/db/test/ts_ext_data.DCL new file mode 100644 index 0000000..2a0dcfa Binary files /dev/null and b/db/test/ts_ext_data.DCL differ diff --git a/db/test/ts_user.DCD b/db/test/ts_user.DCD index 72c0ed1..ae33bb4 100644 Binary files a/db/test/ts_user.DCD and b/db/test/ts_user.DCD differ diff --git a/db/test/ts_user.DCL b/db/test/ts_user.DCL new file mode 100644 index 0000000..b061d25 Binary files /dev/null and b/db/test/ts_user.DCL differ diff --git a/doc/issues/desktop/0020fn5.rst b/doc/issues/desktop/0020fn5.rst deleted file mode 100644 index 336b231..0000000 --- a/doc/issues/desktop/0020fn5.rst +++ /dev/null @@ -1,10 +0,0 @@ -Add exclusion filter for entries. -================================= - -Add a way for users to add regexes for entries to be ignored in the -display. Exclusions may be per-timeline or per-user. - -========= ========== -Created: 2011-06-10 -Resolved: YYYY-MM-DD -========= ========== \ No newline at end of file diff --git a/doc/issues/desktop/0020fs5.rst b/doc/issues/desktop/0020fs5.rst new file mode 100644 index 0000000..6f951c1 --- /dev/null +++ b/doc/issues/desktop/0020fs5.rst @@ -0,0 +1,22 @@ +Add exclusion filter for entries. +================================= + +Add a way for users to add regexes for entries to be ignored in the +display. Exclusions may be per-timeline or per-user. + +Resolution +---------- + +``ts_user`` and ``ts_timeline`` both support an exnteded data property called +``entry_exclusions`` which accepts a list of regular expression strings. Any entries +whose marks match any of the regular expressions should be excluded from view. + +EntryListView.render filters out any matching entries from its display. It still +takes them into account when calculating the duration of other entries. + +---- + +========= ========== +Created: 2011-06-10 +Resolved: 2011-06-15 +========= ========== \ No newline at end of file diff --git a/doc/issues/desktop/0023bn7.rst b/doc/issues/desktop/0023bn7.rst new file mode 100644 index 0000000..bd41dc3 --- /dev/null +++ b/doc/issues/desktop/0023bn7.rst @@ -0,0 +1,12 @@ +Check for exclusion after mark update. +====================================== + +If a user rewrites the mark of an entry, we should check to see if it now +matches one of the defined entry exclusions. + +---- + +========= ========== +Created: YYYY-MM-DD +Resolved: YYYY-MM-DD +========= ========== \ No newline at end of file diff --git a/src/ts_entry.erl b/src/ts_entry.erl index 22dc088..c3d4d3a 100644 --- a/src/ts_entry.erl +++ b/src/ts_entry.erl @@ -36,7 +36,7 @@ update(ER = #ts_entry{}, ExtData) when is_list(ExtData) -> write(ER = #ts_entry{}) -> mnesia:dirty_write(ER). write(ER = #ts_entry{}, ExtData) -> - {atomic, Result} = mnesia:transcation(fun() -> + {atomic, Result} = mnesia:transaction(fun() -> ok = mnesia:write(ER), ok = ts_common:do_set_ext_data(ER, ExtData) end), diff --git a/www/js/ts.js b/www/js/ts.js index b2a16c8..7923023 100644 --- a/www/js/ts.js +++ b/www/js/ts.js @@ -48,15 +48,16 @@ $(document).ready(function(){ comparator: function(entry) { return entry.get('timestamp'); }, initialize: function(model, options) { - if (options.timeline == undefined) { + if (options.timelineModel == undefined) { throw "Cannot create an EntryList without a TimelineModel reference." - } else { this.timeline = options.timeline; } + } else { this.timelineModel = options.timelineModel; } _.bindAll(this, "url"); }, url: function() { - return "/ts_api/entries/" + this.timeline.get('user_id') + "/" + this.timeline.get('id'); + return "/ts_api/entries/" + this.timelineModel.get('user_id') + "/" + + this.timelineModel.get('id'); } }); @@ -312,10 +313,26 @@ $(document).ready(function(){ }, renderOne: function(entry, nextEntry) { + // exclude if any exclusion RegExps match + var excluded = _.any(this.entryExclusions, + function(exclusion) { return exclusion.test(entry.get("mark"))}); + + // create the view if it does not exist if (!entry.view) { new TS.EntryView( {model: entry, markdownConverter: this.markdownConverter}); } entry.view.nextModel = nextEntry - this.entryContainer.prepend(entry.view.render().el); + + // render the element + var el = entry.view.render().el; + + // add it to the container + this.entryContainer.prepend(el); + + // hide it if excluded + if (excluded) { + $(el).fadeOut('slow'); + $(el).addClass('excluded'); + } }, createNewEntryOnEnter: function(e) { @@ -337,6 +354,19 @@ $(document).ready(function(){ }, render: function() { + + // get our user exclusions + var userExclusions = TS.app.user.model.get("entry_exclusions") || []; + + // get the current timeline exclusions + var timelineExclusions = + this.collection.timelineModel.get("entry_exclusions") || []; + + // turn them into RegExps and store them + this.entryExclusions = _.map( + userExclusions.concat(timelineExclusions), + function(exclusion) { return new RegExp(exclusion)} ); + this.entryContainer.empty(); for (var i = 0, len = this.collection.length; i < len; i++) { var entry = this.collection.at(i); @@ -367,7 +397,7 @@ $(document).ready(function(){ if (options.initialTimelineId == undefined) { throw "Can not create a TimelineListView without an initial timeline." } else { - this.selected = this.collection.get(options.initialTimelineId); + this.selectedModel = this.collection.get(options.initialTimelineId); } this.collection.bind('add', this.renderOne); @@ -381,10 +411,10 @@ $(document).ready(function(){ render: function() { // render the basic template - $(this.el).html(ich.timelineTemplate(this.selected.toJSON())); + $(this.el).html(ich.timelineTemplate(this.selectedModel.toJSON())); // render the selection list - _.each(this.collection.without([this.selected]), this.renderOne); + _.each(this.collection.without([this.selectedModel]), this.renderOne); }, editId: function() { @@ -400,7 +430,7 @@ $(document).ready(function(){ }, close: function() { - this.selected.save({ + this.selectedModel.save({ id: this.$('.timeline-id-input').val(), description: this.$('.timeline-desc-input').val()}); $(this.el).removeClass('edit-id edit-desc'); @@ -515,7 +545,7 @@ $(document).ready(function(){ // create the entry collection this.entries = {}; this.entries.collection = new TS.EntryList(entryModels, - {timeline: this.timelines.view.selected}); + {timelineModel: this.timelines.view.selectedModel}); this.entries.view = new TS.EntryListView( {collection: this.entries.collection}); @@ -553,10 +583,10 @@ $(document).ready(function(){ var tl = this.timelines.collection.get(e.srcElement.text); // set the on the timeline view - this.timelines.view.selected = tl; + this.timelines.view.selectedModel = tl; // set the timeline on the EntryList - this.entries.collection.timeline = tl; + this.entries.collection.timelineModel = tl; // update the last_timeline field of the user model this.user.model.set({last_timeline: tl.get('id')});