Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
gy4443
chemotion_eln_server
Commits
0a064d63
Commit
0a064d63
authored
Oct 14, 2015
by
Florian Hübsch
Browse files
Fix pagination and add pagination to SearchAPI.
parent
c797986e
Changes
11
Hide whitespace changes
Inline
Side-by-side
app/api/chemotion/search_api.rb
View file @
0a064d63
...
...
@@ -2,29 +2,54 @@ module Chemotion
class
SearchAPI
<
Grape
::
API
include
Grape
::
Kaminari
# TODO implement search cache?
helpers
do
def
serialization_by_elements
(
elements
)
serialized_samples
=
elements
.
fetch
(
:samples
,
[]).
map
{
|
s
|
SampleSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
serialized_reactions
=
elements
.
fetch
(
:reactions
,
[]).
map
{
|
s
|
ReactionSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
serialized_wellplates
=
elements
.
fetch
(
:wellplates
,
[]).
map
{
|
s
|
WellplateSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
serialized_screens
=
elements
.
fetch
(
:screens
,
[]).
map
{
|
s
|
ScreenSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
def
page_size
7
end
def
pages
(
total_elements
)
total_elements
.
fdiv
(
page_size
).
ceil
end
def
serialization_by_elements_and_page
(
elements
,
page
=
1
)
samples
=
elements
.
fetch
(
:samples
,
[])
reactions
=
elements
.
fetch
(
:reactions
,
[])
wellplates
=
elements
.
fetch
(
:wellplates
,
[])
screens
=
elements
.
fetch
(
:screens
,
[])
serialized_samples
=
Kaminari
.
paginate_array
(
samples
).
page
(
page
).
per
(
page_size
).
map
{
|
s
|
SampleSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
serialized_reactions
=
Kaminari
.
paginate_array
(
reactions
).
page
(
page
).
per
(
page_size
).
map
{
|
s
|
ReactionSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
serialized_wellplates
=
Kaminari
.
paginate_array
(
wellplates
).
page
(
page
).
per
(
page_size
).
map
{
|
s
|
WellplateSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
serialized_screens
=
Kaminari
.
paginate_array
(
screens
).
page
(
page
).
per
(
page_size
).
map
{
|
s
|
ScreenSerializer
.
new
(
s
).
serializable_hash
.
deep_symbolize_keys
}
{
samples:
{
elements:
serialized_samples
,
totalElements:
elements
.
fetch
(
:samples
,
[]).
size
totalElements:
samples
.
size
,
page:
page
,
pages:
pages
(
samples
.
size
),
per_page:
page_size
},
reactions:
{
elements:
serialized_reactions
,
totalElements:
elements
.
fetch
(
:reactions
,
[]).
size
totalElements:
reactions
.
size
,
page:
page
,
pages:
pages
(
reactions
.
size
),
per_page:
page_size
},
wellplates:
{
elements:
serialized_wellplates
,
totalElements:
elements
.
fetch
(
:wellplates
,
[]).
size
totalElements:
wellplates
.
size
,
page:
page
,
pages:
pages
(
wellplates
.
size
),
per_page:
page_size
},
screens:
{
elements:
serialized_screens
,
totalElements:
elements
.
fetch
(
:screens
,
[]).
size
totalElements:
screens
.
size
,
page:
page
,
pages:
pages
(
screens
.
size
),
per_page:
page_size
}
}
end
...
...
@@ -43,10 +68,11 @@ module Chemotion
AllElementSearch
.
new
(
arg
).
search_by_substring
end
# TODO only elements of current user
unless
params
[
:collection_id
]
==
"all"
scope
=
scope
.
by_collection_id
(
params
[
:collection_id
].
to_i
)
end
scope
scope
# joins(:collections).where('collections.user_id = ?', current_user.id).references(:collections)
end
def
elements_by_scope
(
scope
)
...
...
@@ -68,7 +94,7 @@ module Chemotion
when
Wellplate
elements
[
:wellplates
]
=
scope
elements
[
:screens
]
=
scope
.
flat_map
(
&
:screen
).
compact
.
uniq
elements
[
:samples
]
=
scope
.
flat_map
(
&
:
wells
).
compact
.
flat_map
(
&
:
sample
).
uniq
elements
[
:samples
]
=
scope
.
flat_map
(
&
:sample
s
).
uniq
elements
[
:reactions
]
=
elements
[
:samples
].
flat_map
(
&
:reactions
).
uniq
when
Screen
elements
[
:screens
]
=
scope
...
...
@@ -88,8 +114,9 @@ module Chemotion
resource
:search
do
namespace
:all
do
desc
"Return all matched elements and associations"
desc
"Return all matched elements and associations
for substring query
"
params
do
optional
:page
,
type:
Integer
requires
:selection
,
type:
Hash
requires
:collection_id
,
type:
String
end
...
...
@@ -100,13 +127,14 @@ module Chemotion
scope
=
scope_by_search_by_method_arg_and_collection_id
(
search_by_method
,
arg
,
params
[
:collection_id
])
serialization_by_elements
(
elements_by_scope
(
scope
))
serialization_by_elements
_and_page
(
elements_by_scope
(
scope
)
,
params
[
:page
]
)
end
end
namespace
:samples
do
desc
"Return samples and associated elements by search selection"
params
do
optional
:page
,
type:
Integer
requires
:selection
,
type:
Hash
requires
:collection_id
,
type:
String
end
...
...
@@ -122,13 +150,14 @@ module Chemotion
samples
=
scope
.
by_collection_id
(
params
[
:collection_id
].
to_i
)
end
serialization_by_elements
(
elements_by_scope
(
samples
))
serialization_by_elements
(
elements_by_scope
(
samples
)
,
params
[
:page
]
)
end
end
namespace
:reactions
do
desc
"Return reactions and associated elements by search selection"
params
do
optional
:page
,
type:
Integer
requires
:selection
,
type:
Hash
requires
:collection_id
,
type:
String
end
...
...
@@ -144,13 +173,14 @@ module Chemotion
reactions
=
scope
.
by_collection_id
(
params
[
:collection_id
].
to_i
)
end
serialization_by_elements
(
elements_by_scope
(
reactions
))
serialization_by_elements
(
elements_by_scope
(
reactions
)
,
params
[
:page
]
)
end
end
namespace
:wellplates
do
desc
"Return wellplates and associated elements by search selection"
params
do
optional
:page
,
type:
Integer
requires
:selection
,
type:
Hash
requires
:collection_id
,
type:
String
end
...
...
@@ -166,13 +196,14 @@ module Chemotion
wellplates
=
scope
.
by_collection_id
(
params
[
:collection_id
].
to_i
)
end
serialization_by_elements
(
elements_by_scope
(
wellplates
))
serialization_by_elements
(
elements_by_scope
(
wellplates
)
,
params
[
:page
]
)
end
end
namespace
:screens
do
desc
"Return wellplates and associated elements by search selection"
params
do
optional
:page
,
type:
Integer
requires
:selection
,
type:
Hash
requires
:collection_id
,
type:
String
end
...
...
@@ -188,7 +219,7 @@ module Chemotion
screens
=
scope
.
by_collection_id
(
params
[
:collection_id
].
to_i
)
end
serialization_by_elements
(
elements_by_scope
(
screens
))
serialization_by_elements
(
elements_by_scope
(
screens
)
,
params
[
:page
]
)
end
end
...
...
app/assets/javascripts/components/App.js
View file @
0a064d63
...
...
@@ -111,7 +111,7 @@ Aviator.setRoutes({
}
else
{
console
.
log
(
"
generateEmptyReaction
"
)
ElementActions
.
generateEmptyReaction
()
}
}
}
},
'
/:reactionID
'
:
'
show
'
,
...
...
@@ -125,6 +125,7 @@ Aviator.setRoutes({
}
else
{
ElementActions
.
fetchWellplateById
(
wellplateId
);
}
//UIActions.selectTab(3)
}
},
'
/:wellplateId
'
:
'
showOrNew
'
...
...
app/assets/javascripts/components/ElementsTable.js
View file @
0a064d63
...
...
@@ -78,7 +78,6 @@ export default class ElementsTable extends React.Component {
let
elementsDidChange
=
elements
&&
!
deepEqual
(
elements
,
this
.
state
.
elements
);
let
currentElementDidChange
=
!
deepEqual
(
currentElement
,
this
.
state
.
currentElement
);
if
(
elementsDidChange
)
{
this
.
setState
({
elements
,
page
,
pages
,
perPage
,
totalElements
,
currentElement
...
...
app/assets/javascripts/components/List.js
View file @
0a064d63
...
...
@@ -54,6 +54,28 @@ export default class List extends React.Component {
handleTabSelect
(
tab
)
{
UIActions
.
selectTab
(
tab
);
// TODO sollte in tab action handler
let
type
;
switch
(
tab
)
{
case
1
:
type
=
'
sample
'
;
break
;
case
2
:
type
=
'
reaction
'
;
break
;
case
3
:
type
=
'
wellplate
'
;
break
;
case
4
:
type
=
'
screen
'
;
}
let
uiState
=
UIStore
.
getState
();
let
page
=
uiState
[
type
].
page
;
UIActions
.
setPagination
({
type
:
type
,
page
:
page
})
}
render
()
{
...
...
app/assets/javascripts/components/actions/ElementActions.js
View file @
0a064d63
...
...
@@ -24,8 +24,8 @@ class ElementActions {
// -- Search --
fetchBasedOnSearchSelectionAndCollection
(
selection
,
collectionId
)
{
SearchFetcher
.
fetchBasedOnSearchSelectionAndCollection
(
selection
,
collectionId
)
fetchBasedOnSearchSelectionAndCollection
(
selection
,
collectionId
,
currentPage
)
{
SearchFetcher
.
fetchBasedOnSearchSelectionAndCollection
(
selection
,
collectionId
,
currentPage
)
.
then
((
result
)
=>
{
this
.
dispatch
(
result
);
}).
catch
((
errorMessage
)
=>
{
...
...
app/assets/javascripts/components/fetchers/SearchFetcher.js
View file @
0a064d63
...
...
@@ -5,7 +5,7 @@ import Wellplate from '../models/Wellplate';
import
Screen
from
'
../models/Screen
'
;
export
default
class
SearchFetcher
{
static
fetchBasedOnSearchSelectionAndCollection
(
selection
,
collectionId
)
{
static
fetchBasedOnSearchSelectionAndCollection
(
selection
,
collectionId
,
currentPage
)
{
let
promise
=
fetch
(
'
/api/v1/search/
'
+
selection
.
elementType
,
{
credentials
:
'
same-origin
'
,
method
:
'
POST
'
,
...
...
@@ -15,7 +15,8 @@ export default class SearchFetcher {
},
body
:
JSON
.
stringify
({
selection
:
selection
,
collection_id
:
collectionId
collection_id
:
collectionId
,
page
:
currentPage
})
})
.
then
((
response
)
=>
{
...
...
@@ -23,19 +24,31 @@ export default class SearchFetcher {
}).
then
((
json
)
=>
{
let
samples
=
{
elements
:
json
.
samples
.
elements
.
map
((
s
)
=>
new
Sample
(
s
)),
totalElements
:
json
.
samples
.
totalElements
totalElements
:
json
.
samples
.
totalElements
,
page
:
json
.
samples
.
page
,
pages
:
json
.
samples
.
pages
,
perPage
:
json
.
samples
.
per_page
}
let
reactions
=
{
reactions
:
json
.
reactions
.
elements
.
map
((
r
)
=>
new
Reaction
(
r
)),
totalElements
:
json
.
reactions
.
totalElements
elements
:
json
.
reactions
.
elements
.
map
((
r
)
=>
new
Reaction
(
r
)),
totalElements
:
json
.
reactions
.
totalElements
,
page
:
json
.
reactions
.
page
,
pages
:
json
.
reactions
.
pages
,
perPage
:
json
.
reactions
.
per_page
}
let
wellplates
=
{
wellplates
:
json
.
wellplates
.
elements
.
map
((
w
)
=>
new
Wellplate
(
w
)),
totalElements
:
json
.
wellplates
.
totalElements
elements
:
json
.
wellplates
.
elements
.
map
((
w
)
=>
new
Wellplate
(
w
)),
totalElements
:
json
.
wellplates
.
totalElements
,
page
:
json
.
wellplates
.
page
,
pages
:
json
.
wellplates
.
pages
,
perPage
:
json
.
wellplates
.
per_page
}
let
screens
=
{
screens
:
json
.
screens
.
elements
.
map
((
s
)
=>
new
Screen
(
s
)),
totalElements
:
json
.
screens
.
totalElements
elements
:
json
.
screens
.
elements
.
map
((
s
)
=>
new
Screen
(
s
)),
totalElements
:
json
.
screens
.
totalElements
,
page
:
json
.
screens
.
page
,
pages
:
json
.
screens
.
pages
,
perPage
:
json
.
screens
.
per_page
}
return
{
...
...
app/assets/javascripts/components/search/Search.js
View file @
0a064d63
...
...
@@ -24,7 +24,7 @@ export default class Search extends React.Component {
UIActions
.
setSearchSelection
(
selection
);
let
uiState
=
UIStore
.
getState
();
ElementActions
.
fetchBasedOnSearchSelectionAndCollection
(
selection
,
uiState
.
currentCollection
.
id
);
ElementActions
.
fetchBasedOnSearchSelectionAndCollection
(
selection
,
uiState
.
currentCollection
.
id
,
1
);
}
search
(
query
)
{
...
...
app/assets/javascripts/components/stores/ElementStore.js
View file @
0a064d63
...
...
@@ -14,28 +14,28 @@ class ElementStore {
totalElements
:
0
,
page
:
null
,
pages
:
null
,
per
_p
age
:
null
per
P
age
:
null
},
reactions
:
{
elements
:
[],
totalElements
:
0
,
page
:
null
,
pages
:
null
,
per
_p
age
:
null
per
P
age
:
null
},
wellplates
:
{
elements
:
[],
totalElements
:
0
,
page
:
null
,
pages
:
null
,
per
_p
age
:
null
per
P
age
:
null
},
screens
:
{
elements
:
[],
totalElements
:
0
,
page
:
null
,
pages
:
null
,
per
_p
age
:
null
per
P
age
:
null
}
},
currentElement
:
null
...
...
@@ -71,6 +71,7 @@ class ElementStore {
handleCreateScreen
:
ElementActions
.
createScreen
,
handleUnselectCurrentElement
:
UIActions
.
deselectAllElements
,
// FIXME ElementStore listens to UIActions?
handleSetPagination
:
UIActions
.
setPagination
,
handleRefreshElements
:
ElementActions
.
refreshElements
,
handleGenerateEmptyElement
:
[
ElementActions
.
generateEmptyWellplate
,
ElementActions
.
generateEmptyScreen
,
ElementActions
.
generateEmptySample
,
ElementActions
.
generateEmptyReaction
],
...
...
@@ -265,19 +266,29 @@ class ElementStore {
this
.
waitFor
(
UIStore
.
dispatchToken
);
let
uiState
=
UIStore
.
getState
();
let
page
=
uiState
[
type
].
page
;
switch
(
type
)
{
case
'
sample
'
:
ElementActions
.
fetchSamplesByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
case
'
reaction
'
:
ElementActions
.
fetchReactionsByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
case
'
wellplate
'
:
ElementActions
.
fetchWellplatesByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
case
'
screen
'
:
ElementActions
.
fetchScreensByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
this
.
state
.
elements
[
type
+
'
s
'
].
page
=
page
;
let
currentSearchSelection
=
uiState
.
currentSearchSelection
;
// TODO if page changed -> fetch
// if there is a currentSearchSelection we have to execute the respective action
if
(
currentSearchSelection
!=
null
)
{
ElementActions
.
fetchBasedOnSearchSelectionAndCollection
(
currentSearchSelection
,
uiState
.
currentCollection
.
id
,
page
);
}
else
{
switch
(
type
)
{
case
'
sample
'
:
ElementActions
.
fetchSamplesByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
case
'
reaction
'
:
ElementActions
.
fetchReactionsByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
case
'
wellplate
'
:
ElementActions
.
fetchWellplatesByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
case
'
screen
'
:
ElementActions
.
fetchScreensByCollectionId
(
uiState
.
currentCollection
.
id
,
{
page
:
page
});
break
;
}
}
}
}
...
...
app/assets/javascripts/components/stores/UIStore.js
View file @
0a064d63
...
...
@@ -63,7 +63,6 @@ class UIStore {
}
handleSelectTab
(
tab
)
{
console
.
log
(
'
handleSelectTab:
'
+
tab
)
this
.
state
.
currentTab
=
tab
;
}
...
...
@@ -127,6 +126,7 @@ class UIStore {
let
state
=
this
.
state
;
let
hasChanged
=
(
!
state
.
currentCollection
||
state
.
currentCollection
.
id
!=
collection
.
id
)
||
(
state
.
currentSearchSelection
!=
null
);
// TODO state.pagination does not make sense
if
(
hasChanged
)
{
this
.
state
.
currentCollection
=
collection
;
this
.
state
.
currentCollectionId
=
collection
.
id
;
...
...
@@ -138,6 +138,7 @@ class UIStore {
}
}
// FIXME this method is also defined in ElementStore
handleSetPagination
(
pagination
)
{
let
{
type
,
page
}
=
pagination
;
this
.
state
[
type
].
page
=
page
;
...
...
app/models/reaction.rb
View file @
0a064d63
...
...
@@ -81,7 +81,7 @@ class Reaction < ActiveRecord::Base
composer
=
SVG
::
ReactionComposer
.
new
(
inchikeys
,
label:
label
)
self
.
reaction_svg_file
=
composer
.
compose_reaction_svg_and_save
rescue
Exception
=>
e
p
"**** SVG::ReactionComposer failed ***"
Rails
.
logger
.
info
(
"**** SVG::ReactionComposer failed ***"
)
end
end
...
...
app/models/wellplate.rb
View file @
0a064d63
...
...
@@ -41,8 +41,4 @@ class Wellplate < ActiveRecord::Base
Well
.
where
(
wellplate_id:
id
).
delete_all
CollectionsWellplate
.
where
(
wellplate_id:
id
).
delete_all
end
def
samples
wells
.
flat_map
(
&
:sample
)
end
end
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