Project

General

Profile

« Previous | Next » 

Revision 57894

View differences:

modules/dnet-orgs-database-application/trunk/src/main/java/eu/dnetlib/organizations/model/utils/DedupEvents.java
1
package eu.dnetlib.organizations.model.utils;
2

  
3
import java.util.ArrayList;
4
import java.util.List;
5

  
6
import eu.dnetlib.organizations.model.OpenaireDuplicate;
7

  
8
public class DedupEvents {
9

  
10
	private final List<OpenaireDuplicate> duplicates = new ArrayList<>();
11
	private final List<OrganizationConflict> conflicts = new ArrayList<>();
12

  
13
	public List<OpenaireDuplicate> getDuplicates() {
14
		return duplicates;
15
	}
16

  
17
	public List<OrganizationConflict> getConflicts() {
18
		return conflicts;
19
	}
20

  
21
}
modules/dnet-orgs-database-application/trunk/src/main/java/eu/dnetlib/organizations/model/view/DuplicateGroupView.java
23 23
	@Column(name = "name")
24 24
	private String name;
25 25

  
26
	@Column(name = "city")
27
	private String city;
28

  
26 29
	@Column(name = "country")
27 30
	private String country;
28 31

  
......
45 48
		this.name = name;
46 49
	}
47 50

  
51
	public String getCity() {
52
		return city;
53
	}
54

  
55
	public void setCity(final String city) {
56
		this.city = city;
57
	}
58

  
48 59
	public String getCountry() {
49 60
		return country;
50 61
	}
modules/dnet-orgs-database-application/trunk/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java
26 26

  
27 27
import eu.dnetlib.organizations.model.OpenaireDuplicate;
28 28
import eu.dnetlib.organizations.model.utils.BrowseEntry;
29
import eu.dnetlib.organizations.model.utils.DedupEvents;
29
import eu.dnetlib.organizations.model.utils.OrganizationConflict;
30 30
import eu.dnetlib.organizations.model.utils.OrganizationConflictImpl;
31 31
import eu.dnetlib.organizations.model.view.ConflictGroupView;
32 32
import eu.dnetlib.organizations.model.view.DuplicateGroupView;
......
118 118
		}
119 119
	}
120 120

  
121
	@RequestMapping(value = "/dedupEvents", method = RequestMethod.GET)
122
	public DedupEvents dedupEvents(@RequestParam final String id, final Authentication authentication) {
121
	@RequestMapping(value = "/conflicts", method = RequestMethod.GET)
122
	public List<OrganizationConflict> conflicts(@RequestParam final String id, final Authentication authentication) {
123 123
		if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, authentication.getName())) {
124
			final DedupEvents res = new DedupEvents();
125
			res.getDuplicates().addAll(openaireDuplicateRepository.findByLocalId(id));
126
			res.getConflicts().addAll(openaireConflictRepository.getConflictsForId(id));
127
			return res;
124
			return openaireConflictRepository.getConflictsForId(id);
128 125
		} else {
129 126
			throw new RuntimeException("User not authorized");
130 127
		}
131 128
	}
132 129

  
130
	@RequestMapping(value = "/duplicates", method = RequestMethod.GET)
131
	public List<OpenaireDuplicate> duplicates(@RequestParam final String id, final Authentication authentication) {
132
		if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, authentication.getName())) {
133
			return openaireDuplicateRepository.findByLocalId(id);
134
		} else {
135
			throw new RuntimeException("User not authorized");
136
		}
137
	}
138

  
133 139
	@RequestMapping(value = "/conflicts/all", method = RequestMethod.GET)
