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:
@@ -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.
Binary file not shown.
Binary file not shown.
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
|
|
||||||
========= ==========
|
|
||||||
@@ -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
|
||||||
|
========= ==========
|
||||||
@@ -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
|
||||||
|
========= ==========
|
||||||
+1
-1
@@ -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{}) -> mnesia:dirty_write(ER).
|
||||||
|
|
||||||
write(ER = #ts_entry{}, ExtData) ->
|
write(ER = #ts_entry{}, ExtData) ->
|
||||||
{atomic, Result} = mnesia:transcation(fun() ->
|
{atomic, Result} = mnesia:transaction(fun() ->
|
||||||
ok = mnesia:write(ER),
|
ok = mnesia:write(ER),
|
||||||
ok = ts_common:do_set_ext_data(ER, ExtData)
|
ok = ts_common:do_set_ext_data(ER, ExtData)
|
||||||
end),
|
end),
|
||||||
|
|||||||
+41
-11
@@ -48,15 +48,16 @@ $(document).ready(function(){
|
|||||||
comparator: function(entry) { return entry.get('timestamp'); },
|
comparator: function(entry) { return entry.get('timestamp'); },
|
||||||
|
|
||||||
initialize: function(model, options) {
|
initialize: function(model, options) {
|
||||||
if (options.timeline == undefined) {
|
if (options.timelineModel == undefined) {
|
||||||
throw "Cannot create an EntryList without a TimelineModel reference."
|
throw "Cannot create an EntryList without a TimelineModel reference."
|
||||||
} else { this.timeline = options.timeline; }
|
} else { this.timelineModel = options.timelineModel; }
|
||||||
|
|
||||||
_.bindAll(this, "url");
|
_.bindAll(this, "url");
|
||||||
},
|
},
|
||||||
|
|
||||||
url: function() {
|
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) {
|
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(
|
if (!entry.view) { new TS.EntryView(
|
||||||
{model: entry, markdownConverter: this.markdownConverter}); }
|
{model: entry, markdownConverter: this.markdownConverter}); }
|
||||||
entry.view.nextModel = nextEntry
|
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) {
|
createNewEntryOnEnter: function(e) {
|
||||||
@@ -337,6 +354,19 @@ $(document).ready(function(){
|
|||||||
},
|
},
|
||||||
|
|
||||||
render: 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();
|
this.entryContainer.empty();
|
||||||
for (var i = 0, len = this.collection.length; i < len; i++) {
|
for (var i = 0, len = this.collection.length; i < len; i++) {
|
||||||
var entry = this.collection.at(i);
|
var entry = this.collection.at(i);
|
||||||
@@ -367,7 +397,7 @@ $(document).ready(function(){
|
|||||||
if (options.initialTimelineId == undefined) {
|
if (options.initialTimelineId == undefined) {
|
||||||
throw "Can not create a TimelineListView without an initial timeline."
|
throw "Can not create a TimelineListView without an initial timeline."
|
||||||
} else {
|
} else {
|
||||||
this.selected = this.collection.get(options.initialTimelineId);
|
this.selectedModel = this.collection.get(options.initialTimelineId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.collection.bind('add', this.renderOne);
|
this.collection.bind('add', this.renderOne);
|
||||||
@@ -381,10 +411,10 @@ $(document).ready(function(){
|
|||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
// render the basic template
|
// render the basic template
|
||||||
$(this.el).html(ich.timelineTemplate(this.selected.toJSON()));
|
$(this.el).html(ich.timelineTemplate(this.selectedModel.toJSON()));
|
||||||
|
|
||||||
// render the selection list
|
// render the selection list
|
||||||
_.each(this.collection.without([this.selected]), this.renderOne);
|
_.each(this.collection.without([this.selectedModel]), this.renderOne);
|
||||||
},
|
},
|
||||||
|
|
||||||
editId: function() {
|
editId: function() {
|
||||||
@@ -400,7 +430,7 @@ $(document).ready(function(){
|
|||||||
},
|
},
|
||||||
|
|
||||||
close: function() {
|
close: function() {
|
||||||
this.selected.save({
|
this.selectedModel.save({
|
||||||
id: this.$('.timeline-id-input').val(),
|
id: this.$('.timeline-id-input').val(),
|
||||||
description: this.$('.timeline-desc-input').val()});
|
description: this.$('.timeline-desc-input').val()});
|
||||||
$(this.el).removeClass('edit-id edit-desc');
|
$(this.el).removeClass('edit-id edit-desc');
|
||||||
@@ -515,7 +545,7 @@ $(document).ready(function(){
|
|||||||
// create the entry collection
|
// create the entry collection
|
||||||
this.entries = {};
|
this.entries = {};
|
||||||
this.entries.collection = new TS.EntryList(entryModels,
|
this.entries.collection = new TS.EntryList(entryModels,
|
||||||
{timeline: this.timelines.view.selected});
|
{timelineModel: this.timelines.view.selectedModel});
|
||||||
this.entries.view = new TS.EntryListView(
|
this.entries.view = new TS.EntryListView(
|
||||||
{collection: this.entries.collection});
|
{collection: this.entries.collection});
|
||||||
|
|
||||||
@@ -553,10 +583,10 @@ $(document).ready(function(){
|
|||||||
var tl = this.timelines.collection.get(e.srcElement.text);
|
var tl = this.timelines.collection.get(e.srcElement.text);
|
||||||
|
|
||||||
// set the on the timeline view
|
// set the on the timeline view
|
||||||
this.timelines.view.selected = tl;
|
this.timelines.view.selectedModel = tl;
|
||||||
|
|
||||||
// set the timeline on the EntryList
|
// 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
|
// update the last_timeline field of the user model
|
||||||
this.user.model.set({last_timeline: tl.get('id')});
|
this.user.model.set({last_timeline: tl.get('id')});
|
||||||
|
|||||||
Reference in New Issue
Block a user