From 3aac16a7e82d4d093234519c7ecc5af37d79d64a Mon Sep 17 00:00:00 2001 From: Sonia Zorba <sonia.zorba@inaf.it> Date: Mon, 24 Aug 2020 20:12:16 +0200 Subject: [PATCH] Completed download CSV status feature --- gms-ui/src/components/GroupsBreadcrumb.vue | 18 ++++++++++++--- gms-ui/src/main.js | 4 ++-- .../ia2/gms/controller/GroupsController.java | 22 +++++++++++++++++++ .../ia2/gms/manager/GroupStatusManager.java | 15 ++++++++++--- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/gms-ui/src/components/GroupsBreadcrumb.vue b/gms-ui/src/components/GroupsBreadcrumb.vue index 283c847..f1e6f6c 100644 --- a/gms-ui/src/components/GroupsBreadcrumb.vue +++ b/gms-ui/src/components/GroupsBreadcrumb.vue @@ -1,11 +1,14 @@ <template> -<nav aria-label="breadcrumb"> +<nav aria-label="breadcrumb" id="groups-breadcrumbs"> <ol class="breadcrumb"> <li class="breadcrumb-item" v-for="group in groups" v-bind:class="{ active: group.active }" v-bind:key="group.groupId"> <a href="#" v-on:click="changeBreadcrumb(group.groupId)" v-if="!group.active">{{group.groupName}}</a> <span v-if="group.active">{{group.groupName}}</span> </li> </ol> + <a :href="'group/status/' + currentGroup.groupId" :download="currentGroup.groupName + '.csv'" id="csv-status-download" title="Download CSV"> + <font-awesome-icon icon="download"></font-awesome-icon> + </a> </nav> </template> @@ -35,7 +38,9 @@ export default { computed: mapState({ model: state => state.model, input: state => state.input, - groups: state => buildItems(state.model.breadcrumbs) + groups: state => buildItems(state.model.breadcrumbs), + isAdmin: state => state.model.permission === 'ADMIN', + currentGroup: state => state.model.breadcrumbs[state.model.breadcrumbs.length - 1] }), methods: { changeBreadcrumb: function(groupId) { @@ -55,7 +60,14 @@ export default { </script> <style scoped> -nav { +#groups-breadcrumbs { margin-top: 10px; + position: relative; +} + +#csv-status-download { + position: absolute; + right: 18px; + top: 12px; } </style> diff --git a/gms-ui/src/main.js b/gms-ui/src/main.js index 255ab43..2a64d2f 100644 --- a/gms-ui/src/main.js +++ b/gms-ui/src/main.js @@ -5,14 +5,14 @@ import store from './store.js' import './plugins/bootstrap-vue' import App from './App.vue' import { library } from '@fortawesome/fontawesome-svg-core' -import { faTrash, faEdit, faSpinner, faFolder, faUser, faSave } from '@fortawesome/free-solid-svg-icons' +import { faTrash, faEdit, faSpinner, faFolder, faUser, faSave, faDownload } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import VueRouter from 'vue-router' Vue.use(VueRouter) import router from './router.js'; -library.add(faTrash, faEdit, faSpinner, faFolder, faUser, faSave); +library.add(faTrash, faEdit, faSpinner, faFolder, faUser, faSave, faDownload); Vue.component('font-awesome-icon', FontAwesomeIcon); diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java index 8b1f13d..fe9137e 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java +++ b/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java @@ -1,6 +1,8 @@ package it.inaf.ia2.gms.controller; +import com.opencsv.CSVWriter; import it.inaf.ia2.gms.authn.SessionData; +import it.inaf.ia2.gms.manager.GroupStatusManager; import it.inaf.ia2.gms.manager.GroupsManager; import it.inaf.ia2.gms.model.request.AddGroupRequest; import it.inaf.ia2.gms.model.GroupNode; @@ -12,6 +14,9 @@ import it.inaf.ia2.gms.model.request.RenameGroupRequest; import it.inaf.ia2.gms.model.request.SearchFilterRequest; import it.inaf.ia2.gms.persistence.model.GroupEntity; import it.inaf.ia2.gms.service.GroupsTreeBuilder; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -40,6 +45,9 @@ public class GroupsController { @Autowired private GroupsTabResponseBuilder groupsTabResponseBuilder; + @Autowired + private GroupStatusManager groupStatusManager; + @GetMapping(value = "/groups", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> getGroupsTab(@Valid GroupsRequest request) { if (request.isOnlyPanel()) { @@ -85,6 +93,20 @@ public class GroupsController { return ResponseEntity.ok(groupsPanel); } + @GetMapping(value = "/group/status/{groupId}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public void downloadStatus(@PathVariable("groupId") String groupId, HttpServletResponse response) throws Exception { + + try (OutputStream out = response.getOutputStream(); + CSVWriter writer = new CSVWriter(new OutputStreamWriter(out))) { + + writer.writeNext(new String[]{"program", "email"}); + + for (String[] row : groupStatusManager.generateStatus(groupId)) { + writer.writeNext(row); + } + } + } + private <T extends PaginatedModelRequest & SearchFilterRequest> PaginatedData<GroupNode> getGroupsPanel(GroupEntity parentGroup, T request) { return groupsTreeBuilder.listSubGroups(parentGroup, request, session.getUserId()); } diff --git a/gms/src/main/java/it/inaf/ia2/gms/manager/GroupStatusManager.java b/gms/src/main/java/it/inaf/ia2/gms/manager/GroupStatusManager.java index e6d2b38..07cbb42 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/manager/GroupStatusManager.java +++ b/gms/src/main/java/it/inaf/ia2/gms/manager/GroupStatusManager.java @@ -9,7 +9,9 @@ import it.inaf.ia2.gms.persistence.model.GroupEntity; import it.inaf.ia2.gms.persistence.model.MembershipEntity; import it.inaf.ia2.gms.rap.RapClient; import it.inaf.ia2.gms.service.GroupNameService; +import it.inaf.ia2.gms.service.GroupsService; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,6 +29,9 @@ public class GroupStatusManager extends UserAwareComponent { @Autowired private PermissionsManager permissionsManager; + @Autowired + private GroupsService groupsService; + @Autowired private GroupsDAO groupsDAO; @@ -39,7 +44,9 @@ public class GroupStatusManager extends UserAwareComponent { @Autowired private RapClient rapClient; - public List<Object[]> generateStatus(GroupEntity parentGroup) { + public List<String[]> generateStatus(String groupId) { + + GroupEntity parentGroup = groupsService.getGroupById(groupId); Permission groupPermission = permissionsManager.getCurrentUserPermission(parentGroup); @@ -72,7 +79,7 @@ public class GroupStatusManager extends UserAwareComponent { usersMap.put(user.getId(), user.getPrimaryEmail()); } - List<Object[]> rows = new ArrayList<>(); + List<String[]> rows = new ArrayList<>(); for (int i = 0; i < groups.size(); i++) { GroupEntity group = groups.get(i); @@ -85,12 +92,14 @@ public class GroupStatusManager extends UserAwareComponent { LOG.warn("Unable to retrieve information about user " + userId); continue; } - Object[] row = new Object[]{groupName, email}; + String[] row = new String[]{groupName, email}; rows.add(row); } } } + Collections.sort(rows, (r1, r2) -> (r1[0]).compareTo(r2[0])); + return rows; } } -- GitLab