134 140
	public Collection<Set<OrganizationConflictImpl>> findConflicts(final Authentication authentication) {
135 141

  
modules/dnet-orgs-database-application/trunk/src/main/resources/sql/schema.sql
250 250
CREATE VIEW duplicate_groups_view AS SELECT
251 251
	o.id,
252 252
	o.name,
253
	o.city,
253 254
	o.country,
254 255
	count(d.*) as n_duplicates
255 256
FROM
......
257 258
	LEFT OUTER JOIN organizations o ON (o.id = d.local_id)
258 259
WHERE
259 260
	d.reltype = 'suggested'
260
GROUP BY o.id, o.name, o.country
261
GROUP BY o.id, o.name, o.city, o.country
261 262
ORDER BY o.name;
262 263
	
modules/dnet-orgs-database-application/trunk/src/main/resources/static/resources/html/part/all_duplicates.html
5 5
	<table class="table table-sm table-hover">
6 6
		<thead class="thead-light">
7 7
			<tr class="d-flex">
8
				<th class="col-8">Organization</th>
9
				<th class="col-2 text-center">Country</th>
10
				<th class="col-2 text-right"># duplicates</th>
8
				<th class="col-7">Organization</th>
9
				<th class="col-3">Place</th>
10
				<th class="col-1 text-right"># duplicates</th>
11
				<th class="col-1"></th>
11 12
			</tr>
12 13
		</thead>
13 14
		<tbody>
14 15
			<tr ng-repeat="d in duplicates | filter:duplicateFilter" class="d-flex">
15
				<td class="col-8"><a href="#!/edit/0/{{d.id}}" title="{{d.id}}">{{d.name}}</a></td>
16
				<td class="col-2 text-center"><img ng-src="resources/images/flags/{{d.country}}.gif" /> {{d.country}}</td>
17
				<td class="col-2 text-right">{{d.numberOfDuplicates}}</td>
16
				<td class="col-7"><a href="#!/edit/0/{{d.id}}" title="{{d.id}}">{{d.name}}</a></td>
17
				<td class="col-3"><img ng-src="resources/images/flags/{{d.country}}.gif" /> {{d.city}}, {{d.country}}</td>
18
				<td class="col-1 text-right">{{d.numberOfDuplicates}}</td>
19
				<td class="col-1 text-right"><button class="btn btn-sm btn-primary" ng-click="prepareDuplicatesModal(d)" data-toggle="modal" data-target="#duplicatesModal">evaluate</button></td>
18 20
			</tr>
19 21
		</tbody>
20 22
	</table>	
21 23
</div>
24

  
25
<div class="modal fade" id="duplicatesModal" tabindex="-1" role="dialog">
26
	<div class="modal-dialog modal-xl" role="document">
27
		<div class="modal-content">
28
			<div class="modal-header">
29
				<h5 class="modal-title">{{currentOrg.name}}</h5>
30
				<button type="button" class="close" data-dismiss="modal">&times;</button>
31
			</div>
32
				
33
			<div class="modal-body" ng-if="currentDuplicates.length == 0">
34
				No duplicates
35
			</div>
36
					
37
			<table class="table table-sm mt-2"  ng-if="currentDuplicates.length > 0">
38
				<thead>
39
					<tr class="d-flex">
40
						<th class="col-4 pl-3" style="border-top: none;">Related organization</th>
41
						<th class="col-1 text-center" style="border-top: none;">Acronym</th>
42
						<th class="col-2 text-center" style="border-top: none;">Country</th>
43
						<th class="col-3" style="border-top: none;">Source</th>
44
						<th class="col-2" style="border-top: none;"></th>
45
					</tr>
46
				</thead>
47
				<tbody>
48
					<tr class="d-flex" ng-repeat="sr in currentDuplicates">
49
						<td class="col-4 pl-3">
50
							{{sr.oaName}}
51
							<span class="small" ng-if="sr.oaUrl" ><br /><b>URL: </b><a href="{{sr.oaUrl}}" target="_blank">{{sr.oaUrl}}</a></span>
52
						</td>
53
						<td class="col-1 text-center small">{{sr.oaAcronym}}</td>
54
						<td class="col-2 text-center small"><img ng-src="resources/images/flags/{{sr.oaCountry}}.gif" /> {{sr.oaCountry}}</td>
55
						<td class="col-3 small">
56
							<b>Collected from:</b> {{sr.oaCollectedFrom}}<br />
57
							<b>Original Id:</b> <span class="text-monospace">{{sr.oaOriginalId}}</span>
58
						</td>
59
						<td class="col-2 text-right">
60
							<div class="btn-group btn-group-toggle btn-group-sm" data-toggle="buttons">
61
								<label class="btn" ng-class="{'btn-danger' : sr.relType == 'is_different', 'btn-outline-danger' : sr.relType != 'is_different'}">
62
									<input type="radio" autocomplete="off" ng-model="sr.relType" value="is_different" ng-class="{'active' : sr.relType == 'is_different'}"><i class="fas fa-times fa-fw"></i>
63
								</label>
64
								<label class="btn" ng-class="{'btn-info' : sr.relType == 'suggested', 'btn-outline-info' : sr.relType != 'suggested'}">
65
									<input type="radio" autocomplete="off" ng-model="sr.relType" value="suggested" ng-class="{'active' : sr.relType == 'suggested'}"><i class="fas fa-question fa-fw"></i>
66
								</label>
67
								<label class="btn" ng-class="{'btn-success' : sr.relType == 'is_similar', 'btn-outline-success' : sr.relType != 'is_similar'}">
68
									<input type="radio" autocomplete="off" ng-model="sr.relType" value="is_similar" ng-class="{'active' : sr.relType == 'is_similar'}"/><i class="fas fa-check fa-fw"></i>
69
								</label>
70
							</div>		
71
						</td>
72
					</tr>
73
				</tbody>
74
			</table>
75
			<div class="modal-footer">
76
				<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
77
				<button type="button" class="btn btn-primary" data-dismiss="modal" ng-click="saveCurrentDuplicates()" ng-if="currentDuplicates.length > 0">Save changes</button>
78
			</div>
79
		</div>
80
	</div>
81
</div>
modules/dnet-orgs-database-application/trunk/src/main/resources/static/resources/js/organizations.js
53 53
			}
54 54
			
55 55
			scope.loadDedupEvents = function() {
56
				scope.events = [];
57
				$http.get('api/organizations/dedupEvents?id=' + scope.orgId).then(function successCallback(res) {
56
				scope.events = {};
57

  
58
				$http.get('api/organizations/conflicts?id=' + scope.orgId).then(function successCallback(res) {
58 59
					if((typeof res.data) == 'string') { alert("Session expired !"); location.reload(true); }
59
					scope.events = res.data;
60
					scope.events.conflicts = res.data;
61
					$http.get('api/organizations/duplicates?id=' + scope.orgId).then(function successCallback(res) {
62
						if((typeof res.data) == 'string') { alert("Session expired !"); location.reload(true); }
63
						scope.events.duplicates = res.data;
64
					}, function errorCallback(res) {
65
						alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
66
					});
60 67
				}, function errorCallback(res) {
61 68
					alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
62 69
				});
......
227 234
			'infoMethod'   : '&'
228 235
		},
229 236
		templateUrl: 'resources/html/part/all_duplicates.html',
230
		link: function(scope, element, attrs, ctrl) {}
237
		link: function(scope, element, attrs, ctrl) {
238
			scope.currentOrg = {};
239
			scope.currentDuplicates = [];
240
			
241
			scope.prepareDuplicatesModal = function(org) {
242
				scope.currentOrg = org;
243
				scope.currentDuplicates = [];
244
				$http.get('api/organizations/duplicates?id=' + org.id).then(function successCallback(res) {
245
					if((typeof res.data) == 'string') { alert("Session expired !"); location.reload(true); }
246
					scope.currentDuplicates = res.data;
247
				}, function errorCallback(res) {
248
					alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
249
				});
250
			};
251
			
252
			scope.saveCurrentDuplicates = function() {
253
				$http.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
254
				$http.post('api/organizations/duplicates', scope.currentDuplicates).then(function successCallback(res) {
255
					if((typeof res.data) == 'string') { alert("Session expired !"); location.reload(true); }
256
					if (scope.infoMethod)             { scope.infoMethod(); }
257
					scope.currentOrg.numberOfDuplicates = 0;
258
					for (var i=0; i<res.data.length; i++) {
259
						if (res.data[i].relType == 'suggested') {
260
							scope.currentOrg.numberOfDuplicates++;
261
						}
262
					}
263
					scope.currentDuplicates = [];
264
				}, function errorCallback(res) {
265
					alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
266
				});
267
			};
268
		}
231 269
     }
270
	
271
	
232 272
});
233 273

  
234 274
orgsModule.config(function($routeProvider) {

Also available in: Unified diff