Skip to content
Snippets Groups Projects
Commit 4644ba3a authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Completed search functionality; fixed paginator issue

parent d9e8fd00
No related branches found
No related tags found
No related merge requests found
Showing with 105 additions and 42 deletions
VUE_APP_API_CLIENT = 'mock' VUE_APP_API_CLIENT = 'mock'
VUE_APP_API_BASE_URL = ''
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</span> </span>
</b-list-group-item> </b-list-group-item>
</b-list-group> </b-list-group>
<Paginator :paginatedPanel="model.genericSearchResults" :onUpdate="updateSearchResults" /> <Paginator :paginatedPanel="model.genericSearchResults" :onUpdate="updateSearchResults" :paginatorInput="input.genericSearch" />
</div> </div>
</div> </div>
</template> </template>
...@@ -47,7 +47,10 @@ export default { ...@@ -47,7 +47,10 @@ export default {
} }
}, },
updateSearchResults: function() { updateSearchResults: function() {
client.search(this.input)
.then(results => {
this.$store.commit('displaySearchResults', results);
});
} }
} }
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</b-list-group> </b-list-group>
<p v-if="model.groupsPanel.items.length === 0">No groups</p> <p v-if="model.groupsPanel.items.length === 0">No groups</p>
</div> </div>
<Paginator :paginatedPanel="model.groupsPanel" :onUpdate="updatePagination" /> <Paginator :paginatedPanel="model.groupsPanel" :onUpdate="updatePagination" :paginatorInput="input" />
<RenameGroupModal ref="renameGroupModal" /> <RenameGroupModal ref="renameGroupModal" />
<ConfirmRemoveGroupModal ref="confirmRemoveGroupModal" /> <ConfirmRemoveGroupModal ref="confirmRemoveGroupModal" />
</b-tab> </b-tab>
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
</b-list-group> </b-list-group>
<p v-if="model.membersPanel.items.length === 0">No direct members</p> <p v-if="model.membersPanel.items.length === 0">No direct members</p>
</div> </div>
<Paginator :paginatedPanel="model.membersPanel" :onUpdate="updatePagination" /> <Paginator :paginatedPanel="model.membersPanel" :onUpdate="updatePagination" :paginatorInput="input" />
<ConfirmRemoveMemberModal ref="confirmRemoveMemberModal" /> <ConfirmRemoveMemberModal ref="confirmRemoveMemberModal" />
</b-tab> </b-tab>
</template> </template>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<label for="page-size">Page size:</label> <label for="page-size">Page size:</label>
</b-col> </b-col>
<b-col sm="6"> <b-col sm="6">
<b-form-select id="page-size" v-model="input.paginatorPageSize" :options="pageSizeOptions" v-on:change="changePageSize"></b-form-select> <b-form-select id="page-size" v-model="paginatorInput.paginatorPageSize" :options="pageSizeOptions" v-on:change="changePageSize"></b-form-select>
</b-col> </b-col>
</b-row> </b-row>
</div> </div>
...@@ -26,11 +26,12 @@ export default { ...@@ -26,11 +26,12 @@ export default {
name: 'Paginator', name: 'Paginator',
props: { props: {
paginatedPanel: Object, paginatedPanel: Object,
onUpdate: Function onUpdate: Function,
paginatorInput: Object
}, },
computed: mapState({ /*computed: mapState({
input: state => state.input input: state => state.input
}), }),*/
data: function() { data: function() {
return { return {
pageSizeOptions: [{ pageSizeOptions: [{
...@@ -54,11 +55,11 @@ export default { ...@@ -54,11 +55,11 @@ export default {
}, },
methods: { methods: {
setPage: function(page) { setPage: function(page) {
this.input.paginatorPage = page; this.paginatorInput.paginatorPage = page;
this.onUpdate(); this.onUpdate();
}, },
changePageSize: function(pageSize) { changePageSize: function(pageSize) {
this.input.paginatorPageSize = pageSize; this.paginatorInput.paginatorPageSize = pageSize;
this.onUpdate(); this.onUpdate();
} }
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
</table> </table>
<p v-if="model.permissionsPanel.items.length === 0">No direct permissions</p> <p v-if="model.permissionsPanel.items.length === 0">No direct permissions</p>
</div> </div>
<Paginator :paginatedPanel="model.permissionsPanel" :onUpdate="updatePagination" /> <Paginator :paginatedPanel="model.permissionsPanel" :onUpdate="updatePagination" :paginatorInput="input" />
<ConfirmRemovePermissionModal ref="confirmRemovePermissionModal" /> <ConfirmRemovePermissionModal ref="confirmRemovePermissionModal" />
</b-tab> </b-tab>
</template> </template>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<!-- Right aligned nav items --> <!-- Right aligned nav items -->
<b-navbar-nav class="ml-auto"> <b-navbar-nav class="ml-auto">
<b-nav-form> <b-nav-form>
<b-form-input size="sm" class="mr-sm-2" placeholder="Search" v-model="input.genericSearch.filter"></b-form-input> <b-form-input size="sm" class="mr-sm-2" placeholder="Search" v-model="input.genericSearch.filter" @keydown.native.enter="genericSearch"></b-form-input>
<b-button size="sm" class="my-2 my-sm-0" type="button" v-on:click="genericSearch()">Search</b-button> <b-button size="sm" class="my-2 my-sm-0" type="button" v-on:click="genericSearch()">Search</b-button>
</b-nav-form> </b-nav-form>
<b-nav-item-dropdown :text="user" right v-if="user"> <b-nav-item-dropdown :text="user" right v-if="user">
...@@ -40,7 +40,12 @@ export default { ...@@ -40,7 +40,12 @@ export default {
showMainPage() { showMainPage() {
this.$store.commit('showMainPage'); this.$store.commit('showMainPage');
}, },
genericSearch() { genericSearch(event) {
// prevent the page reload if enter is pressed
if (event) {
event.preventDefault();
}
this.input.genericSearch.page = 1; this.input.genericSearch.page = 1;
this.input.genericSearch.pageSize = 20; this.input.genericSearch.pageSize = 20;
client.search(this.input) client.search(this.input)
......
...@@ -30,9 +30,9 @@ export default new Vuex.Store({ ...@@ -30,9 +30,9 @@ export default new Vuex.Store({
paginatorPage: 1, paginatorPage: 1,
selectedTab: 'groups', selectedTab: 'groups',
tabIndex: 0, tabIndex: 0,
searchFilter: null, searchFilter: '',
genericSearch: { genericSearch: {
filter: null, filter: '',
paginatorPage: 1, paginatorPage: 1,
paginatorPageSize: 20 paginatorPageSize: 20
} }
......
...@@ -19,11 +19,21 @@ public class PaginatedData<T> { ...@@ -19,11 +19,21 @@ public class PaginatedData<T> {
public PaginatedData(List<T> allItems, int page, int pageSize) { public PaginatedData(List<T> allItems, int page, int pageSize) {
if (page < 1) {
throw new IllegalArgumentException("Page numbers start from 1");
}
totalItems = allItems.size(); totalItems = allItems.size();
this.currentPage = page;
this.pageSize = pageSize; this.pageSize = pageSize;
totalPages = (int) Math.ceil((double) totalItems / pageSize); totalPages = totalItems == 0 ? 1 : (int) Math.ceil((double) totalItems / pageSize);
if (page <= totalPages) {
this.currentPage = page;
} else {
// back to last available page
this.currentPage = totalPages;
}
if (allItems.isEmpty()) { if (allItems.isEmpty()) {
items = allItems; items = allItems;
......
...@@ -75,16 +75,23 @@ public class SearchService { ...@@ -75,16 +75,23 @@ public class SearchService {
// Select only the groups visible to the user // Select only the groups visible to the user
List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId); List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId);
List<SearchResponseItem> items = new ArrayList<>(); List<Map.Entry<String, String>> groupsIdPath = new ArrayList<>();
for (GroupEntity group : allGroups) { for (GroupEntity group : allGroups) {
PermissionUtils.getGroupPermission(group, permissions).ifPresent(permission -> { PermissionUtils.getGroupPermission(group, permissions).ifPresent(permission -> {
groupsIdPath.add(new SimpleEntry<>(group.getId(), group.getPath()));
});
}
List<SearchResponseItem> items = new ArrayList<>();
Map<String, List<String>> groupNames = groupNameService.getNames(groupsIdPath);
for (Map.Entry<String, String> entry : groupsIdPath) {
String groupId = entry.getKey();
SearchResponseItem item = new SearchResponseItem(); SearchResponseItem item = new SearchResponseItem();
item.setType(SearchResponseType.GROUP); item.setType(SearchResponseType.GROUP);
item.setId(group.getId()); item.setId(groupId);
item.setLabel(group.getName()); List<String> names = groupNames.get(groupId);
item.setLabel(String.join(" / ", names));
items.add(item); items.add(item);
});
} }
return items; return items;
......
...@@ -56,4 +56,35 @@ public class PaginatedDataTest { ...@@ -56,4 +56,35 @@ public class PaginatedDataTest {
assertEquals(6, (int) paginatedData.getLinks().get(0)); assertEquals(6, (int) paginatedData.getLinks().get(0));
assertEquals(10, (int) paginatedData.getLinks().get(4)); assertEquals(10, (int) paginatedData.getLinks().get(4));
} }
/**
* When the page size change (from a smaller size to a bigger size) and we
* are in the last page it could be that we need to set a lower page number
* because the selected page is empty.
*/
@Test
public void testGoToLastPageIfPageOverflow() {
List<Integer> allItems = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
allItems.add(i);
}
PaginatedData<Integer> paginatedData = new PaginatedData<>(allItems, 2, 20);
assertEquals(1, paginatedData.getCurrentPage()); // back to last page
assertEquals(6, paginatedData.getItems().size());
assertEquals(6, paginatedData.getTotalItems());
}
@Test(expected = IllegalArgumentException.class)
public void testIllegalPageNumber() {
new PaginatedData<>(new ArrayList<>(), 0, 20);
}
@Test
public void testPageOneForEmptyList() {
PaginatedData<Integer> paginatedData = new PaginatedData<>(new ArrayList<>(), 1, 20);
assertEquals(1, paginatedData.getCurrentPage());
}
} }
...@@ -21,6 +21,7 @@ import java.util.List; ...@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
...@@ -54,6 +55,28 @@ public class SearchServiceTest { ...@@ -54,6 +55,28 @@ public class SearchServiceTest {
@InjectMocks @InjectMocks
private SearchService searchService; private SearchService searchService;
@Before
public void mockGroupNameService() {
when(groupNameService.getNames(any())).then(invocation -> {
Map<String, List<String>> result = new HashMap<>();
List<Map.Entry<String, String>> arg = invocation.getArgument(0);
for (Entry<String, String> entry : arg) {
List<String> names = new ArrayList<>();
switch (entry.getKey()) {
case "ROOT":
names.add("Root");
break;
case "group1_id":
names.add("Group 1");
break;
}
result.put(entry.getKey(), names);
}
return result;
});
}
@Test @Test
public void testGenericSearch() { public void testGenericSearch() {
...@@ -140,24 +163,6 @@ public class SearchServiceTest { ...@@ -140,24 +163,6 @@ public class SearchServiceTest {
root.setPath(""); root.setPath("");
when(groupsService.getRoot()).thenReturn(root); when(groupsService.getRoot()).thenReturn(root);
when(groupNameService.getNames(any())).then(invocation -> {
Map<String, List<String>> result = new HashMap<>();
List<Map.Entry<String, String>> arg = invocation.getArgument(0);
for (Entry<String, String> entry : arg) {
List<String> names = new ArrayList<>();
switch (entry.getKey()) {
case "ROOT":
names.add("Root");
break;
case "group1_id":
names.add("Group 1");
break;
}
result.put(entry.getKey(), names);
}
return result;
});
UserSearchResponse response = searchService.getUserSearchResult("admin_id", "target_id"); UserSearchResponse response = searchService.getUserSearchResult("admin_id", "target_id");
assertEquals(1, response.getGroups().size()); assertEquals(1, response.getGroups().size());
assertEquals(1, response.getPermissions().size()); assertEquals(1, response.getPermissions().size());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment