Implemented entry exclusions in UI.
* Resolved D0020: Add exclusion filter for entries. * Refactored ``timeline`` fields of several objects in ``ts.js`` to be ``timelineModel`` to be explicit. * Added support for exclusions in ``EntryListView.renderOne`` and ``EntryListView.render``.
This commit is contained in:
parent
602bdca7e3
commit
1fff94b622
143
.ide/vim-views/ts.js.view
Normal file
143
.ide/vim-views/ts.js.view
Normal file
@ -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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
db/test/ts_ext_data.DCL
Normal file
BIN
db/test/ts_ext_data.DCL
Normal file
Binary file not shown.
Binary file not shown.
BIN
db/test/ts_user.DCL
Normal file
BIN
db/test/ts_user.DCL
Normal file
Binary file not shown.
@ -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
|
||||
========= ==========
|
22
doc/issues/desktop/0020fs5.rst
Normal file
22
doc/issues/desktop/0020fs5.rst
Normal file
@ -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
|
||||
========= ==========
|
12
doc/issues/desktop/0023bn7.rst
Normal file
12
doc/issues/desktop/0023bn7.rst
Normal file
@ -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
|
||||
========= ==========
|
@ -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),
|
||||
|
52
www/js/ts.js
52
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')});
|
||||
|
Loading…
x
Reference in New Issue
Block a user