Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Markus Opolka
vue-cdbp
Commits
1afeeeea
Commit
1afeeeea
authored
Jan 18, 2018
by
Markus Opolka
Browse files
Refactor search in back and frontend
parent
46865ec0
Changes
8
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
1afeeeea
...
...
@@ -6,6 +6,7 @@ yarn-debug.log*
yarn-error.log*
yarn.lock
package-lock.json
*.tar
# Windows Start scripts
*.bat
...
...
app.js
View file @
1afeeeea
...
...
@@ -143,9 +143,7 @@ app.get('/api/search', function (req, res) {
let
query
=
{
element
:
req
.
query
.
element
,
content
:
req
.
query
.
content
,
attribute
:
req
.
query
.
attribute
,
value
:
req
.
query
.
value
content
:
req
.
query
.
content
}
let
data
=
[]
...
...
lib.js
View file @
1afeeeea
const
flat
=
require
(
'
flat
'
)
// Arrays
const
flatten
=
require
(
'
flatten
'
)
// Objects
const
flatten
=
require
(
'
flatten
'
)
// Flatten Objects
function
has
(
object
,
key
)
{
/*
* Check if object has a key
*/
return
object
?
hasOwnProperty
.
call
(
object
,
key
)
:
false
}
function
findKeyRecursive
(
object
,
keytofind
,
ret
=
[])
{
/*
...
...
@@ -41,51 +47,51 @@ function countReferences (features) {
return
count
}
function
searchIn
Object
(
obj
,
query
)
{
function
searchIn
Elements
(
elements
,
query
)
{
/*
* Search for query in a
fiven flatobject
* Search
es
for
a
query in a
n array of elemts
*/
let
results
=
[]
Object
.
keys
(
obj
).
forEach
(
function
(
key
)
{
// Attributes
if
(
typeof
query
.
attribute
!==
'
undefined
'
)
{
const
reAttr
=
new
RegExp
(
'
_attributes.
'
+
query
.
attribute
)
if
(
!
reAttr
.
test
(
key
))
{
return
}
}
// Values
if
(
typeof
query
.
value
!==
'
undefined
'
)
{
const
reVal
=
new
RegExp
(
query
.
value
)
if
(
!
reVal
.
test
(
obj
[
key
]))
{
return
}
}
// Elements
if
(
typeof
query
.
element
!==
'
undefined
'
)
{
const
reElem
=
new
RegExp
(
'
[^_]
'
+
query
.
element
,
'
g
'
)
if
(
!
reElem
.
test
(
key
))
{
return
}
}
// Content
if
(
typeof
query
.
content
!==
'
undefined
'
)
{
const
reCont
=
new
RegExp
(
query
.
content
)
if
(
!
reCont
.
test
(
obj
[
key
]))
{
return
}
}
try
{
var
reContent
=
new
RegExp
(
query
.
content
)
}
catch
(
err
)
{
console
.
log
(
arguments
.
callee
)
// eslint-disable-line no-caller
console
.
log
(
'
>> Error while searching elements
'
)
return
results
}
// Add hit to results as object
let
res
=
{}
res
[
key
]
=
obj
[
key
]
results
.
push
(
res
)
})
for
(
let
idx
=
0
;
idx
<
elements
.
length
;
idx
++
)
{
var
matchContent
=
reContent
.
test
(
elements
[
idx
].
_text
)
if
(
matchContent
)
{
results
.
push
(
elements
[
idx
])
}
}
return
results
}
function
searchInDocument
(
document
,
query
)
{
/*
* Search for text in (js) document elements
*/
let
elems
=
findKeyRecursive
(
document
,
query
.
element
)
let
results
=
searchInElements
(
elems
,
query
)
if
(
results
.
length
>
0
)
{
document
[
'
results
'
]
=
results
document
[
'
hits
'
]
=
undefined
}
else
{
return
null
}
return
document
}
function
searchInFeatures
(
features
,
query
)
{
/*
* Searches for a query in an array of features
...
...
@@ -129,30 +135,7 @@ function searchFeaturesInDocument (document, query) {
let
results
=
searchInFeatures
(
features
,
query
)
if
(
results
.
length
>
0
)
{
document
[
'
count
'
]
=
countReferences
(
results
)
document
[
'
results
'
]
=
results
}
else
{
return
null
}
return
document
}
function
searchInDocument
(
document
,
query
)
{
/*
* Search for query in (js) document
*/
let
faltobject
=
{}
try
{
flatobject
=
flat
(
document
.
object
.
TEI
)
}
catch
(
err
)
{
console
.
log
(
arguments
.
callee
)
// eslint-disable-line no-caller
console
.
log
(
'
>> Error while searching
'
)
}
let
results
=
searchInObject
(
flatobject
,
query
)
if
(
results
.
length
>
0
)
{
document
[
'
hits
'
]
=
countReferences
(
results
)
document
[
'
results
'
]
=
results
}
else
{
return
null
...
...
package.json
View file @
1afeeeea
...
...
@@ -13,7 +13,6 @@
},
"dependencies"
:
{
"
express
"
:
"
^4.16.2
"
,
"
flat
"
:
"
^4.0.0
"
,
"
flatten
"
:
"
^1.0.2
"
,
"
memory-cache
"
:
"
^0.2.0
"
,
"
vue
"
:
"
^2.5.2
"
,
...
...
src/components/Features.vue
View file @
1afeeeea
...
...
@@ -71,32 +71,7 @@
<!-- Search Results -->
<v-flex
xs12
v-if=
"results"
>
<v-card
v-for=
"letter in results"
v-bind:key=
"letter.url"
>
<v-card-title
primary-title
>
{{
letter
.
name
}}
<v-chip
label
color=
"lime accent-4"
>
{{
letter
.
collection
}}
</v-chip>
<v-chip
color=
"indigo"
text-color=
"white"
>
<v-avatar
class=
"indigo darken-4"
>
{{
letter
.
count
}}
</v-avatar>
Hits
</v-chip>
</v-card-title>
<v-card-text>
<ul
style=
"list-style-type:none;"
>
<li
v-for=
"hit in letter.results"
>
<v-chip
outline
small
color=
"secondary"
>
{{
hit
.
_text
}}
</v-chip>
<v-chip
label
small
>
<span
v-if=
"hit._attributes.category"
>
Category:
{{
(
hit
.
_attributes
.
category
)
}}
</span>
<span
v-if=
"hit._attributes.type"
>
, Type:
{{
(
hit
.
_attributes
.
type
)
}}
</span>
<span
v-if=
"hit._attributes.subtype"
>
, Subtype:
{{
(
hit
.
_attributes
.
subtype
)
}}
</span>
</v-chip>
<v-chip
label
small
text-color=
"white"
color=
"deep-orange darken-4"
v-if=
"hit._attributes.ref"
>
Line:
{{
(
hit
.
_attributes
.
ref
)
}}
</v-chip>
</li>
</ul>
</v-card-text>
<v-card-actions>
<v-btn
:to=
"letter.link"
flat
>
View
</v-btn>
</v-card-actions>
</v-card>
<result
:letter=
"letter"
v-for=
"letter in results"
v-bind:key=
"letter.url"
/>
</v-flex>
</v-layout>
...
...
src/components/Result.vue
0 → 100644
View file @
1afeeeea
<
template
>
<v-card>
<v-card-title
primary-title
>
<span
class=
"title"
>
{{
letter
.
name
}}
</span><v-chip
label
color=
"lime accent-4"
>
{{
letter
.
collection
}}
</v-chip>
<v-chip
color=
"indigo"
text-color=
"white"
v-if=
"letter.hits"
>
<v-avatar
class=
"indigo darken-4"
>
{{
letter
.
hits
}}
</v-avatar>
Hits
</v-chip>
</v-card-title>
<v-card-text>
<ul
style=
"list-style-type:none;"
>
<li
v-for=
"hit in letter.results"
>
<v-chip
outline
small
color=
"secondary"
>
{{
hit
.
_text
}}
</v-chip>
<v-chip
label
small
v-if=
"has(hit, '_attributes')"
>
<span
v-if=
"has(hit._attributes, 'no')"
>
Line:
{{
(
hit
.
_attributes
.
no
)
}}
</span>
<span
v-if=
"has(hit._attributes, 'category')"
>
Category:
{{
(
hit
.
_attributes
.
category
)
}}
</span>
<span
v-if=
"has(hit._attributes, 'type')"
>
, Type:
{{
(
hit
.
_attributes
.
type
)
}}
</span>
<span
v-if=
"has(hit._attributes, 'subtype')"
>
, Subtype:
{{
(
hit
.
_attributes
.
subtype
)
}}
</span>
</v-chip>
<v-chip
label
small
text-color=
"white"
color=
"deep-orange darken-4"
v-if=
"has(hit._attributes, 'ref')"
>
Line:
{{
(
hit
.
_attributes
.
ref
)
}}
</v-chip>
</li>
</ul>
</v-card-text>
<v-card-actions>
<v-btn
:to=
"letter.link"
flat
>
View
</v-btn>
</v-card-actions>
</v-card>
</
template
>
<
script
>
export
default
{
// Component for Results in Search
data
()
{
return
{
data
:
null
}
},
methods
:
{
has
(
object
,
key
)
{
return
object
?
hasOwnProperty
.
call
(
object
,
key
)
:
false
}
},
props
:
{
letter
:
null
}
}
</
script
>
src/components/Search.vue
View file @
1afeeeea
...
...
@@ -13,8 +13,9 @@
<v-card>
<v-card-text
class=
"grey lighten-3"
>
<p>
Content in an element:
<strong>
element:content
</strong>
(Regular Expressions are supported)
</p>
<p>
Attribute of an element:
<strong>
element@attribute=value
</strong></p>
<p>
Attribute and content:
<strong>
element@attribute=value:content
</strong></p>
<p>
If no element is provided, the text will be searched.
</p>
<!--
<p>
Attribute of an element:
<strong>
element@attribute=value
</strong></p>
-->
<!--
<p>
Attribute and content:
<strong>
element@attribute=value:content
</strong></p>
-->
</v-card-text>
</v-card>
</v-expansion-panel-content>
...
...
@@ -59,30 +60,13 @@
<v-card
color=
"blue-grey lighten-1"
class=
"white--text"
>
<v-card-text>
Results:
{{
results
.
length
}}
letter(s)
<v-slider
v-model=
"cutoff"
min=
"20"
max=
"255"
thumb-label
dark
></v-slider>
<v-checkbox
label=
"Show Labels"
v-model=
"showlabels"
dark
></v-checkbox>
</v-card-text>
</v-card>
</v-flex>
<!-- Search Results -->
<v-flex
xs12
v-if=
"results"
>
<v-card
v-for=
"letter in results"
v-bind:key=
"letter.url"
>
<v-card-title
primary-title
>
{{
letter
.
name
}}
<v-chip
label
color=
"lime accent-4"
>
{{
letter
.
collection
}}
</v-chip>
</v-card-title>
<v-card-text>
<ul
style=
"list-style-type:none;"
>
<li
v-for=
"hit in letter.results"
>
<v-chip
outline
small
color=
"secondary"
>
{{
getValue
(
hit
)
}}
</v-chip>
<v-chip
label
small
v-if=
"showlabels"
>
{{
getKey
(
hit
)
}}
</v-chip>
</li>
</ul>
</v-card-text>
<v-card-actions>
<v-btn
:to=
"letter.link"
flat
>
View
</v-btn>
</v-card-actions>
</v-card>
<result
:letter=
"letter"
v-for=
"letter in results"
v-bind:key=
"letter.url"
/>
</v-flex>
</v-layout>
...
...
@@ -98,10 +82,7 @@ export default {
header
:
'
Search
'
,
invalid
:
false
,
search
:
''
,
pattern
:
[
'
([a-z]+)@([a-z]+=[a-z0-9]+)(:.+)?
'
,
'
^([a-z]+):(.+)
'
],
pattern
:
'
^([a-z]+):(.+)
'
,
results
:
null
,
searching
:
false
,
cutoff
:
100
,
...
...
@@ -109,36 +90,8 @@ export default {
}
},
methods
:
{
parse
()
{
let
match
=
''
let
regex
=
''
let
params
=
{
element
:
undefined
,
content
:
undefined
,
attribute
:
undefined
,
value
:
undefined
}
// Parse the input
if
(
this
.
search
.
indexOf
(
'
@
'
)
>
0
)
{
regex
=
new
RegExp
(
this
.
pattern
[
0
])
match
=
regex
.
exec
(
this
.
search
)
params
.
element
=
match
[
1
]
params
.
attribute
=
match
[
2
].
split
(
'
=
'
)[
0
]
params
.
value
=
match
[
2
].
split
(
'
=
'
)[
1
]
if
(
match
[
3
])
params
.
content
=
match
[
3
].
replace
(
'
:
'
,
''
)
}
else
{
regex
=
new
RegExp
(
this
.
pattern
[
1
])
match
=
regex
.
exec
(
this
.
search
)
params
.
element
=
match
[
1
]
params
.
content
=
match
[
2
]
}
return
params
},
find
()
{
// Parse input field and call search API
let
params
=
this
.
parse
()
find
(
params
)
{
// Call search API
// Remove undefined values
Object
.
keys
(
params
).
forEach
((
key
)
=>
(
params
[
key
]
==
null
)
&&
delete
params
[
key
])
this
.
searching
=
true
...
...
@@ -149,32 +102,29 @@ export default {
},
validate
()
{
// Validate input field
this
.
search
.
toLowerCase
(
)
let
search
=
this
.
search
.
split
(
'
:
'
)
const
validator
=
new
RegExp
(
this
.
pattern
.
join
(
'
|
'
))
if
(
validator
.
test
(
this
.
search
))
{
this
.
invalid
=
false
this
.
find
()
}
else
{
// If no element is entered we search the text
<
l
>
if
(
typeof
search
[
1
]
===
'
undefined
'
)
{
search
.
unshift
(
'
l
'
)
}
let
params
=
{
element
:
search
[
0
],
content
:
search
[
1
]
}
if
(
!
params
.
content
)
{
this
.
invalid
=
true
}
else
{
this
.
invalid
=
false
this
.
find
(
params
)
}
},
clear
()
{
// Clear input field
this
.
invalid
=
false
this
.
search
=
''
},
getValue
(
obj
)
{
// Get value of unknown key in object
let
key
=
Object
.
keys
(
obj
)[
0
]
return
obj
[
key
].
substr
(
0
,
this
.
cutoff
)
},
getKey
(
obj
)
{
// Get unknown first key from object
let
key
=
Object
.
keys
(
obj
)[
0
]
key
=
key
.
replace
(
'
teiHeader.xenoData.
'
,
''
)
key
=
key
.
replace
(
/.
[
0-9
]
._text/
,
''
)
return
key
}
}
}
...
...
src/main.js
View file @
1afeeeea
...
...
@@ -6,12 +6,14 @@ import VueResource from 'vue-resource'
import
App
from
'
./App
'
import
router
from
'
./router
'
import
Feature
from
'
./components/Feature
'
import
Result
from
'
./components/Result
'
import
'
../node_modules/vuetify/dist/vuetify.min.css
'
Vue
.
config
.
productionTip
=
false
Vue
.
use
(
Vuetify
)
Vue
.
use
(
VueResource
)
Vue
.
component
(
'
feature
'
,
Feature
)
Vue
.
component
(
'
result
'
,
Result
)
/* eslint-disable no-new */
new
Vue
({
...
...
Markus Opolka
@bi40resu
mentioned in issue
#6 (closed)
·
Jan 18, 2018
mentioned in issue
#6 (closed)
mentioned in issue #6
Toggle commit list
Markus Opolka
@bi40resu
mentioned in issue
#2 (closed)
·
Jan 18, 2018
mentioned in issue
#2 (closed)
mentioned in issue #2
Toggle commit list
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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