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
9051fefd
Commit
9051fefd
authored
Jun 14, 2017
by
Sean Hammond
Committed by
GitHub
Jun 14, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #431 from hypothesis/tags-decaf
Convert tags service to JS
parents
93632029
515a59e1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
185 additions
and
152 deletions
+185
-152
tags.coffee
src/sidebar/tags.coffee
+0
-51
tags.js
src/sidebar/tags.js
+75
-0
tags-test.coffee
src/sidebar/test/tags-test.coffee
+0
-101
tags-test.js
src/sidebar/test/tags-test.js
+110
-0
No files found.
src/sidebar/tags.coffee
deleted
100644 → 0
View file @
93632029
module
.
exports
=
[
'localStorage'
,
(
localStorage
)
->
TAGS_LIST_KEY
=
'hypothesis.user.tags.list'
TAGS_MAP_KEY
=
'hypothesis.user.tags.map'
filter
:
(
query
)
->
savedTags
=
localStorage
.
getObject
TAGS_LIST_KEY
savedTags
?=
[]
# Only show tags having query as a substring
filterFn
=
(
e
)
->
e
.
toLowerCase
().
indexOf
(
query
.
toLowerCase
())
>
-
1
savedTags
.
filter
(
filterFn
)
# Add newly added tags from an annotation to the stored ones and refresh
# timestamp for every tags used.
store
:
(
tags
)
->
savedTags
=
localStorage
.
getObject
TAGS_MAP_KEY
savedTags
?=
{}
for
tag
in
tags
if
savedTags
[
tag
.
text
]
?
# Update counter and timestamp
savedTags
[
tag
.
text
].
count
+=
1
savedTags
[
tag
.
text
].
updated
=
Date
.
now
()
else
# Brand new tag, create an entry for it
savedTags
[
tag
.
text
]
=
{
text
:
tag
.
text
count
:
1
updated
:
Date
.
now
()
}
localStorage
.
setObject
TAGS_MAP_KEY
,
savedTags
tagsList
=
[]
for
tag
of
savedTags
tagsList
[
tagsList
.
length
]
=
tag
# Now produce TAGS_LIST, ordered by (count desc, lexical asc)
compareFn
=
(
t1
,
t2
)
->
if
savedTags
[
t1
].
count
!=
savedTags
[
t2
].
count
return
savedTags
[
t2
].
count
-
savedTags
[
t1
].
count
else
return
-
1
if
t1
<
t2
return
1
if
t1
>
t2
return
0
tagsList
=
tagsList
.
sort
(
compareFn
)
localStorage
.
setObject
TAGS_LIST_KEY
,
tagsList
]
src/sidebar/tags.js
0 → 100644
View file @
9051fefd
'use strict'
;
/**
* @typedef Tag
* @property {string} text - The label of the tag
* @property {number} count - The number of times this tag has been used.
* @property {number} updated - The timestamp when this tag was last used.
*/
/**
* Service for fetching tag suggestions and storing data to generate them.
*
* The `tags` service stores metadata about recently used tags to local storage
* and provides a `filter` method to fetch tags matching a query, ranked based
* on frequency of usage.
*/
// @ngInject
function
tags
(
localStorage
)
{
var
TAGS_LIST_KEY
=
'hypothesis.user.tags.list'
;
var
TAGS_MAP_KEY
=
'hypothesis.user.tags.map'
;
/**
* Return a list of tag suggestions matching `query`.
*
* @param {string} query
* @return {Tag[]} List of matching tags
*/
function
filter
(
query
)
{
var
savedTags
=
localStorage
.
getObject
(
TAGS_LIST_KEY
)
||
[];
return
savedTags
.
filter
((
e
)
=>
{
return
e
.
toLowerCase
().
indexOf
(
query
.
toLowerCase
())
!==
-
1
;
});
}
/**
* Update the list of stored tag suggestions based on the tags that a user has
* entered for a given annotation.
*
* @param {Tag} tags - List of tags.
*/
function
store
(
tags
)
{
// Update the stored (tag, frequency) map.
var
savedTags
=
localStorage
.
getObject
(
TAGS_MAP_KEY
)
||
{};
tags
.
forEach
((
tag
)
=>
{
if
(
savedTags
[
tag
.
text
])
{
savedTags
[
tag
.
text
].
count
+=
1
;
savedTags
[
tag
.
text
].
updated
=
Date
.
now
();
}
else
{
savedTags
[
tag
.
text
]
=
{
text
:
tag
.
text
,
count
:
1
,
updated
:
Date
.
now
(),
};
}
});
localStorage
.
setObject
(
TAGS_MAP_KEY
,
savedTags
);
// Sort tag suggestions by frequency.
var
tagsList
=
Object
.
keys
(
savedTags
).
sort
((
t1
,
t2
)
=>
{
if
(
savedTags
[
t1
].
count
!==
savedTags
[
t2
].
count
)
{
return
savedTags
[
t2
].
count
-
savedTags
[
t1
].
count
;
}
return
t1
.
localeCompare
(
t2
);
});
localStorage
.
setObject
(
TAGS_LIST_KEY
,
tagsList
);
}
return
{
filter
,
store
,
};
}
module
.
exports
=
tags
;
src/sidebar/test/tags-test.coffee
deleted
100644 → 0
View file @
93632029
{
module
,
inject
}
=
angular
.
mock
describe
'tags'
,
->
TAGS_LIST_KEY
=
'hypothesis.user.tags.list'
TAGS_MAP_KEY
=
'hypothesis.user.tags.map'
fakeLocalStorage
=
null
sandbox
=
null
savedTagsMap
=
null
savedTagsList
=
null
tags
=
null
before
->
angular
.
module
(
'h'
,
[]).
service
(
'tags'
,
require
(
'../tags'
))
beforeEach
module
(
'h'
)
beforeEach
module
(
$provide
)
->
sandbox
=
sinon
.
sandbox
.
create
()
fakeStorage
=
{}
fakeLocalStorage
=
{
getObject
:
sandbox
.
spy
(
key
)
->
fakeStorage
[
key
]
setObject
:
sandbox
.
spy
(
key
,
value
)
->
fakeStorage
[
key
]
=
value
wipe
:
->
fakeStorage
=
{}
}
$provide
.
value
'localStorage'
,
fakeLocalStorage
return
beforeEach
inject
(
_tags_
)
->
tags
=
_tags_
afterEach
->
sandbox
.
restore
()
beforeEach
->
fakeLocalStorage
.
wipe
()
stamp
=
Date
.
now
()
savedTagsMap
=
foo
:
text
:
'foo'
count
:
1
updated
:
stamp
bar
:
text
:
'bar'
count
:
5
updated
:
stamp
future
:
text
:
'future'
count
:
2
updated
:
stamp
argon
:
text
:
'argon'
count
:
1
updated
:
stamp
savedTagsList
=
[
'bar'
,
'future'
,
'argon'
,
'foo'
]
fakeLocalStorage
.
setObject
TAGS_MAP_KEY
,
savedTagsMap
fakeLocalStorage
.
setObject
TAGS_LIST_KEY
,
savedTagsList
describe
'filter()'
,
->
it
'returns tags having the query as a substring'
,
->
assert
.
deepEqual
(
tags
.
filter
(
'a'
),
[
'bar'
,
'argon'
])
it
'is case insensitive'
,
->
assert
.
deepEqual
(
tags
.
filter
(
'Ar'
),
[
'bar'
,
'argon'
])
describe
'store()'
,
->
it
'saves new tags to storage'
,
->
tags
.
store
([{
text
:
'new'
}])
storedTagsList
=
fakeLocalStorage
.
getObject
TAGS_LIST_KEY
assert
.
deepEqual
(
storedTagsList
,
[
'bar'
,
'future'
,
'argon'
,
'foo'
,
'new'
])
storedTagsMap
=
fakeLocalStorage
.
getObject
TAGS_MAP_KEY
assert
.
isTrue
(
storedTagsMap
.
new
?
)
assert
.
equal
(
storedTagsMap
.
new
.
count
,
1
)
assert
.
equal
(
storedTagsMap
.
new
.
text
,
'new'
)
it
'increases the count for a tag already stored'
,
->
tags
.
store
([{
text
:
'bar'
}])
storedTagsMap
=
fakeLocalStorage
.
getObject
TAGS_MAP_KEY
assert
.
equal
(
storedTagsMap
.
bar
.
count
,
6
)
it
'list is ordered by count desc, lexical asc'
,
->
# Will increase from 1 to 6 (as future)
tags
.
store
([{
text
:
'foo'
}])
tags
.
store
([{
text
:
'foo'
}])
tags
.
store
([{
text
:
'foo'
}])
tags
.
store
([{
text
:
'foo'
}])
tags
.
store
([{
text
:
'foo'
}])
storedTagsList
=
fakeLocalStorage
.
getObject
TAGS_LIST_KEY
assert
.
deepEqual
(
storedTagsList
,
[
'foo'
,
'bar'
,
'future'
,
'argon'
])
it
'gets/sets its objects from the localstore'
,
->
tags
.
store
([{
text
:
'foo'
}])
assert
.
called
(
fakeLocalStorage
.
getObject
)
assert
.
called
(
fakeLocalStorage
.
setObject
)
src/sidebar/test/tags-test.js
0 → 100644
View file @
9051fefd
'use strict'
;
var
angular
=
require
(
'angular'
);
var
TAGS_LIST_KEY
=
'hypothesis.user.tags.list'
;
var
TAGS_MAP_KEY
=
'hypothesis.user.tags.map'
;
class
FakeStorage
{
constructor
()
{
this
.
_storage
=
{};
}
getObject
(
key
)
{
return
this
.
_storage
[
key
];
}
setObject
(
key
,
value
)
{
this
.
_storage
[
key
]
=
value
;
}
}
describe
(
'sidebar.tags'
,
()
=>
{
var
fakeLocalStorage
;
var
tags
;
before
(()
=>
{
angular
.
module
(
'h'
,
[])
.
service
(
'tags'
,
require
(
'../tags'
));
});
beforeEach
(()
=>
{
fakeLocalStorage
=
new
FakeStorage
();
var
stamp
=
Date
.
now
();
var
savedTagsMap
=
{
foo
:
{
text
:
'foo'
,
count
:
1
,
updated
:
stamp
,
},
bar
:
{
text
:
'bar'
,
count
:
5
,
updated
:
stamp
,
},
future
:
{
text
:
'future'
,
count
:
2
,
updated
:
stamp
,
},
argon
:
{
text
:
'argon'
,
count
:
1
,
updated
:
stamp
,
},
};
var
savedTagsList
=
Object
.
keys
(
savedTagsMap
);
fakeLocalStorage
.
setObject
(
TAGS_MAP_KEY
,
savedTagsMap
);
fakeLocalStorage
.
setObject
(
TAGS_LIST_KEY
,
savedTagsList
);
angular
.
mock
.
module
(
'h'
,
{
localStorage
:
fakeLocalStorage
,
});
angular
.
mock
.
inject
((
_tags_
)
=>
{
tags
=
_tags_
;
});
});
describe
(
'#filter'
,
()
=>
{
it
(
'returns tags having the query as a substring'
,
()
=>
{
assert
.
deepEqual
(
tags
.
filter
(
'a'
),
[
'bar'
,
'argon'
]);
});
it
(
'is case insensitive'
,
()
=>
{
assert
.
deepEqual
(
tags
.
filter
(
'Ar'
),
[
'bar'
,
'argon'
]);
});
});
describe
(
'#store'
,
()
=>
{
it
(
'saves new tags to storage'
,
()
=>
{
tags
.
store
([{
text
:
'new'
}]);
var
storedTagsList
=
fakeLocalStorage
.
getObject
(
TAGS_LIST_KEY
);
assert
.
include
(
storedTagsList
,
'new'
);
var
storedTagsMap
=
fakeLocalStorage
.
getObject
(
TAGS_MAP_KEY
);
assert
.
match
(
storedTagsMap
.
new
,
sinon
.
match
({
count
:
1
,
text
:
'new'
,
updated
:
sinon
.
match
.
number
,
}));
});
it
(
'increases the count for a tag already stored'
,
()
=>
{
tags
.
store
([{
text
:
'bar'
}]);
var
storedTagsMap
=
fakeLocalStorage
.
getObject
(
TAGS_MAP_KEY
);
assert
.
equal
(
storedTagsMap
.
bar
.
count
,
6
);
});
it
(
'orders list by count descending, lexical ascending'
,
()
=>
{
for
(
var
i
=
0
;
i
<
6
;
i
++
)
{
tags
.
store
([{
text
:
'foo'
}]);
}
var
storedTagsList
=
fakeLocalStorage
.
getObject
(
TAGS_LIST_KEY
);
assert
.
deepEqual
(
storedTagsList
,
[
'foo'
,
'bar'
,
'future'
,
'argon'
]);
});
});
});
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