Loading gms-ui/src/components/GroupsBreadcrumb.vue +15 −3 Original line number Diff line number Diff line <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> Loading Loading @@ -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) { Loading @@ -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> gms-ui/src/main.js +2 −2 Original line number Diff line number Diff line Loading @@ -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); Loading gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java +22 −0 Original line number Diff line number Diff line 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; Loading @@ -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; Loading Loading @@ -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()) { Loading Loading @@ -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()); } Loading gms/src/main/java/it/inaf/ia2/gms/manager/GroupStatusManager.java +12 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -27,6 +29,9 @@ public class GroupStatusManager extends UserAwareComponent { @Autowired private PermissionsManager permissionsManager; @Autowired private GroupsService groupsService; @Autowired private GroupsDAO groupsDAO; Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; } } Loading
gms-ui/src/components/GroupsBreadcrumb.vue +15 −3 Original line number Diff line number Diff line <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> Loading Loading @@ -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) { Loading @@ -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>
gms-ui/src/main.js +2 −2 Original line number Diff line number Diff line Loading @@ -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); Loading
gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java +22 −0 Original line number Diff line number Diff line 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; Loading @@ -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; Loading Loading @@ -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()) { Loading Loading @@ -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()); } Loading
gms/src/main/java/it/inaf/ia2/gms/manager/GroupStatusManager.java +12 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -27,6 +29,9 @@ public class GroupStatusManager extends UserAwareComponent { @Autowired private PermissionsManager permissionsManager; @Autowired private GroupsService groupsService; @Autowired private GroupsDAO groupsDAO; Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; } }