Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
e5da3786
Commit
e5da3786
authored
Nov 12, 2014
by
Nick Stenning
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1638 from hypothesis/1615-update-timestamps
Update annotation card timestamps regulary
parents
4cd394a7
ca928da6
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
202 additions
and
88 deletions
+202
-88
annotation.coffee
h/static/scripts/directives/annotation.coffee
+67
-52
filters.coffee
h/static/scripts/filters.coffee
+0
-35
time-helpers.coffee
h/static/scripts/helpers/time-helpers.coffee
+55
-0
annotation.html
h/templates/client/annotation.html
+1
-1
time-helpers-test.coffee
tests/js/helpers/time-helpers-test.coffee
+79
-0
No files found.
h/static/scripts/directives/annotation.coffee
View file @
e5da3786
...
...
@@ -249,58 +249,73 @@ AnnotationController = [
# value is used to signal whether the annotation is being displayed inside
# an embedded widget.
###
annotation
=
[
'annotator'
,
'documentHelpers'
,
(
annotator
,
documentHelpers
)
->
linkFn
=
(
scope
,
elem
,
attrs
,
[
ctrl
,
thread
,
threadFilter
,
counter
])
->
# Helper function to remove the temporary thread created for a new reply.
prune
=
(
message
)
->
return
if
message
.
id
?
# threading plugin will take care of it
return
unless
thread
.
container
.
message
is
message
thread
.
container
.
parent
?
.
removeChild
(
thread
.
container
)
if
thread
?
annotator
.
subscribe
'annotationDeleted'
,
prune
scope
.
$on
'$destroy'
,
->
annotator
.
unsubscribe
'annotationDeleted'
,
prune
# Observe the embedded attribute
attrs
.
$observe
'annotationEmbedded'
,
(
value
)
->
ctrl
.
embedded
=
value
?
and
value
!=
'false'
# Save on Meta + Enter or Ctrl + Enter.
elem
.
on
'keydown'
,
(
event
)
->
if
event
.
keyCode
==
13
and
(
event
.
metaKey
or
event
.
ctrlKey
)
event
.
preventDefault
()
scope
.
$evalAsync
->
ctrl
.
save
()
# Keep track of edits going on in the thread.
if
counter
?
# Expand the thread if descendants are editing.
scope
.
$watch
(
->
counter
.
count
'edit'
),
(
count
)
->
if
count
and
not
ctrl
.
editing
and
thread
.
collapsed
thread
.
toggleCollapsed
()
# Propagate changes through the counters.
scope
.
$watch
(
->
ctrl
.
editing
),
(
editing
,
old
)
->
if
editing
counter
.
count
'edit'
,
1
# Disable the filter and freeze it to always match while editing.
threadFilter
?
.
freeze
()
else
if
old
counter
.
count
'edit'
,
-
1
threadFilter
?
.
freeze
(
false
)
# Clean up when the thread is destroyed
scope
.
$on
'$destroy'
,
->
if
ctrl
.
editing
then
counter
?
.
count
'edit'
,
-
1
controller
:
'AnnotationController'
controllerAs
:
'vm'
link
:
linkFn
require
:
[
'annotation'
,
'?^thread'
,
'?^threadFilter'
,
'?^deepCount'
]
scope
:
annotationGet
:
'&annotation'
templateUrl
:
'annotation.html'
annotation
=
[
'annotator'
,
'documentHelpers'
,
'render'
,
'timeHelpers'
,
'$timeout'
,
(
annotator
,
documentHelpers
,
render
,
timeHelpers
,
$timeout
)
->
linkFn
=
(
scope
,
elem
,
attrs
,
[
ctrl
,
thread
,
threadFilter
,
counter
])
->
# Helper function to remove the temporary thread created for a new reply.
prune
=
(
message
)
->
return
if
message
.
id
?
# threading plugin will take care of it
return
unless
thread
.
container
.
message
is
message
thread
.
container
.
parent
?
.
removeChild
(
thread
.
container
)
if
thread
?
annotator
.
subscribe
'annotationDeleted'
,
prune
scope
.
$on
'$destroy'
,
->
annotator
.
unsubscribe
'annotationDeleted'
,
prune
# Observe the embedded attribute
attrs
.
$observe
'annotationEmbedded'
,
(
value
)
->
ctrl
.
embedded
=
value
?
and
value
!=
'false'
# Save on Meta + Enter or Ctrl + Enter.
elem
.
on
'keydown'
,
(
event
)
->
if
event
.
keyCode
==
13
and
(
event
.
metaKey
or
event
.
ctrlKey
)
event
.
preventDefault
()
scope
.
$evalAsync
->
ctrl
.
save
()
# Keep track of edits going on in the thread.
if
counter
?
# Expand the thread if descendants are editing.
scope
.
$watch
(
->
counter
.
count
'edit'
),
(
count
)
->
if
count
and
not
ctrl
.
editing
and
thread
.
collapsed
thread
.
toggleCollapsed
()
# Propagate changes through the counters.
scope
.
$watch
(
->
ctrl
.
editing
),
(
editing
,
old
)
->
if
editing
counter
.
count
'edit'
,
1
# Disable the filter and freeze it to always match while editing.
threadFilter
?
.
freeze
()
else
if
old
counter
.
count
'edit'
,
-
1
threadFilter
?
.
freeze
(
false
)
# Clean up when the thread is destroyed
scope
.
$on
'$destroy'
,
->
if
ctrl
.
editing
then
counter
?
.
count
'edit'
,
-
1
updateTimeStamp
=
->
stamp
=
ctrl
.
annotation
.
updated
scope
.
timestamp
=
timeHelpers
.
toFuzzyString
stamp
fuzzyUpdate
=
timeHelpers
.
nextFuzzyUpdate
(
stamp
)
# Handle null value, give default 5 sec
fuzzyUpdate
?=
5
nextUpdate
=
1000
*
fuzzyUpdate
+
500
$timeout
->
render
updateTimeStamp
,
nextUpdate
,
false
render
updateTimeStamp
controller
:
'AnnotationController'
controllerAs
:
'vm'
link
:
linkFn
require
:
[
'annotation'
,
'?^thread'
,
'?^threadFilter'
,
'?^deepCount'
]
scope
:
annotationGet
:
'&annotation'
templateUrl
:
'annotation.html'
]
...
...
h/static/scripts/filters.coffee
View file @
e5da3786
...
...
@@ -7,40 +7,6 @@ class Converter extends Markdown.Converter
text
.
replace
/<a href=/g
,
"<a target=
\"
_blank
\"
href="
fuzzyTime
=
(
date
)
->
return
''
if
not
date
delta
=
Math
.
round
((
+
new
Date
-
new
Date
(
date
))
/
1000
)
minute
=
60
hour
=
minute
*
60
day
=
hour
*
24
week
=
day
*
7
month
=
day
*
30
year
=
day
*
365
if
(
delta
<
30
)
fuzzy
=
'moments ago'
else
if
(
delta
<
minute
)
fuzzy
=
delta
+
' seconds ago'
else
if
(
delta
<
2
*
minute
)
fuzzy
=
'a minute ago'
else
if
(
delta
<
hour
)
fuzzy
=
Math
.
floor
(
delta
/
minute
)
+
' minutes ago'
else
if
(
Math
.
floor
(
delta
/
hour
)
==
1
)
fuzzy
=
'1 hour ago'
else
if
(
delta
<
day
)
fuzzy
=
Math
.
floor
(
delta
/
hour
)
+
' hours ago'
else
if
(
delta
<
day
*
2
)
fuzzy
=
'yesterday'
else
if
(
delta
<
month
)
fuzzy
=
Math
.
round
(
delta
/
day
)
+
' days ago'
else
if
(
delta
<
year
)
fuzzy
=
Math
.
round
(
delta
/
month
)
+
' months ago'
else
fuzzy
=
Math
.
round
(
delta
/
year
)
+
' years ago'
fuzzy
momentFilter
=
->
(
value
,
format
)
->
# Determine the timezone name and browser language.
...
...
@@ -66,6 +32,5 @@ persona = (user, part='username') ->
angular
.
module
(
'h'
)
.
filter
(
'converter'
,
->
(
new
Converter
()).
makeHtml
)
.
filter
(
'fuzzyTime'
,
->
fuzzyTime
)
.
filter
(
'moment'
,
momentFilter
)
.
filter
(
'persona'
,
->
persona
)
h/static/scripts/helpers/time-helpers.coffee
0 → 100644
View file @
e5da3786
minute
=
60
hour
=
minute
*
60
day
=
hour
*
24
month
=
day
*
30
year
=
day
*
365
BREAKPOINTS
=
[
[
30
,
'moments ago'
,
1
]
[
minute
,
'{} seconds ago'
,
1
]
[
2
*
minute
,
'a minute ago'
,
minute
]
[
hour
,
'{} minutes ago'
,
minute
]
[
2
*
hour
,
'an hour ago'
,
hour
]
[
day
,
'{} hours ago'
,
hour
]
[
2
*
day
,
'yesterday'
,
day
]
[
month
,
'{} days ago'
,
day
]
[
year
,
'{} months ago'
,
month
]
[
Infinity
,
'{} years ago'
,
year
]
]
arrayFind
=
(
array
,
predicate
)
->
if
not
array
?
throw
new
TypeError
(
'arrayFindIndex called on null or undefined'
)
if
typeof
predicate
!=
'function'
throw
new
TypeError
(
'predicate must be a function'
)
for
value
,
i
in
array
if
predicate
(
value
,
i
,
array
)
return
value
return
null
getBreakpoint
=
(
date
)
->
delta
=
Math
.
round
((
new
Date
()
-
new
Date
(
date
))
/
1000
)
delta
:
delta
breakpoint
:
arrayFind
(
BREAKPOINTS
,
(
x
)
->
x
[
0
]
>
delta
)
createTimeHelpers
=
->
toFuzzyString
:
(
date
)
->
return
''
unless
date
{
delta
,
breakpoint
}
=
getBreakpoint
(
date
)
return
''
unless
breakpoint
template
=
breakpoint
[
1
]
resolution
=
breakpoint
[
2
]
return
template
.
replace
(
'{}'
,
String
(
Math
.
floor
(
delta
/
resolution
)))
nextFuzzyUpdate
:
(
date
)
->
return
null
if
not
date
{
_
,
breakpoint
}
=
getBreakpoint
(
date
)
return
null
unless
breakpoint
return
breakpoint
[
2
]
angular
.
module
(
'h.helpers'
)
.
factory
(
'timeHelpers'
,
createTimeHelpers
)
h/templates/client/annotation.html
View file @
e5da3786
...
...
@@ -37,7 +37,7 @@
title=
"{{vm.annotation.update | moment:'LLLL'}}"
ng-if=
"!vm.editing && vm.annotation.updated"
ng-href=
"{{baseURI}}a/{{vm.annotation.id}}"
>
{{
vm.annotation.updated | fuzzyTime | date : mediumDate
}}
</a>
>
{{
timestamp
}}
</a>
</header>
<!-- Excerpts -->
...
...
tests/js/helpers/time-helpers-test.coffee
0 → 100644
View file @
e5da3786
assert
=
chai
.
assert
minute
=
60
hour
=
minute
*
60
day
=
hour
*
24
month
=
day
*
30
year
=
day
*
365
FIXTURES_TO_FUZZY_STRING
=
[
[
10
,
'moments ago'
]
[
29
,
'moments ago'
]
[
49
,
'49 seconds ago'
]
[
minute
+
5
,
'a minute ago'
]
[
3
*
minute
+
5
,
'3 minutes ago'
]
[
4
*
hour
,
'4 hours ago'
]
[
27
*
hour
,
'yesterday'
]
[
3
*
day
+
30
*
minute
,
'3 days ago'
]
[
6
*
month
+
2
*
day
,
'6 months ago'
]
[
8
*
year
,
'8 years ago'
]
]
FIXTURES_NEXT_FUZZY_UPDATE
=
[
[
10
,
1
]
[
29
,
1
]
[
49
,
1
]
[
minute
+
5
,
minute
]
[
3
*
minute
+
5
,
minute
]
[
4
*
hour
,
hour
]
[
27
*
hour
,
day
]
[
3
*
day
+
30
*
minute
,
day
]
[
6
*
month
+
2
*
day
,
month
]
[
8
*
year
,
year
]
]
describe
'timeHelpers'
,
->
beforeEach
module
(
'h.helpers'
)
timeHelpers
=
null
sandbox
=
null
beforeEach
inject
(
_timeHelpers_
)
->
timeHelpers
=
_timeHelpers_
sandbox
=
sinon
.
sandbox
.
create
()
sandbox
.
useFakeTimers
()
afterEach
->
sandbox
.
restore
()
describe
'.toFuzzyString'
,
->
it
'Handles empty dates'
,
->
time
=
null
expect
=
''
assert
.
equal
(
timeHelpers
.
toFuzzyString
(
time
),
expect
)
testFixture
=
(
f
)
->
->
time
=
new
Date
()
expect
=
f
[
1
]
sandbox
.
clock
.
tick
(
f
[
0
]
*
1000
)
assert
.
equal
(
timeHelpers
.
toFuzzyString
(
time
),
expect
)
for
f
,
i
in
FIXTURES_TO_FUZZY_STRING
it
"creates correct fuzzy string for fixture
#{
i
}
"
,
testFixture
(
f
)
describe
'.nextFuzzyUpdate'
,
->
it
'Handles empty dates'
,
->
time
=
null
expect
=
null
assert
.
equal
(
timeHelpers
.
nextFuzzyUpdate
(
time
),
expect
)
testFixture
=
(
f
)
->
->
time
=
new
Date
()
expect
=
f
[
1
]
sandbox
.
clock
.
tick
(
f
[
0
]
*
1000
)
assert
.
equal
(
timeHelpers
.
nextFuzzyUpdate
(
time
),
expect
)
for
f
,
i
in
FIXTURES_NEXT_FUZZY_UPDATE
it
"gives correct next fuzzy update time for fixture
#{
i
}
"
,
testFixture
(
f
)
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment