refactoring ui as single angularJs application
This commit is contained in:
parent
2ed71532db
commit
5b681ed9e8
|
@ -0,0 +1,30 @@
|
|||
package eu.dnetlib.is;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import eu.dnetlib.data.is.resource.model.ResourceType;
|
||||
import eu.dnetlib.data.is.resource.repository.ResourceTypeRepository;
|
||||
|
||||
@RestController
|
||||
public class MainAjaxController {
|
||||
|
||||
@Autowired
|
||||
private ResourceTypeRepository resourceTypeRepository;
|
||||
|
||||
@GetMapping("/ajax/resourceTypes")
|
||||
public Iterable<ResourceType> resourceTypes() {
|
||||
return resourceTypeRepository.findAll();
|
||||
}
|
||||
|
||||
@GetMapping("/ajax/resourceTypes/{id}")
|
||||
public ResourceType resourceTypes(@PathVariable final String id) {
|
||||
return resourceTypeRepository
|
||||
.findById(id)
|
||||
.orElse(new ResourceType("not_present", "???", MediaType.TEXT_PLAIN_VALUE, 0));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package eu.dnetlib.is;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import eu.dnetlib.data.is.context.repository.ContextRepository;
|
||||
import eu.dnetlib.data.is.resource.model.ResourceType;
|
||||
import eu.dnetlib.data.is.resource.repository.ResourceTypeRepository;
|
||||
import eu.dnetlib.data.is.vocabulary.repository.VocabularyRepository;
|
||||
import eu.dnetlib.data.is.vocabulary.repository.VocabularyTermRepository;
|
||||
import eu.dnetlib.is.info.KeyValue;
|
||||
import eu.dnetlib.is.wfs.WfHistoryAjaxController;
|
||||
import eu.dnetlib.openaire.dsm.utils.DsmBrowsableFields;
|
||||
|
||||
@Controller
|
||||
public class MainController {
|
||||
|
||||
@Autowired
|
||||
private ContextRepository contextRepository;
|
||||
|
||||
@Autowired
|
||||
private VocabularyRepository vocabularyRepository;
|
||||
|
||||
@Autowired
|
||||
private VocabularyTermRepository vocabularyTermRepository;
|
||||
|
||||
@Autowired
|
||||
private ResourceTypeRepository resourceTypeRepository;
|
||||
|
||||
@GetMapping("/main")
|
||||
public void mainPage() {}
|
||||
|
||||
@GetMapping("/dsm")
|
||||
public void searchDsApi(final ModelMap map) {
|
||||
map.addAttribute("pageSize", 100);
|
||||
map.addAttribute("browsableFields", Arrays.stream(DsmBrowsableFields.values())
|
||||
.map(f -> new KeyValue(f.name(), f.desc))
|
||||
.collect(Collectors.toList()));
|
||||
map.addAttribute("protocols", vocabularyTermRepository.findTermsByVocabulary("dnet:protocols"));
|
||||
map.addAttribute("compatibilityLevels", vocabularyTermRepository.findTermsByVocabulary("dnet:compatibilityLevel"));
|
||||
map.addAttribute("contentDescTypes", vocabularyTermRepository.findTermsByVocabulary("dnet:content_description_typologies"));
|
||||
}
|
||||
|
||||
@GetMapping("/resources")
|
||||
public String listResources(@RequestParam final String type, final ModelMap map) {
|
||||
|
||||
if (type.equalsIgnoreCase("vocabulary")) {
|
||||
return "redirect:vocs";
|
||||
} else if (type.equalsIgnoreCase("context")) {
|
||||
return "redirect:contexts";
|
||||
} else if (type.equalsIgnoreCase("protocol")) {
|
||||
return "redirect:protocols";
|
||||
} else {
|
||||
final Optional<ResourceType> restype = resourceTypeRepository.findById(type);
|
||||
if (restype.isPresent() && restype.get().isSimple()) {
|
||||
map.addAttribute("type", restype.get());
|
||||
} else {
|
||||
map.addAttribute("type", new ResourceType("not_present", "???", MediaType.TEXT_PLAIN_VALUE, 0));
|
||||
}
|
||||
return "simpleResources";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/vocs")
|
||||
public void vocabularies() {}
|
||||
|
||||
@GetMapping("/contexts")
|
||||
public void contexts() {}
|
||||
|
||||
@GetMapping("/protocols")
|
||||
public void protocols() {}
|
||||
|
||||
@GetMapping("/wf_history")
|
||||
public void wfHistory(final ModelMap map,
|
||||
@RequestParam(required = false, defaultValue = "-1") final Long from,
|
||||
@RequestParam(required = false, defaultValue = "-1") final Long to) {
|
||||
map.put("maxNumberOfRecentWfs", WfHistoryAjaxController.MAX_NUMBER_OF_RECENT_WFS);
|
||||
map.put("fromDate", from);
|
||||
map.put("toDate", to);
|
||||
}
|
||||
|
||||
@GetMapping("/info")
|
||||
public void wfHistory() throws Exception {}
|
||||
|
||||
@ModelAttribute("resTypes")
|
||||
public Iterable<ResourceType> resourceTypes() {
|
||||
return resourceTypeRepository.findAll();
|
||||
}
|
||||
}
|
|
@ -22,12 +22,16 @@ public class WfHistoryAjaxController {
|
|||
@Autowired
|
||||
private WfProcessExecutionRepository wfProcessExecutionRepository;
|
||||
|
||||
@Deprecated
|
||||
public static final int MAX_NUMBER_OF_RECENT_WFS = 100;
|
||||
|
||||
@GetMapping("/")
|
||||
public List<WfProcessExecution> history(@RequestParam(required = false) final Long from, @RequestParam(required = false) final Long to) {
|
||||
public List<WfProcessExecution> history(
|
||||
@RequestParam(required = true) final int total,
|
||||
@RequestParam(required = false) final Long from,
|
||||
@RequestParam(required = false) final Long to) {
|
||||
if (from == null && to == null) {
|
||||
return wfProcessExecutionRepository.findAll(PageRequest.of(0, MAX_NUMBER_OF_RECENT_WFS, Sort.by("endDate").descending())).toList();
|
||||
return wfProcessExecutionRepository.findAll(PageRequest.of(0, total, Sort.by("endDate").descending())).toList();
|
||||
} else if (from == null) {
|
||||
return wfProcessExecutionRepository.findByEndDateBetweenOrderByEndDateDesc(new Date(0), new Date(to));
|
||||
} else if (to == null) {
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package eu.dnetlib.openaire.dsm;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
@ -13,10 +17,12 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import eu.dnetlib.common.controller.AbstractDnetController;
|
||||
import eu.dnetlib.data.is.vocabulary.repository.VocabularyTermRepository;
|
||||
import eu.dnetlib.data.openaire.dsm.model.Api;
|
||||
import eu.dnetlib.data.openaire.dsm.model.BrowseTerm;
|
||||
import eu.dnetlib.data.openaire.dsm.model.view.SimpleDsWithApis;
|
||||
import eu.dnetlib.is.errors.DsmException;
|
||||
import eu.dnetlib.is.info.KeyValue;
|
||||
import eu.dnetlib.openaire.dsm.utils.DsmBrowsableFields;
|
||||
|
||||
@RestController
|
||||
|
@ -26,6 +32,25 @@ public class DsmAjaxController extends AbstractDnetController {
|
|||
@Autowired
|
||||
private DsmService dsmService;
|
||||
|
||||
@Autowired
|
||||
private VocabularyTermRepository vocabularyTermRepository;
|
||||
|
||||
@GetMapping("/browsableFields")
|
||||
public List<KeyValue> browsableFields() {
|
||||
return Arrays.stream(DsmBrowsableFields.values())
|
||||
.map(f -> new KeyValue(f.name(), f.desc))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@GetMapping("/validTerms")
|
||||
public Map<String, Iterable<String>> validTerms() {
|
||||
final Map<String, Iterable<String>> map = new LinkedHashMap<>();
|
||||
map.put("protocols", vocabularyTermRepository.findTermsByVocabulary("dnet:protocols"));
|
||||
map.put("compatibilityLevels", vocabularyTermRepository.findTermsByVocabulary("dnet:compatibilityLevel"));
|
||||
map.put("contentDescTypes", vocabularyTermRepository.findTermsByVocabulary("dnet:content_description_typologies"));
|
||||
return map;
|
||||
}
|
||||
|
||||
@GetMapping("/browse/{field}")
|
||||
public List<BrowseTerm> browse(@PathVariable final String field) {
|
||||
return dsmService.browseTerm(DsmBrowsableFields.valueOf(field));
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Context Editor</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
@ -6,7 +8,7 @@
|
|||
data-target="#showParametersModal" ng-click="loadContextParameters()">[show]</a>
|
||||
</p>
|
||||
<p>
|
||||
<a class="btn btn-sm btn-info" href="#!/list">Return to contexts list</a> <a class="btn btn-sm btn-success" href="/api/contexts/{{ctxId}}" target="_blank">Download</a>
|
||||
<a class="btn btn-sm btn-info" href="#!/contexts">Return to contexts list</a> <a class="btn btn-sm btn-success" href="/api/contexts/{{ctxId}}" target="_blank">Download</a>
|
||||
</p>
|
||||
|
||||
<ul>
|
|
@ -1,3 +1,4 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Contexts</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
@ -26,7 +27,7 @@
|
|||
<td colspan="4" class="text-muted">no contexts</td>
|
||||
</tr>
|
||||
<tr ng-repeat="ctx in contexts|filter:ctxFilter">
|
||||
<th><a href="#!/edit/{{ctx.id}}">{{ctx.id}}</a></th>
|
||||
<th><a href="#!/context/{{ctx.id}}">{{ctx.id}}</a></th>
|
||||
<td>{{ctx.label}}</td>
|
||||
<td>{{ctx.type}}</td>
|
||||
<td align="right">
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Datasource Manager: Add API</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Datasource Manager: API</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Datasource Manager: Results</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
|
@ -5,7 +7,7 @@
|
|||
<span></span><b>Number of results:</b> {{nResults}}<br />
|
||||
<b>Page:</b> <span ng-if="nPages > 0">{{currPage + 1}} / {{nPages}}</span><span ng-if="nPages == 0">- / -</span>
|
||||
</p>
|
||||
|
||||
|
||||
<nav ng-show="nPages > 1">
|
||||
<ul class="pagination small">
|
||||
<li class="page-item" ng-class="{'disabled' : currPage <= 0}">
|
||||
|
@ -58,7 +60,7 @@
|
|||
<td>
|
||||
<div ng-repeat="a in r.apis" ng-if="a.id">
|
||||
<span class="monospaced">
|
||||
<a href="#!/api?id={{a.id}}">{{a.id}}</a>
|
||||
<a href="#!/dsm/api?id={{a.id}}">{{a.id}}</a>
|
||||
</span>
|
||||
<span class="badge badge-primary" title="protocol">{{a.protocol}}</span>
|
||||
<span class="badge badge-info" title="compliance">{{a.compliance}}</span>
|
||||
|
@ -66,7 +68,7 @@
|
|||
<span ng-if="a.aggrDate"><br/><b>Last aggregation:</b> {{a.aggrDate}} <b>(total: {{a.aggrTotal}})</b></span>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-primary btn-sm mt-2" href="#!/add/api?dsId={{r.id}}&dsName={{r.name}}">add api</a>
|
||||
<a class="btn btn-primary btn-sm mt-2" href="#!/dsm/addApi?dsId={{r.id}}&dsName={{r.name}}">add api</a>
|
||||
</td>
|
||||
</tr><tr ng-if="r.consenttermsofuse">
|
||||
<th>Consent Terms of Use</th>
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Datasource Manager: Search</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row mt-5">
|
||||
<div class="offset-md-3 col-md-6 offset-lg-4 col-lg-4">
|
|
@ -0,0 +1,41 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Container Info</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="infoFilter" placeholder="Filter..."/>
|
||||
</p>
|
||||
|
||||
<div class="card mb-3" ng-repeat="section in info" ng-show="(section.data|filter:infoFilter).length > 0">
|
||||
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{section.name}}</h5>
|
||||
|
||||
<table class="table table-striped table-sm small" style="table-layout: fixed;">
|
||||
<thead ng-if="section.name == 'Modules'">
|
||||
<tr>
|
||||
<th>Group ID</th>
|
||||
<th>Artifact ID</th>
|
||||
<th>Version</th>
|
||||
<th>POM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="r in section.data|filter:infoFilter" ng-if="section.name != 'Modules'">
|
||||
<th style="width: 25%;">{{r.k}}</th>
|
||||
<td style="overflow-x: auto;"><pre style="margin: 0;">{{r.v}}</pre></td>
|
||||
</tr>
|
||||
<tr ng-repeat="r in section.data|filter:infoFilter" ng-if="section.name == 'Modules'" ng-class="{'table-warning' : r.files.length > 1}">
|
||||
<td>{{r.group}}</td>
|
||||
<td>{{r.name}}</td>
|
||||
<td class="text-monospace"><span ng-repeat="v in r.versions">{{v}}<br /></span></td>
|
||||
<td class="text-monospace"><span ng-repeat="f in r.files">{{f}}<br /></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,34 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Harvesting Protocols</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<p><b>NOTE:</b> Use the api to register new protocols</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card mt-4" ng-repeat="prot in protocols">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{prot.id}}</h5>
|
||||
<p class="card-text" ng-if="prot.params.length == 0">No parameters</p>
|
||||
<table class="table table-sm table-striped" ng-if="prot.params.length > 0">
|
||||
<thead>
|
||||
<th style="width: 20%">Parameter</th>
|
||||
<th>Description</th>
|
||||
<th style="width: 15%" class="text-center">Type</th>
|
||||
<th style="width: 15%" class="text-center">Required</th>
|
||||
<th style="width: 15%" class="text-center">Has Sel Function</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="p in prot.params">
|
||||
<th>{{p.name}}</th>
|
||||
<td>{{p.label}}</td>
|
||||
<td class="text-center">{{p.type}}</td>
|
||||
<td class="text-center"><i class="fa fa-check" ng-if="!p.optional"></i></td>
|
||||
<td class="text-center"><i class="fa fa-check" ng-if="p.hasSelFunction"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,124 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">{{typeDesc.name}}</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p>
|
||||
<button class="btn btn-sm btn-primary" data-toggle="modal" data-target="#newResourceModal" ng-click="prepareNewResource()">create a new resource</button>
|
||||
</p>
|
||||
<p ng-show="resources.length > 0">
|
||||
<input type="text" class="form-control form-control-sm" ng-model="resFilter" placeholder="Filter..." />
|
||||
</p>
|
||||
<p>
|
||||
<span class="text-muted"><b>Number of resources:</b> {{(resources | filter:resFilter).length}}</span>
|
||||
</p>
|
||||
|
||||
<div class="card mb-4" ng-repeat="r in resources|filter:resFilter">
|
||||
<div class="card-body small">
|
||||
<span class="badge badge-primary float-right">{{typeDesc.contentType}}</span>
|
||||
<h5 class="card-title" title="{{r.id}}">{{r.name}}</h5>
|
||||
<p class="card-text">{{r.description}}</p>
|
||||
<p class="text-muted small">
|
||||
<b>Id:</b> {{r.id}}<br /> <b>Creation date:</b> {{r.creationDate}}<br /> <b>Modification date:</b> {{r.modificationDate}}
|
||||
</p>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editMetadataModal" ng-click="prepareEditMetadata(r)">edit metadata</button>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editContentModal" ng-click="prepareEditContent(r)">edit content</button>
|
||||
<a href="./api/resources/{{r.id}}/content" class="btn btn-sm btn-success" target="_blank">raw content</a>
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="deleteResource(r)">delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="editMetadataModal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Edit metadata</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<form>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>ID</label> <input type="text" readonly class="form-control-plaintext" ng-model="tmpRes.id" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Type</label> <input type="text" readonly class="form-control-plaintext" ng-model="tmpRes.type" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Name</label> <input type="text" class="form-control" ng-model="tmpRes.name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea class="form-control" ng-model="tmpRes.description" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" data-dismiss="modal" ng-click="saveMetadata(tmpRes.id, tmpRes)" ng-disabled="!tmpRes.id || !tmpRes.name">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="newResourceModal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">New resource ({{type}})</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<form>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Name</label> <input type="text" class="form-control" ng-model="tmpRes.name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea class="form-control" ng-model="tmpRes.description"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Content ({{typeDesc.contentType}})</label>
|
||||
<textarea class="form-control" ng-model="tmpRes.content" rows="25"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" ng-click="createNewResource(tmpRes)" ng-disabled="!tmpRes.name || !tmpRes.content">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="editContentModal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Edit content</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<form>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>{{typeDesc.contentType}}</label>
|
||||
<textarea class="form-control" ng-model="tmpContent" rows="25"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" ng-click="saveContent(tmpRes.id, tmpContent)" ng-disabled="!tmpContent">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Vocabulary Editor</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
@ -7,7 +9,7 @@
|
|||
<b>Description: </b>{{vocInfo.description}}
|
||||
</p>
|
||||
<p>
|
||||
<a class="btn btn-sm btn-info" href="#!/list">Return to vocabulary list</a>
|
||||
<a class="btn btn-sm btn-info" href="#!/vocs">Return to vocabulary list</a>
|
||||
<button class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editVocabularyTermModal" ng-click="prepareNewTerm()">create a new term</button>
|
||||
<a class="btn btn-sm btn-success" href="/api/vocs/{{vocId}}/terms" target="_blank">Download</a>
|
||||
</p>
|
|
@ -1,3 +1,5 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Vocabularies</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
@ -24,7 +26,7 @@
|
|||
<td colspan="4" class="text-muted">no vocabularies</td>
|
||||
</tr>
|
||||
<tr ng-repeat="v in vocabularies|filter:vocFilter">
|
||||
<th><a href="#!/edit?id={{v.id}}">{{v.id}}</a></th>
|
||||
<th><a href="#!/vocabularyEditor?id={{v.id}}">{{v.id}}</a></th>
|
||||
<td>{{v.name}}</td>
|
||||
<td>{{v.description}}</td>
|
||||
<td align="right">
|
|
@ -0,0 +1,132 @@
|
|||
<h1 class="ml-3 mb-4 mt-3">Workflow History</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
<p ng-show="workflows.length > 0">
|
||||
<input type="text" class="form-control form-control-sm" ng-model="wfFilter" placeholder="Filter..."/>
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
<span ng-show="fromDate < 0 && toDate < 0"><b>Recent workflows</b> (max {{maxNumberOfRecentWfs}})</span>
|
||||
<span ng-show="fromDate >= 0 && toDate >= 0"><b>Workflows from </b>{{fromDate | date:"yyyy-MM-dd HH:mm:ss"}} <b>to</b> {{toDate | date:"yyyy-MM-dd HH:mm:ss"}}</span>
|
||||
<span ng-show="fromDate >= 0 && toDate < 0"><b>Workflows from </b>{{fromDate | date:"yyyy-MM-dd HH:mm:ss"}} <b>to</b> <i>undefined</i></span>
|
||||
<span ng-show="fromDate < 0 && toDate >= 0"><b>Workflows from </b><i>undefined</i> <b>to</b> {{toDate | date:"yyyy-MM-dd HH:mm:ss"}}</span>
|
||||
<br />
|
||||
<span><b>Count :</b> {{(workflows | filter:wfFilter).length}}</span>
|
||||
</p>
|
||||
<table class="table table-sm table-striped small">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'processId'; sortReverse = !sortReverse">
|
||||
Process Id
|
||||
<i ng-show="sortField == 'processId' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'processId' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 20%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'name'; sortReverse = !sortReverse">
|
||||
Workflow Name
|
||||
<i ng-show="sortField == 'name' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'name' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'family'; sortReverse = !sortReverse">
|
||||
Workflow Family
|
||||
<i ng-show="sortField == 'family' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'family' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 30%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'dsName'; sortReverse = !sortReverse">
|
||||
Datasource
|
||||
<i ng-show="sortField == 'dsName' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'dsName' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'status'; sortReverse = !sortReverse">
|
||||
Status
|
||||
<i ng-show="sortField == 'status' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'status' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'startDate'; sortReverse = !sortReverse">
|
||||
Start Date
|
||||
<i ng-show="sortField == 'startDate' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'startDate' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'endDate'; sortReverse = !sortReverse">
|
||||
End Date
|
||||
<i ng-show="sortField == 'endDate' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'endDate' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-show="(workflows|filter:wfFilter).length == 0">
|
||||
<td colspan="7" class="text-muted">no workflows</td>
|
||||
</tr>
|
||||
<tr ng-repeat="wf in workflows | orderBy:sortField:sortReverse | filter:wfFilter">
|
||||
<th><a href="javascript:void(0)" data-toggle="modal" data-target="#showWfDetailsModal" ng-click="setCurrentWf(wf)">{{wf.processId}}</a></th>
|
||||
<td>{{wf.name}}</td>
|
||||
<td>{{wf.family}}</td>
|
||||
<td>{{wf.dsName}}</td>
|
||||
<td><span class="badge" ng-class="{
|
||||
'badge-success' : (wf.status == 'success'),
|
||||
'badge-danger' : (wf.status == 'failure'),
|
||||
'badge-primary' : (wf.status != 'success') && (wf.status != 'failure')
|
||||
}">{{wf.status}}</span></td>
|
||||
<td>{{wf.startDate}}</td>
|
||||
<td>{{wf.endDate}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="showWfDetailsModal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Details</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
<b>Started at: </b>{{currentWf.startDate}}<br />
|
||||
<b>Finished at: </b>{{currentWf.endDate}}<br />
|
||||
<b>Duration: </b>{{currentWf.duration}}<br />
|
||||
</p>
|
||||
|
||||
<input type="text" class="form-control form-control-sm" ng-model="detailsFilter" placeholder="Filter..."/>
|
||||
|
||||
<table class="table table-sm table-striped small mt-2" style="table-layout: fixed;">
|
||||
<tr ng-repeat="p in currentWf.arrayDetails | filter:detailsFilter">
|
||||
<th style="width: 30%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"><a href="javascript:void(0)" ng-click="setCurrentDetailParam(p.k,p.v)">{{p.k}}</a></th>
|
||||
<td style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{p.v}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="card card-body bg-light" ng-show="currDetailsKey">
|
||||
<b>{{currDetailsKey}}</b><br />
|
||||
<pre>{{currDetailsValue}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1,9 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html ng-app="isApp">
|
||||
<head>
|
||||
<title>OpenAIRE IS Tools</title>
|
||||
<meta http-equiv="refresh" content="0; URL='./main'" />
|
||||
<title>OpenAIRE Tools</title>
|
||||
<link rel="stylesheet" href="common/css/bootstrap.cerulean.min.css" />
|
||||
<link rel="stylesheet" href="common/css/fontawesome-all.min.css" />
|
||||
|
||||
<style type="text/css">
|
||||
td,th {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.overlaydiv {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 10000;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.grayRectangle {
|
||||
position: absolute;
|
||||
background-color: black;
|
||||
opacity:0.6;
|
||||
top: 30%;
|
||||
left: 40%;
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
z-index: 100;
|
||||
border-radius: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="spinnerdiv" class="overlaydiv">
|
||||
<span class="grayRectangle"><!--The spinner is added on loading here--></span>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light" ng-controller="isMenuController">
|
||||
<a class="navbar-brand" href="./">D-Net</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="./">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Datasources</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#!/dsm/search">Search</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Configuration</a>
|
||||
<div class="dropdown-menu">
|
||||
<h6 class="dropdown-header">Simple resources</h6>
|
||||
<a ng-repeat="t in resTypes" ng-if="t.simple"
|
||||
class="dropdown-item"
|
||||
href="#!/resources/{{t.id}}">
|
||||
<span>{{t.name}}</span>
|
||||
<span class="badge badge-primary">{{t.count}}</span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<h6 class="dropdown-header">Advanced resources</h6>
|
||||
<a ng-repeat="t in resTypes" ng-if="!t.simple"
|
||||
class="dropdown-item"
|
||||
href="#!/resources/{{t.id}}">
|
||||
<span>{{t.name}}</span>
|
||||
<span class="badge badge-primary">{{t.count}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Logs</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#!/wf_history/100">Workflow history</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Info</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#!/info">Container Info</a>
|
||||
<a class="dropdown-item" href="./docs" target="_blank">API documentation</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
</body>
|
||||
|
||||
<script src="common/js/jquery.min.js"></script>
|
||||
<script src="common/js/popper.min.js"></script>
|
||||
<script src="common/js/bootstrap.min.js"></script>
|
||||
<script src="common/js/angular.min.js"></script>
|
||||
<script src="common/js/angular-route.min.js"></script>
|
||||
<script src="common/js/spin.js"></script>
|
||||
<script src="js/is_utils.js"></script>
|
||||
<script src="js/is_main.js"></script>
|
||||
|
||||
</html>
|
|
@ -1,107 +0,0 @@
|
|||
var app = angular.module('contextsApp', ['ngRoute']);
|
||||
|
||||
app.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/list', { templateUrl: 'contexts/list.html', controller: 'ctxListController' })
|
||||
.when('/edit/:id', { templateUrl: 'contexts/editor.html', controller: 'ctxEditorController' })
|
||||
.otherwise({ redirectTo: '/list' });
|
||||
}
|
||||
]);
|
||||
|
||||
app.controller('ctxListController', function($scope, $http) {
|
||||
$scope.contexts = [];
|
||||
$scope.tmpCtx = {};
|
||||
$scope.mode = '';
|
||||
|
||||
call_http_get($http, './ajax/contexts/?' + $.now(), function(res) {
|
||||
$scope.contexts = res.data;
|
||||
});
|
||||
|
||||
$scope.prepareNewCtx = function() {
|
||||
$scope.mode = 'new';
|
||||
$scope.tmpCtx = {
|
||||
'id' : '',
|
||||
'label' : '',
|
||||
'type' : '',
|
||||
'parameters' : []
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditCtx = function(ctx) {
|
||||
$scope.mode = 'edit';
|
||||
$scope.tmpCtx = angular.copy(ctx);
|
||||
}
|
||||
|
||||
$scope.saveContext = function(ctx) {
|
||||
if ($scope.mode == 'new') {
|
||||
var found = false;
|
||||
|
||||
angular.forEach($scope.contexts, function(v) {
|
||||
if (ctx.id == ctx.id) { found = true; };
|
||||
});
|
||||
|
||||
if (found) {
|
||||
alert("Insertion failed: context already exists !");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
json_http_post($http,'./ajax/contexts/?' + $.now(), ctx, function(res) {
|
||||
$scope.contexts = res.data;
|
||||
alert("Context saved");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteContext = function(id) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
call_http_delete($http, './ajax/contexts/' + encodeURIComponent(id) + '?' + $.now(), function(res) {
|
||||
$scope.contexts = res.data;
|
||||
alert("Context deleted");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
app.controller('ctxEditorController', function($scope, $http, $location, $routeParams) {
|
||||
$scope.ctxId = $routeParams.id;
|
||||
$scope.ctxInfo = {};
|
||||
$scope.categories = [];
|
||||
$scope.parameters = [];
|
||||
|
||||
var url = './ajax/contexts/' + encodeURIComponent($scope.ctxId);
|
||||
|
||||
call_http_get($http, url + '?' + $.now(), function(res) {
|
||||
$scope.ctxInfo = res.data;
|
||||
|
||||
call_http_get($http, url + '/categories?' + $.now(), function(res) {
|
||||
$scope.categories = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.loadContextParameters = function() {
|
||||
$scope.parameters = [];
|
||||
call_http_get($http, './ajax/contexts/' + encodeURIComponent($scope.ctxId) + '?' + $.now(), function(res) {
|
||||
$scope.parameters = res.data.parameters;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.populateNode = function(level, node) {
|
||||
$scope.url = './ajax/contexts/'
|
||||
+ encodeURIComponent(level)
|
||||
+ '/'
|
||||
+ encodeURIComponent(node.id)
|
||||
+ '/concepts';
|
||||
|
||||
node.populated = true;
|
||||
|
||||
call_http_get($http, $scope.url + '?' + $.now(), function(res) {
|
||||
node.concepts = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.initShowParameters = function(params) {
|
||||
$scope.parameters = params;
|
||||
}
|
||||
|
||||
});
|
|
@ -0,0 +1,582 @@
|
|||
var app = angular.module('isApp', ['ngRoute']);
|
||||
|
||||
app.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/info', { templateUrl: './html/info.html', controller: 'infoController' })
|
||||
.when('/wf_history/:total', { templateUrl: './html/wf_history.html', controller: 'wfHistoryController' })
|
||||
.when('/protocols', { templateUrl: './html/protocols.html', controller: 'protocolsController' })
|
||||
.when('/resources/:type', { templateUrl: './html/resources.html', controller: 'resourcesController' })
|
||||
.when('/contexts', { templateUrl: './html/contexts.html', controller: 'ctxListController' })
|
||||
.when('/context/:id', { templateUrl: './html/context_viewer.html', controller: 'ctxViewerController' })
|
||||
.when('/vocs', { templateUrl: './html/vocs.html', controller: 'vocListController' })
|
||||
.when('/vocabularyEditor', { templateUrl: './html/voc_editor.html', controller: 'vocEditorController' })
|
||||
.when('/dsm/search', { templateUrl: './html/dsm_search.html', controller: 'dsmSearchController' })
|
||||
.when('/dsm/results/:page/:size', { templateUrl: './html/dsm_results.html', controller: 'dsmResultsController' })
|
||||
.when('/dsm/results/:field/:page/:size', { templateUrl: './html/dsm_results.html', controller: 'dsmResultsController' })
|
||||
.when('/dsm/addApi', { templateUrl: './html/dsm_add_api.html', controller: 'dsmAddApiController' })
|
||||
.when('/dsm/api', { templateUrl: './html/dsm_api.html', controller: 'dsmApiController' })
|
||||
.otherwise({ redirectTo: '/info' });
|
||||
}
|
||||
]);
|
||||
|
||||
app.controller('isMenuController', function($scope, $http) {
|
||||
$scope.resTypes = [];
|
||||
|
||||
call_http_get($http, './ajax/resourceTypes' , function(res) {
|
||||
$scope.resTypes = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('infoController', function($scope, $http) {
|
||||
$scope.info = [];
|
||||
|
||||
call_http_get($http, './ajax/info/?' + $.now(), function(res) {
|
||||
angular.forEach(res.data, function(section) {
|
||||
if (section.name != 'Modules') {
|
||||
angular.forEach(section.data, function(r) {
|
||||
if (r.k.toLowerCase().endsWith('path') || r.k.toLowerCase().endsWith('.dirs')) {
|
||||
r.v = r.v.replaceAll(':', ':\n');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$scope.info = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('wfHistoryController', function($scope, $http, $routeParams) {
|
||||
$scope.fromDate = $routeParams.from;
|
||||
$scope.toDate = $routeParams.to;
|
||||
$scope.maxNumberOfRecentWfs = $routeParams.total;
|
||||
|
||||
$scope.workflows = [];
|
||||
$scope.currentWf = {};
|
||||
$scope.currDetailsKey = '';
|
||||
$scope.currDetailsValue = '';
|
||||
$scope.sortField = 'processId';
|
||||
$scope.sortReverse = false;
|
||||
|
||||
$scope.reload = function() {
|
||||
var url = './ajax/wfs/?' + $.now();
|
||||
|
||||
url += "&total=" + $scope.maxNumberOfRecentWfs;
|
||||
|
||||
if ($scope.fromDate > 0) { url += "&from=" + $scope.fromDate; }
|
||||
if ($scope.toDate > 0) { url += "&to=" + $scope.toDate; }
|
||||
|
||||
call_http_get($http, url, function(res) {
|
||||
$scope.workflows = res.data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setCurrentWf = function(wf) {
|
||||
$scope.currentWf = angular.copy(wf);
|
||||
$scope.currDetailsKey = '';
|
||||
$scope.currDetailsValue = '';
|
||||
$scope.currentWf.arrayDetails = [];
|
||||
$scope.currentWf.duration = $scope.calculateDateDiff(parseInt(wf.details['system:startDate']), parseInt(wf.details['system:endDate']));
|
||||
|
||||
angular.forEach(wf.details, function(v,k) {
|
||||
$scope.currentWf.arrayDetails.push({'k':k, 'v':v});
|
||||
});
|
||||
}
|
||||
|
||||
$scope.setCurrentDetailParam = function(k, v) {
|
||||
$scope.currDetailsKey = k;
|
||||
$scope.currDetailsValue = v;
|
||||
}
|
||||
|
||||
|
||||
$scope.calculateDateDiff = function(start, end) {
|
||||
if (start <= 0 || end <= 0) {
|
||||
return '-';
|
||||
}
|
||||
var seconds = 0;
|
||||
var minutes = 0;
|
||||
var hours = 0;
|
||||
var days = 0;
|
||||
|
||||
if (end > start) {
|
||||
seconds = Math.round((end - start) / 1000);
|
||||
if (seconds > 60) {
|
||||
minutes = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
if (minutes > 60) {
|
||||
hours = Math.floor(minutes / 60);
|
||||
minutes = minutes % 60;
|
||||
if (hours > 24) {
|
||||
days = Math.floor(hours / 24);
|
||||
hours = hours % 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var res = '';
|
||||
if (days > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += days + " day(s)"
|
||||
}
|
||||
if (hours > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += hours + " hour(s)"
|
||||
}
|
||||
if (minutes > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += minutes + " minute(s)"
|
||||
}
|
||||
if (seconds > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += seconds + " second(s)"
|
||||
}
|
||||
if (!res) {
|
||||
res = '0 seconds';
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
$scope.reload();
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('resourcesController', function($scope, $http, $routeParams, $location) {
|
||||
$scope.resources = [];
|
||||
$scope.tmpRes = {};
|
||||
$scope.tmpContent = "loading...";
|
||||
$scope.type = $routeParams.type;
|
||||
$scope.typeDesc = {};
|
||||
|
||||
$scope.reload = function() {
|
||||
call_http_get($http, './ajax/resourceTypes/' + encodeURIComponent($scope.type) + '?' + $.now(), function(res) {
|
||||
$scope.typeDesc = res.data;
|
||||
});
|
||||
|
||||
call_http_get($http, './ajax/resources/' + encodeURIComponent($scope.type) + '?' + $.now(), function(res) {
|
||||
$scope.resources = res.data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.prepareNewResource = function() {
|
||||
$scope.tmpRes = {
|
||||
'name' : '',
|
||||
'description' : '',
|
||||
'content' : ''
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditMetadata = function(r) {
|
||||
$scope.tmpRes = angular.copy(r);
|
||||
}
|
||||
|
||||
$scope.prepareEditContent = function(r) {
|
||||
$scope.tmpRes = angular.copy(r);
|
||||
$scope.tmpContent = "loading...";
|
||||
call_http_get($http, './ajax/resources/' + encodeURIComponent(r.id) + '/content?' + $.now(), function(res) {
|
||||
if (res.data instanceof Object) {
|
||||
$scope.tmpContent = JSON.stringify(res.data, null, "\t");
|
||||
} else {
|
||||
$scope.tmpContent = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.createNewResource = function(r) {
|
||||
params_http_post($http, './ajax/resources/?' + $.now(), $.param({
|
||||
'name' : r.name,
|
||||
'type' : $scope.type,
|
||||
'description' : r.description,
|
||||
'content' : r.content
|
||||
}), function(res) {
|
||||
alert("Resource saved");
|
||||
$('#newResourceModal').modal('hide');
|
||||
$scope.reload();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.saveMetadata = function(id, md) {
|
||||
json_http_post($http, './ajax/resources/' + encodeURIComponent(id) + '/metadata?' + $.now(), md, function(res) {
|
||||
alert("Resource saved");
|
||||
$scope.reload();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.saveContent = function(id, content) {
|
||||
params_http_post($http, './ajax/resources/' + encodeURIComponent(id) + '/content?' + $.now(), $.param({
|
||||
'content' : content
|
||||
}), function(res) {
|
||||
alert("Resource saved");
|
||||
$('#editContentModal').modal('hide');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteResource = function(r) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
call_http_delete($http, './ajax/resources/' + encodeURIComponent(r.id) + '?' + $.now(), function(res) {
|
||||
alert("Resource deleted");
|
||||
$scope.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if ($scope.type == 'context') { $location.url("/contexts"); }
|
||||
else if ($scope.type == 'vocabulary') { $location.url("/vocs"); }
|
||||
else if ($scope.type == 'protocol') { $location.url("/protocols"); }
|
||||
else { $scope.reload(); }
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('protocolsController', function($scope, $http) {
|
||||
$scope.protocols = [];
|
||||
|
||||
call_http_get($http, './ajax/protocols/?' + $.now(), function(res) {
|
||||
$scope.protocols = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('ctxListController', function($scope, $http) {
|
||||
$scope.contexts = [];
|
||||
$scope.tmpCtx = {};
|
||||
$scope.mode = '';
|
||||
|
||||
call_http_get($http, './ajax/contexts/?' + $.now(), function(res) {
|
||||
$scope.contexts = res.data;
|
||||
});
|
||||
|
||||
$scope.prepareNewCtx = function() {
|
||||
$scope.mode = 'new';
|
||||
$scope.tmpCtx = {
|
||||
'id' : '',
|
||||
'label' : '',
|
||||
'type' : '',
|
||||
'parameters' : []
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditCtx = function(ctx) {
|
||||
$scope.mode = 'edit';
|
||||
$scope.tmpCtx = angular.copy(ctx);
|
||||
}
|
||||
|
||||
$scope.saveContext = function(ctx) {
|
||||
if ($scope.mode == 'new') {
|
||||
var found = false;
|
||||
|
||||
angular.forEach($scope.contexts, function(v) {
|
||||
if (ctx.id == ctx.id) { found = true; };
|
||||
});
|
||||
|
||||
if (found) {
|
||||
alert("Insertion failed: context already exists !");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
json_http_post($http,'./ajax/contexts/?' + $.now(), ctx, function(res) {
|
||||
$scope.contexts = res.data;
|
||||
alert("Context saved");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteContext = function(id) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
call_http_delete($http, './ajax/contexts/' + encodeURIComponent(id) + '?' + $.now(), function(res) {
|
||||
$scope.contexts = res.data;
|
||||
alert("Context deleted");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('ctxViewerController', function($scope, $http, $routeParams) {
|
||||
$scope.ctxId = $routeParams.id;
|
||||
$scope.ctxInfo = {};
|
||||
$scope.categories = [];
|
||||
$scope.parameters = [];
|
||||
|
||||
var url = './ajax/contexts/' + encodeURIComponent($scope.ctxId);
|
||||
|
||||
call_http_get($http, url + '?' + $.now(), function(res) {
|
||||
$scope.ctxInfo = res.data;
|
||||
|
||||
call_http_get($http, url + '/categories?' + $.now(), function(res) {
|
||||
$scope.categories = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.loadContextParameters = function() {
|
||||
$scope.parameters = [];
|
||||
call_http_get($http, './ajax/contexts/' + encodeURIComponent($scope.ctxId) + '?' + $.now(), function(res) {
|
||||
$scope.parameters = res.data.parameters;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.populateNode = function(level, node) {
|
||||
$scope.url = './ajax/contexts/'
|
||||
+ encodeURIComponent(level)
|
||||
+ '/'
|
||||
+ encodeURIComponent(node.id)
|
||||
+ '/concepts';
|
||||
|
||||
node.populated = true;
|
||||
|
||||
call_http_get($http, $scope.url + '?' + $.now(), function(res) {
|
||||
node.concepts = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.initShowParameters = function(params) {
|
||||
$scope.parameters = params;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('vocListController', function($scope, $http) {
|
||||
$scope.vocabularies = [];
|
||||
$scope.tmpVoc = {};
|
||||
$scope.mode = '';
|
||||
|
||||
call_http_get($http, './ajax/vocs/?' + $.now(), function(res) {
|
||||
$scope.vocabularies = res.data;
|
||||
});
|
||||
|
||||
$scope.prepareNewVoc = function() {
|
||||
$scope.mode = 'new';
|
||||
$scope.tmpVoc = {
|
||||
'id' : '',
|
||||
'name' : '',
|
||||
'description' : ''
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditVoc = function(voc) {
|
||||
$scope.mode = 'edit';
|
||||
$scope.tmpVoc = angular.copy(voc);
|
||||
}
|
||||
|
||||
$scope.saveVocabulary = function(voc) {
|
||||
if ($scope.mode == 'new') {
|
||||
var found = false;
|
||||
|
||||
angular.forEach($scope.vocabularies, function(v) {
|
||||
if (voc.id == v.id) { found = true; };
|
||||
});
|
||||
|
||||
if (found) {
|
||||
alert("Insertion failed: vocabulary already exists !");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
json_http_post($http, './ajax/vocs/?' + $.now(), voc, function(res) {
|
||||
$scope.vocabularies = res.data;
|
||||
alert("Vocabulary saved");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteVocabulary = function(id) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
call_http_delete($http, './ajax/vocs/' + encodeURIComponent(id) + '?' + $.now(), function(res) {
|
||||
$scope.vocabularies = res.data;
|
||||
alert("Vocabulary deleted");
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('vocEditorController', function($scope, $http, $routeParams) {
|
||||
$scope.terms = [];
|
||||
$scope.vocId = $routeParams.id;
|
||||
$scope.vocInfo = {};
|
||||
$scope.editTermCode = '';
|
||||
$scope.tmpTerm = {};
|
||||
$scope.mode = '';
|
||||
$scope.currTerm = [];
|
||||
|
||||
$scope.baseUrl = './ajax/vocs/' + encodeURIComponent($scope.vocId);
|
||||
|
||||
call_http_get($http, $scope.baseUrl + '?' + $.now(), function(res) {
|
||||
$scope.vocInfo = res.data;
|
||||
|
||||
call_http_get($http, $scope.baseUrl + '/terms?' + $.now(), function(res) {
|
||||
$scope.terms = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.setCurrTerm = function(term) {
|
||||
$scope.currTerm = angular.copy(term);
|
||||
}
|
||||
|
||||
$scope.prepareNewTerm = function() {
|
||||
$scope.mode = 'new';
|
||||
$scope.editTermCode = '';
|
||||
$scope.tmpTerm = {
|
||||
'code' : '',
|
||||
'name' : '',
|
||||
'encoding' : 'OPENAIRE',
|
||||
'synonyms' : []
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditTerm = function(term) {
|
||||
$scope.mode = 'edit';
|
||||
$scope.editTermCode = term.code;
|
||||
$scope.tmpTerm = angular.copy(term);
|
||||
}
|
||||
|
||||
|
||||
$scope.saveTerm = function(term) {
|
||||
var url = $scope.baseUrl + '/terms?' + $.now();
|
||||
|
||||
json_http_post($http, url, term, function(res) {
|
||||
if ($scope.editTermCode != '' && $scope.editTermCode != $scope.tmpTerm.code) {
|
||||
var deleteUrl = $scope.baseUrl + '/terms/' + encodeURIComponent($scope.editTermCode) + '?' + $.now();
|
||||
call_http_delete($http, deleteUrl, function(res) {
|
||||
$scope.terms = res.data;
|
||||
alert("Term replaced");
|
||||
});
|
||||
} else {
|
||||
$scope.terms = res.data;
|
||||
alert("Term saved");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteTerm = function(code) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
var url = $scope.baseUrl + '/terms/' + encodeURIComponent(code) + '?' + $.now();
|
||||
|
||||
call_http_delete($http, url, function(res) {
|
||||
$scope.terms = res.data;
|
||||
alert("Term deleted");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('dsmSearchController', function($scope, $http, $location, $timeout) {
|
||||
$scope.browseFieldId = "";
|
||||
$scope.browseFieldName = "";
|
||||
$scope.browseData = [];
|
||||
|
||||
$scope.browsableFields = [];
|
||||
|
||||
call_http_get($http, './ajax/dsm/browsableFields' , function(res) {
|
||||
$scope.browsableFields = res.data;
|
||||
});
|
||||
|
||||
$scope.browseField = function(id, label) {
|
||||
$scope.browseFieldId = id;
|
||||
$scope.browseFieldName = name;
|
||||
$scope.browseData = [];
|
||||
|
||||
call_http_get($http, './ajax/dsm/browse/' + encodeURIComponent(id) + '?' + $.now(), function(res) {
|
||||
$scope.browseData = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.search = function(field, value) {
|
||||
var path = "/dsm/results";
|
||||
if (field) { path += '/' + encodeURIComponent(field); }
|
||||
path += '/0/100';
|
||||
|
||||
$timeout(function() {
|
||||
$location.path(path).search('value', value);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('dsmResultsController', function($scope, $http, $location, $routeParams) {
|
||||
$scope.field = $routeParams.field;
|
||||
$scope.value = $routeParams.value;
|
||||
$scope.pageSize = $routeParams.size;
|
||||
$scope.currPage = $routeParams.page;
|
||||
|
||||
$scope.nResults = 0;
|
||||
$scope.results = [];
|
||||
$scope.nPages = 0;
|
||||
|
||||
var url = './ajax/dsm/';
|
||||
if ($scope.field) { url += 'searchByField/' + encodeURIComponent($scope.field); }
|
||||
else { url += 'search' }
|
||||
url += '/' + $scope.currPage + '/' + $scope.pageSize;
|
||||
url += '?value=' + encodeURIComponent($scope.value) + '&' + $.now();
|
||||
|
||||
call_http_get($http, url, function(res) {
|
||||
$scope.results = res.data.content;
|
||||
$scope.nResults = res.data.totalElements;
|
||||
$scope.currPage = res.data.number;
|
||||
$scope.nPages = res.data.totalPages;
|
||||
});
|
||||
|
||||
$scope.gotoPage = function(page) {
|
||||
$scope.results = [];
|
||||
var path = "/dsm/results";
|
||||
if ($scope.field) { path += '/' + encodeURIComponent($scope.field); }
|
||||
path += '/' + page + '/' + $scope.pageSize;
|
||||
$location.path(path).search('value', $scope.value);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('dsmApiController', function($scope, $http, $routeParams) {
|
||||
$scope.apiId = $routeParams.id;
|
||||
$scope.api = {};
|
||||
|
||||
call_http_get($http, './ajax/dsm/api?id=' + encodeURIComponent($scope.apiId) , function(res) {
|
||||
$scope.api = res.data;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
app.controller('dsmAddApiController', function($scope, $http, $routeParams) {
|
||||
$scope.dsName = $routeParams.dsName;
|
||||
$scope.prefix = 'api_________::' + $routeParams.dsId + '::';
|
||||
$scope.api = {}
|
||||
|
||||
$scope.protocols = [];
|
||||
$scope.compatibilityLevels = [];
|
||||
$scope.contentDescTypes = [];
|
||||
|
||||
call_http_get($http, './ajax/dsm/browsableFields' , function(res) {
|
||||
$scope.protocols = res.data.protocols;
|
||||
$scope.compatibilityLevels = res.data.compatibilityLevels;
|
||||
$scope.contentDescTypes = res.data.contentDescTypes;
|
||||
});
|
||||
|
||||
$scope.save = function() {
|
||||
var record = angular.copy($scope.api);
|
||||
record.id = $scope.prefix + record.id;
|
||||
record.datasource = $routeParams.dsId;
|
||||
|
||||
json_http_post($http, './ajax/dsm/api', record, function(res) {
|
||||
$scope.api = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Spinner show/hide methods ~ Andrea Mannocci
|
||||
var spinnerOpts = {
|
||||
lines: 15,
|
||||
length: 16,
|
||||
width: 5,
|
||||
radius: 25,
|
||||
color: '#eeeeee',
|
||||
className: 'spinner',
|
||||
top: '40%'
|
||||
};
|
||||
|
||||
var spinnerTarget = document.getElementById('spinnerdiv');
|
||||
|
||||
var spinner;
|
||||
|
||||
function showSpinner() {
|
||||
spinner = new Spinner(spinnerOpts).spin(spinnerTarget);
|
||||
spinnerTarget.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
function hideSpinner() {
|
||||
spinnerTarget.style.visibility = 'hidden';
|
||||
spinner.stop();
|
||||
}
|
||||
|
||||
function call_http_get($http, url, onSuccess) {
|
||||
showSpinner();
|
||||
|
||||
$http.get(url).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
function call_http_delete($http, url, onSuccess) {
|
||||
showSpinner();
|
||||
|
||||
$http.delete(url).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
function json_http_post($http, url, obj, onSuccess) {
|
||||
showSpinner();
|
||||
$http.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
|
||||
$http.post(url, obj).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
function params_http_post($http, url, params, onSuccess) {
|
||||
showSpinner();
|
||||
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
|
||||
$http.post(url, params).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
var app = angular.module('resourcesApp', []);
|
||||
|
||||
app.controller('resourcesController', function($scope, $http) {
|
||||
$scope.resources = [];
|
||||
$scope.tmpRes = {};
|
||||
$scope.tmpContent = "loading...";
|
||||
$scope.type = typeId();
|
||||
|
||||
$scope.reload = function() {
|
||||
call_http_get($http, './ajax/resources/' + encodeURIComponent($scope.type) + '?' + $.now(), function(res) {
|
||||
$scope.resources = res.data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.prepareNewResource = function() {
|
||||
$scope.tmpRes = {
|
||||
'name' : '',
|
||||
'description' : '',
|
||||
'content' : ''
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditMetadata = function(r) {
|
||||
$scope.tmpRes = angular.copy(r);
|
||||
}
|
||||
|
||||
$scope.prepareEditContent = function(r) {
|
||||
$scope.tmpRes = angular.copy(r);
|
||||
$scope.tmpContent = "loading...";
|
||||
call_http_get($http, './ajax/resources/' + encodeURIComponent(r.id) + '/content?' + $.now(), function(res) {
|
||||
if (res.data instanceof Object) {
|
||||
$scope.tmpContent = JSON.stringify(res.data, null, "\t");
|
||||
} else {
|
||||
$scope.tmpContent = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.createNewResource = function(r) {
|
||||
params_http_post($http, './ajax/resources/?' + $.now(), $.param({
|
||||
'name' : r.name,
|
||||
'type' : $scope.type,
|
||||
'description' : r.description,
|
||||
'content' : r.content
|
||||
}), function(res) {
|
||||
alert("Resource saved");
|
||||
$('#newResourceModal').modal('hide');
|
||||
$scope.reload();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.saveMetadata = function(id, md) {
|
||||
json_http_post($http, './ajax/resources/' + encodeURIComponent(id) + '/metadata?' + $.now(), md, function(res) {
|
||||
alert("Resource saved");
|
||||
$scope.reload();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.saveContent = function(id, content) {
|
||||
params_http_post($http, './ajax/resources/' + encodeURIComponent(id) + '/content?' + $.now(), $.param({
|
||||
'content' : content
|
||||
}), function(res) {
|
||||
alert("Resource saved");
|
||||
$('#editContentModal').modal('hide');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteResource = function(r) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
call_http_delete($http, './ajax/resources/' + encodeURIComponent(r.id) + '?' + $.now(), function(res) {
|
||||
alert("Resource deleted");
|
||||
$scope.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.reload();
|
||||
});
|
|
@ -1,134 +0,0 @@
|
|||
var app = angular.module('vocabulariesApp', ['ngRoute']);
|
||||
|
||||
|
||||
app.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/list', { templateUrl: 'vocs/list.html', controller: 'vocListController' })
|
||||
.when('/edit', { templateUrl: 'vocs/editor.html', controller: 'vocEditorController' })
|
||||
.otherwise({ redirectTo: '/list' });
|
||||
}
|
||||
]);
|
||||
|
||||
app.controller('vocListController', function($scope, $http, $location) {
|
||||
$scope.vocabularies = [];
|
||||
$scope.tmpVoc = {};
|
||||
$scope.mode = '';
|
||||
|
||||
call_http_get($http, './ajax/vocs/?' + $.now(), function(res) {
|
||||
$scope.vocabularies = res.data;
|
||||
});
|
||||
|
||||
$scope.prepareNewVoc = function() {
|
||||
$scope.mode = 'new';
|
||||
$scope.tmpVoc = {
|
||||
'id' : '',
|
||||
'name' : '',
|
||||
'description' : ''
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditVoc = function(voc) {
|
||||
$scope.mode = 'edit';
|
||||
$scope.tmpVoc = angular.copy(voc);
|
||||
}
|
||||
|
||||
$scope.saveVocabulary = function(voc) {
|
||||
if ($scope.mode == 'new') {
|
||||
var found = false;
|
||||
|
||||
angular.forEach($scope.vocabularies, function(v) {
|
||||
if (voc.id == v.id) { found = true; };
|
||||
});
|
||||
|
||||
if (found) {
|
||||
alert("Insertion failed: vocabulary already exists !");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
json_http_post($http, './ajax/vocs/?' + $.now(), voc, function(res) {
|
||||
$scope.vocabularies = res.data;
|
||||
alert("Vocabulary saved");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteVocabulary = function(id) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
call_http_delete($http, './ajax/vocs/' + encodeURIComponent(id) + '?' + $.now(), function(res) {
|
||||
$scope.vocabularies = res.data;
|
||||
alert("Vocabulary deleted");
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('vocEditorController', function($scope, $http, $location, $routeParams) {
|
||||
$scope.terms = [];
|
||||
$scope.vocId = $routeParams.id;
|
||||
$scope.vocInfo = {};
|
||||
$scope.editTermCode = '';
|
||||
$scope.tmpTerm = {};
|
||||
$scope.mode = '';
|
||||
$scope.currTerm = [];
|
||||
|
||||
$scope.baseUrl = './ajax/vocs/' + encodeURIComponent($scope.vocId);
|
||||
|
||||
call_http_get($http, $scope.baseUrl + '?' + $.now(), function(res) {
|
||||
$scope.vocInfo = res.data;
|
||||
|
||||
call_http_get($http, $scope.baseUrl + '/terms?' + $.now(), function(res) {
|
||||
$scope.terms = res.data;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.setCurrTerm = function(term) {
|
||||
$scope.currTerm = angular.copy(term);
|
||||
}
|
||||
|
||||
$scope.prepareNewTerm = function() {
|
||||
$scope.mode = 'new';
|
||||
$scope.editTermCode = '';
|
||||
$scope.tmpTerm = {
|
||||
'code' : '',
|
||||
'name' : '',
|
||||
'encoding' : 'OPENAIRE',
|
||||
'synonyms' : []
|
||||
};
|
||||
}
|
||||
|
||||
$scope.prepareEditTerm = function(term) {
|
||||
$scope.mode = 'edit';
|
||||
$scope.editTermCode = term.code;
|
||||
$scope.tmpTerm = angular.copy(term);
|
||||
}
|
||||
|
||||
|
||||
$scope.saveTerm = function(term) {
|
||||
var url = $scope.baseUrl + '/terms?' + $.now();
|
||||
|
||||
json_http_post($http, url, term, function(res) {
|
||||
if ($scope.editTermCode != '' && $scope.editTermCode != $scope.tmpTerm.code) {
|
||||
var deleteUrl = $scope.baseUrl + '/terms/' + encodeURIComponent($scope.editTermCode) + '?' + $.now();
|
||||
call_http_delete($http, deleteUrl, function(res) {
|
||||
$scope.terms = res.data;
|
||||
alert("Term replaced");
|
||||
});
|
||||
} else {
|
||||
$scope.terms = res.data;
|
||||
alert("Term saved");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteTerm = function(code) {
|
||||
if (confirm("Are you sure ?")) {
|
||||
var url = $scope.baseUrl + '/terms/' + encodeURIComponent(code) + '?' + $.now();
|
||||
|
||||
call_http_delete($http, url, function(res) {
|
||||
$scope.terms = res.data;
|
||||
alert("Term deleted");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
});
|
|
@ -1,93 +0,0 @@
|
|||
var app = angular.module('wfHistoryApp', []);
|
||||
|
||||
app.controller('wfHistoryController', function($scope, $http) {
|
||||
|
||||
$scope.fromDate = fromDate();
|
||||
$scope.toDate = toDate();
|
||||
$scope.maxNumberOfRecentWfs = maxNumberOfRecentWfs();
|
||||
|
||||
$scope.workflows = [];
|
||||
$scope.currentWf = {};
|
||||
$scope.currDetailsKey = '';
|
||||
$scope.currDetailsValue = '';
|
||||
$scope.sortField = 'processId';
|
||||
$scope.sortReverse = false;
|
||||
|
||||
$scope.reload = function() {
|
||||
var url = './ajax/wfs/?' + $.now();
|
||||
if ($scope.fromDate > 0) { url += "&from=" + $scope.fromDate; }
|
||||
if ($scope.toDate > 0) { url += "&to=" + $scope.toDate; }
|
||||
|
||||
call_http_get($http, url, function(res) {
|
||||
$scope.workflows = res.data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setCurrentWf = function(wf) {
|
||||
$scope.currentWf = angular.copy(wf);
|
||||
$scope.currDetailsKey = '';
|
||||
$scope.currDetailsValue = '';
|
||||
$scope.currentWf.arrayDetails = [];
|
||||
$scope.currentWf.duration = $scope.calculateDateDiff(parseInt(wf.details['system:startDate']), parseInt(wf.details['system:endDate']));
|
||||
|
||||
angular.forEach(wf.details, function(v,k) {
|
||||
$scope.currentWf.arrayDetails.push({'k':k, 'v':v});
|
||||
});
|
||||
}
|
||||
|
||||
$scope.setCurrentDetailParam = function(k, v) {
|
||||
$scope.currDetailsKey = k;
|
||||
$scope.currDetailsValue = v;
|
||||
}
|
||||
|
||||
|
||||
$scope.calculateDateDiff = function(start, end) {
|
||||
if (start <= 0 || end <= 0) {
|
||||
return '-';
|
||||
}
|
||||
var seconds = 0;
|
||||
var minutes = 0;
|
||||
var hours = 0;
|
||||
var days = 0;
|
||||
|
||||
if (end > start) {
|
||||
seconds = Math.round((end - start) / 1000);
|
||||
if (seconds > 60) {
|
||||
minutes = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
if (minutes > 60) {
|
||||
hours = Math.floor(minutes / 60);
|
||||
minutes = minutes % 60;
|
||||
if (hours > 24) {
|
||||
days = Math.floor(hours / 24);
|
||||
hours = hours % 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var res = '';
|
||||
if (days > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += days + " day(s)"
|
||||
}
|
||||
if (hours > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += hours + " hour(s)"
|
||||
}
|
||||
if (minutes > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += minutes + " minute(s)"
|
||||
}
|
||||
if (seconds > 0) {
|
||||
if (res) { res += ', '; }
|
||||
res += seconds + " second(s)"
|
||||
}
|
||||
if (!res) {
|
||||
res = '0 seconds';
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
$scope.reload();
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Contexts')"></head>
|
||||
|
||||
<body ng-app="contextsApp">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Contexts')"></nav>
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script src="js/contexts.js"></script>
|
||||
</html>
|
|
@ -1,137 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Search Datasources')"></head>
|
||||
|
||||
<body ng-app="dsmApp" ng-controller="dsmSearchController">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Search Datasources')"></nav>
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
function browsableFields() { return /*[[${browsableFields}]]*/ ''; }
|
||||
function pageSize() { return /*[[${pageSize}]]*/ ''; }
|
||||
function protocols() { return /*[[${protocols}]]*/ ''; }
|
||||
function compatibilityLevels() { return /*[[${compatibilityLevels}]]*/ ''; }
|
||||
function contentDescTypes() { return /*[[${contentDescTypes}]]*/ ''; }
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var app = angular.module('dsmApp', ['ngRoute']);
|
||||
|
||||
app.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/search', { templateUrl: 'dsm/search.html', controller: 'dsmSearchController' })
|
||||
.when('/results/:page/:size', { templateUrl: 'dsm/results.html', controller: 'dsmResultsController' })
|
||||
.when('/results/:field/:page/:size', { templateUrl: 'dsm/results.html', controller: 'dsmResultsController' })
|
||||
.when('/add/api', { templateUrl: 'dsm/addApi.html', controller: 'dsmAddApiController' })
|
||||
.when('/api', { templateUrl: 'dsm/api.html', controller: 'dsmApiController' })
|
||||
.otherwise({ redirectTo: '/search' });
|
||||
}
|
||||
]);
|
||||
|
||||
app.controller('dsmSearchController', function($scope, $http, $location, $timeout) {
|
||||
$scope.browseFieldId = "";
|
||||
$scope.browseFieldName = "";
|
||||
$scope.browseData = [];
|
||||
|
||||
$scope.browsableFields = browsableFields();
|
||||
|
||||
$scope.browseField = function(id, label) {
|
||||
$scope.browseFieldId = id;
|
||||
$scope.browseFieldName = name;
|
||||
$scope.browseData = [];
|
||||
|
||||
call_http_get($http, './ajax/dsm/browse/' + encodeURIComponent(id) + '?' + $.now(), function(res) {
|
||||
$scope.browseData = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.search = function(field, value) {
|
||||
var path = "/results";
|
||||
if (field) { path += '/' + encodeURIComponent(field); }
|
||||
path += '/0/' + pageSize();
|
||||
|
||||
$timeout(function() {
|
||||
$location.path(path).search('value', value);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.controller('dsmResultsController', function($scope, $http, $location, $routeParams) {
|
||||
$scope.field = $routeParams.field;
|
||||
$scope.value = $routeParams.value;
|
||||
$scope.pageSize = $routeParams.size;
|
||||
$scope.currPage = $routeParams.page;
|
||||
|
||||
$scope.nResults = 0;
|
||||
$scope.results = [];
|
||||
$scope.nPages = 0;
|
||||
|
||||
var url = './ajax/dsm/';
|
||||
if ($scope.field) { url += 'searchByField/' + encodeURIComponent($scope.field); }
|
||||
else { url += 'search' }
|
||||
url += '/' + $scope.currPage + '/' + $scope.pageSize;
|
||||
url += '?value=' + encodeURIComponent($scope.value) + '&' + $.now();
|
||||
|
||||
call_http_get($http, url, function(res) {
|
||||
$scope.results = res.data.content;
|
||||
$scope.nResults = res.data.totalElements;
|
||||
$scope.currPage = res.data.number;
|
||||
$scope.nPages = res.data.totalPages;
|
||||
});
|
||||
|
||||
$scope.gotoPage = function(page) {
|
||||
$scope.results = [];
|
||||
var path = "/results";
|
||||
if ($scope.field) { path += '/' + encodeURIComponent($scope.field); }
|
||||
path += '/' + page + '/' + $scope.pageSize;
|
||||
$location.path(path).search('value', $scope.value);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
app.controller('dsmApiController', function($scope, $http, $location, $timeout, $routeParams) {
|
||||
$scope.apiId = $routeParams.id;
|
||||
$scope.api = {};
|
||||
|
||||
call_http_get($http, './ajax/dsm/api?id=' + encodeURIComponent($scope.apiId) , function(res) {
|
||||
$scope.api = res.data;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
app.controller('dsmAddApiController', function($scope, $http, $location, $timeout, $routeParams) {
|
||||
$scope.dsName = $routeParams.dsName;
|
||||
$scope.prefix = 'api_________::' + $routeParams.dsId + '::';
|
||||
$scope.api = {}
|
||||
|
||||
$scope.protocols = protocols();
|
||||
$scope.compatibilityLevels = compatibilityLevels();
|
||||
$scope.contentDescTypes = contentDescTypes();
|
||||
|
||||
$scope.save = function() {
|
||||
var record = angular.copy($scope.api);
|
||||
record.id = $scope.prefix + record.id;
|
||||
record.datasource = $routeParams.dsId;
|
||||
|
||||
json_http_post($http, './ajax/dsm/api', record, function(res) {
|
||||
$scope.api = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -1,194 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
<head th:fragment="htmlHeader(pageTitle)">
|
||||
<title th:text="|OpenAIRE Tools - ${pageTitle}|"></title>
|
||||
<link rel="stylesheet" href="common/css/bootstrap.cerulean.min.css" />
|
||||
<link rel="stylesheet" href="common/css/fontawesome-all.min.css" />
|
||||
|
||||
<style type="text/css">
|
||||
td,th {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.overlaydiv {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 10000;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.grayRectangle {
|
||||
position: absolute;
|
||||
background-color: black;
|
||||
opacity:0.6;
|
||||
top: 30%;
|
||||
left: 40%;
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
z-index: 100;
|
||||
border-radius: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<th:block th:fragment="mainMenu(pageTitle)">
|
||||
|
||||
<div id="spinnerdiv" class="overlaydiv">
|
||||
<span class="grayRectangle"><!--The spinner is added on loading here--></span>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="/main">D-Net</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="./main">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Datasources</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="./dsm">Search</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Configuration</a>
|
||||
<div class="dropdown-menu">
|
||||
<h6 class="dropdown-header">Simple resources</h6>
|
||||
<a th:each="t: ${resTypes}"
|
||||
th:if="${t.simple}"
|
||||
class="dropdown-item"
|
||||
th:href="@{'./resources?type=' + ${t.id}}">
|
||||
<span th:text="${t.name}"></span>
|
||||
<span th:text="${t.count}" class="badge badge-primary"></span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<h6 class="dropdown-header">Advanced resources</h6>
|
||||
<a th:each="t: ${resTypes}"
|
||||
th:unless="${t.simple}"
|
||||
class="dropdown-item"
|
||||
th:href="@{'./resources?type=' + ${t.id}}">
|
||||
<span th:text="${t.name}"></span>
|
||||
<span th:text="${t.count}" class="badge badge-primary"></span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Logs</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="./wf_history">Workflow history</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="javascript:void(0)" data-toggle="dropdown">Info</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="./info">Container Info</a>
|
||||
<a class="dropdown-item" href="./docs" target="_blank">API documentation</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<h1 class="ml-3 mb-4 mt-3" th:text="${pageTitle}"></h1>
|
||||
|
||||
</th:block>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:fragment="scripts">
|
||||
<script>
|
||||
// Spinner show/hide methods ~ Andrea Mannocci
|
||||
var spinnerOpts = {
|
||||
lines: 15,
|
||||
length: 16,
|
||||
width: 5,
|
||||
radius: 25,
|
||||
color: '#eeeeee',
|
||||
className: 'spinner',
|
||||
top: '40%'
|
||||
};
|
||||
|
||||
var spinnerTarget = document.getElementById('spinnerdiv');
|
||||
|
||||
var spinner;
|
||||
|
||||
function showSpinner() {
|
||||
spinner = new Spinner(spinnerOpts).spin(spinnerTarget);
|
||||
spinnerTarget.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
function hideSpinner() {
|
||||
spinnerTarget.style.visibility = 'hidden';
|
||||
spinner.stop();
|
||||
}
|
||||
|
||||
function call_http_get($http, url, onSuccess) {
|
||||
showSpinner();
|
||||
|
||||
$http.get(url).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
function call_http_delete($http, url, onSuccess) {
|
||||
showSpinner();
|
||||
|
||||
$http.delete(url).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
function json_http_post($http, url, obj, onSuccess) {
|
||||
showSpinner();
|
||||
$http.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
|
||||
$http.post(url, obj).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
function params_http_post($http, url, params, onSuccess) {
|
||||
showSpinner();
|
||||
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
|
||||
$http.post(url, params).then(function successCallback(res) {
|
||||
hideSpinner();
|
||||
onSuccess(res);
|
||||
}, function errorCallback(res) {
|
||||
hideSpinner();
|
||||
alert('ERROR: ' + res.data.error + ' (' + res.data.message + ')');
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script src="common/js/jquery.min.js"></script>
|
||||
<script src="common/js/popper.min.js"></script>
|
||||
<script src="common/js/bootstrap.min.js"></script>
|
||||
<script src="common/js/angular.min.js"></script>
|
||||
<script src="common/js/angular-route.min.js"></script>
|
||||
<script src="common/js/spin.js"></script>
|
||||
|
||||
</th:block>
|
||||
|
||||
</html>
|
|
@ -1,85 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Info')"></head>
|
||||
|
||||
<body ng-app="infoApp" ng-controller="infoController">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Info')"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
<p>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="infoFilter" placeholder="Filter..."/>
|
||||
</p>
|
||||
|
||||
<div class="card mb-3" ng-repeat="section in info" ng-show="(section.data|filter:infoFilter).length > 0">
|
||||
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{section.name}}</h5>
|
||||
|
||||
<table class="table table-striped table-sm small" style="table-layout: fixed;">
|
||||
<thead ng-if="section.name == 'Modules'">
|
||||
<tr>
|
||||
<th>Group ID</th>
|
||||
<th>Artifact ID</th>
|
||||
<th>Version</th>
|
||||
<th>POM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="r in section.data|filter:infoFilter" ng-if="section.name != 'Modules'">
|
||||
<th style="width: 25%;">{{r.k}}</th>
|
||||
<td style="overflow-x: auto;"><pre style="margin: 0;">{{r.v}}</pre></td>
|
||||
</tr>
|
||||
<tr ng-repeat="r in section.data|filter:infoFilter" ng-if="section.name == 'Modules'" ng-class="{'table-warning' : r.files.length > 1}">
|
||||
<td>{{r.group}}</td>
|
||||
<td>{{r.name}}</td>
|
||||
<td class="text-monospace"><span ng-repeat="v in r.versions">{{v}}<br /></span></td>
|
||||
<td class="text-monospace"><span ng-repeat="f in r.files">{{f}}<br /></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script>
|
||||
var app = angular.module('infoApp', []);
|
||||
|
||||
app.controller('infoController', function($scope, $http) {
|
||||
$scope.info = [];
|
||||
|
||||
call_http_get($http, './ajax/info/?' + $.now(), function(res) {
|
||||
angular.forEach(res.data, function(section) {
|
||||
if (section.name != 'Modules') {
|
||||
angular.forEach(section.data, function(r) {
|
||||
if (r.k.toLowerCase().endsWith('path') || r.k.toLowerCase().endsWith('.dirs')) {
|
||||
r.v = r.v.replaceAll(':', ':\n');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$scope.info = res.data;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Homepage')"></head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Homepage')"></nav>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
</html>
|
|
@ -1,62 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Harvesting Protocols')"></head>
|
||||
|
||||
<body ng-app="protocolsApp" ng-controller="protocolsController">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Harvesting Protocols')"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<p><b>NOTE:</b> Use the api to register new protocols</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card mt-4" ng-repeat="prot in protocols">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{prot.id}}</h5>
|
||||
<p class="card-text" ng-if="prot.params.length == 0">No parameters</p>
|
||||
<table class="table table-sm table-striped" ng-if="prot.params.length > 0">
|
||||
<thead>
|
||||
<th style="width: 20%">Parameter</th>
|
||||
<th>Description</th>
|
||||
<th style="width: 15%" class="text-center">Type</th>
|
||||
<th style="width: 15%" class="text-center">Required</th>
|
||||
<th style="width: 15%" class="text-center">Has Sel Function</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="p in prot.params">
|
||||
<th>{{p.name}}</th>
|
||||
<td>{{p.label}}</td>
|
||||
<td class="text-center">{{p.type}}</td>
|
||||
<td class="text-center"><i class="fa fa-check" ng-if="!p.optional"></i></td>
|
||||
<td class="text-center"><i class="fa fa-check" ng-if="p.hasSelFunction"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script>
|
||||
var app = angular.module('protocolsApp', []);
|
||||
|
||||
app.controller('protocolsController', function($scope, $http) {
|
||||
$scope.protocols = [];
|
||||
|
||||
call_http_get($http, './ajax/protocols/?' + $.now(), function(res) {
|
||||
$scope.protocols = res.data;
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader(${type.name})"></head>
|
||||
|
||||
<script th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
function typeId() { return /*[[${type.id}]]*/ ''; }
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
<body ng-app="resourcesApp" ng-controller="resourcesController">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu(${type.name})"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p>
|
||||
<button class="btn btn-sm btn-primary" data-toggle="modal" data-target="#newResourceModal" ng-click="prepareNewResource()">create a new resource</button>
|
||||
</p>
|
||||
<p ng-show="resources.length > 0">
|
||||
<input type="text" class="form-control form-control-sm" ng-model="resFilter" placeholder="Filter..."/>
|
||||
</p>
|
||||
<p>
|
||||
<span class="text-muted"><b>Number of resources:</b> {{(resources | filter:resFilter).length}}</span>
|
||||
</p>
|
||||
|
||||
<div class="card mb-4" ng-repeat="r in resources|filter:resFilter">
|
||||
<div class="card-body small">
|
||||
<span class="badge badge-primary float-right" th:text="${type.contentType}"></span>
|
||||
<h5 class="card-title" title="{{r.id}}">{{r.name}}</h5>
|
||||
<p class="card-text">{{r.description}}</p>
|
||||
<p class="text-muted small">
|
||||
<b>Id:</b> {{r.id}}<br />
|
||||
<b>Creation date:</b> {{r.creationDate}}<br />
|
||||
<b>Modification date:</b> {{r.modificationDate}}
|
||||
</p>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editMetadataModal" ng-click="prepareEditMetadata(r)">edit metadata</button>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editContentModal" ng-click="prepareEditContent(r)">edit content</button>
|
||||
<a href="./api/resources/{{r.id}}/content" class="btn btn-sm btn-success" target="_blank">raw content</a>
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="deleteResource(r)">delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="editMetadataModal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Edit metadata</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<form>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>ID</label>
|
||||
<input type="text" readonly class="form-control-plaintext" ng-model="tmpRes.id" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Type</label>
|
||||
<input type="text" readonly class="form-control-plaintext" ng-model="tmpRes.type" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Name</label>
|
||||
<input type="text" class="form-control" ng-model="tmpRes.name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea class="form-control" ng-model="tmpRes.description" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" data-dismiss="modal" ng-click="saveMetadata(tmpRes.id, tmpRes)" ng-disabled="!tmpRes.id || !tmpRes.name">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="newResourceModal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">New resource: <span th:text="${type.id}"></span></h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<form>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Name</label>
|
||||
<input type="text" class="form-control" ng-model="tmpRes.name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea class="form-control" ng-model="tmpRes.description"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Content (<span th:text="${type.contentType}"></span>)</label>
|
||||
<textarea class="form-control" ng-model="tmpRes.content" rows="25"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" ng-click="createNewResource(tmpRes)" ng-disabled="!tmpRes.name || !tmpRes.content">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="editContentModal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Edit content</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<form>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label th:text="${type.contentType}"></label>
|
||||
<textarea class="form-control" ng-model="tmpContent" rows="25"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" ng-click="saveContent(tmpRes.id, tmpContent)" ng-disabled="!tmpContent">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script src="js/simpleResources.js"></script>
|
||||
</html>
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Vocabularies')"></head>
|
||||
|
||||
<body ng-app="vocabulariesApp">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Vocabularies')"></nav>
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script src="js/vocabularies.js"></script>
|
||||
</html>
|
|
@ -1,153 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head th:replace="fragments/mainParts.html :: htmlHeader('Workflow history')"></head>
|
||||
|
||||
<script th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
function maxNumberOfRecentWfs() { return /*[[${maxNumberOfRecentWfs}]]*/ -1; }
|
||||
function fromDate() { return /*[[${fromDate}]]*/ -1; }
|
||||
function toDate() { return /*[[${toDate}]]*/ -1; }
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
<body ng-app="wfHistoryApp" ng-controller="wfHistoryController">
|
||||
|
||||
<nav th:replace="fragments/mainParts.html :: mainMenu('Workflow history')"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
<p ng-show="workflows.length > 0">
|
||||
<input type="text" class="form-control form-control-sm" ng-model="wfFilter" placeholder="Filter..."/>
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
<span ng-show="fromDate < 0 && toDate < 0"><b>Recent workflows</b> (max {{maxNumberOfRecentWfs}})</span>
|
||||
<span ng-show="fromDate >= 0 && toDate >= 0"><b>Workflows from </b>{{fromDate | date:"yyyy-MM-dd HH:mm:ss"}} <b>to</b> {{toDate | date:"yyyy-MM-dd HH:mm:ss"}}</span>
|
||||
<span ng-show="fromDate >= 0 && toDate < 0"><b>Workflows from </b>{{fromDate | date:"yyyy-MM-dd HH:mm:ss"}} <b>to</b> <i>undefined</i></span>
|
||||
<span ng-show="fromDate < 0 && toDate >= 0"><b>Workflows from </b><i>undefined</i> <b>to</b> {{toDate | date:"yyyy-MM-dd HH:mm:ss"}}</span>
|
||||
<br />
|
||||
<span><b>Count :</b> {{(workflows | filter:wfFilter).length}}</span>
|
||||
</p>
|
||||
<table class="table table-sm table-striped small">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'processId'; sortReverse = !sortReverse">
|
||||
Process Id
|
||||
<i ng-show="sortField == 'processId' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'processId' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 20%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'name'; sortReverse = !sortReverse">
|
||||
Workflow Name
|
||||
<i ng-show="sortField == 'name' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'name' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'family'; sortReverse = !sortReverse">
|
||||
Workflow Family
|
||||
<i ng-show="sortField == 'family' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'family' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 30%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'dsName'; sortReverse = !sortReverse">
|
||||
Datasource
|
||||
<i ng-show="sortField == 'dsName' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'dsName' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'status'; sortReverse = !sortReverse">
|
||||
Status
|
||||
<i ng-show="sortField == 'status' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'status' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'startDate'; sortReverse = !sortReverse">
|
||||
Start Date
|
||||
<i ng-show="sortField == 'startDate' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'startDate' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 10%">
|
||||
<a href="javascript:void(0)" ng-click="sortField = 'endDate'; sortReverse = !sortReverse">
|
||||
End Date
|
||||
<i ng-show="sortField == 'endDate' && !sortReverse" class="fa fa-angle-down"></i>
|
||||
<i ng-show="sortField == 'endDate' && sortReverse" class="fa fa-angle-up"></i>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-show="(workflows|filter:wfFilter).length == 0">
|
||||
<td colspan="7" class="text-muted">no workflows</td>
|
||||
</tr>
|
||||
<tr ng-repeat="wf in workflows | orderBy:sortField:sortReverse | filter:wfFilter">
|
||||
<th><a href="javascript:void(0)" data-toggle="modal" data-target="#showWfDetailsModal" ng-click="setCurrentWf(wf)">{{wf.processId}}</a></th>
|
||||
<td>{{wf.name}}</td>
|
||||
<td>{{wf.family}}</td>
|
||||
<td>{{wf.dsName}}</td>
|
||||
<td><span class="badge" ng-class="{
|
||||
'badge-success' : (wf.status == 'success'),
|
||||
'badge-danger' : (wf.status == 'failure'),
|
||||
'badge-primary' : (wf.status != 'success') && (wf.status != 'failure')
|
||||
}">{{wf.status}}</span></td>
|
||||
<td>{{wf.startDate}}</td>
|
||||
<td>{{wf.endDate}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="showWfDetailsModal">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Details</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
<b>Started at: </b>{{currentWf.startDate}}<br />
|
||||
<b>Finished at: </b>{{currentWf.endDate}}<br />
|
||||
<b>Duration: </b>{{currentWf.duration}}<br />
|
||||
</p>
|
||||
|
||||
<input type="text" class="form-control form-control-sm" ng-model="detailsFilter" placeholder="Filter..."/>
|
||||
|
||||
<table class="table table-sm table-striped small mt-2" style="table-layout: fixed;">
|
||||
<tr ng-repeat="p in currentWf.arrayDetails | filter:detailsFilter">
|
||||
<th style="width: 30%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"><a href="javascript:void(0)" ng-click="setCurrentDetailParam(p.k,p.v)">{{p.k}}</a></th>
|
||||
<td style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{p.v}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="card card-body bg-light" ng-show="currDetailsKey">
|
||||
<b>{{currDetailsKey}}</b><br />
|
||||
<pre>{{currDetailsValue}}</pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<th:block th:replace="fragments/mainParts.html :: scripts"></th:block>
|
||||
|
||||
<script src="js/wf_history.js"></script>
|
||||
</html>
|
Loading…
Reference in New Issue