move to @Service

This commit is contained in:
Michele Artini 2022-11-28 11:11:13 +01:00
parent 9e05516295
commit a402e0c85d
11 changed files with 229 additions and 130 deletions

View File

@ -1,120 +1,52 @@
package eu.dnetlib.is.context; package eu.dnetlib.is.context;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.dnetlib.common.controller.AbstractDnetController;
import eu.dnetlib.is.context.model.Category; import eu.dnetlib.is.context.model.Category;
import eu.dnetlib.is.context.model.ConceptLevel0;
import eu.dnetlib.is.context.model.ConceptLevel1;
import eu.dnetlib.is.context.model.ConceptLevel2;
import eu.dnetlib.is.context.model.Context; import eu.dnetlib.is.context.model.Context;
import eu.dnetlib.is.context.model.CtxChildInfo; import eu.dnetlib.is.context.model.CtxChildInfo;
import eu.dnetlib.is.context.model.repository.CategoryRepository; import eu.dnetlib.is.util.InformationServiceException;
import eu.dnetlib.is.context.model.repository.ConceptLevel0Repository;
import eu.dnetlib.is.context.model.repository.ConceptLevel1Repository;
import eu.dnetlib.is.context.model.repository.ConceptLevel2Repository;
import eu.dnetlib.is.context.model.repository.ContextRepository;
@RestController @RestController
@RequestMapping("/api/contexts") @RequestMapping("/api/contexts")
public class ContextRestController { public class ContextRestController extends AbstractDnetController {
@Autowired @Autowired
private ContextRepository contextRepository; private ContextService contextService;
@Autowired
private CategoryRepository categoryRepository;
@Autowired
private ConceptLevel0Repository conceptLevel0Repository;
@Autowired
private ConceptLevel1Repository conceptLevel1Repository;
@Autowired
private ConceptLevel2Repository conceptLevel2Repository;
private static final Log log = LogFactory.getLog(ContextRestController.class);
@GetMapping("/") @GetMapping("/")
public List<Context> listContexts() { public List<Context> listContexts() {
return contextRepository.findAll() return contextService.listContexts();
.stream()
.sorted((v1, v2) -> StringUtils.compareIgnoreCase(v1.getId(), v2.getId()))
.collect(Collectors.toList());
} }
@GetMapping("/{ctxId}") @GetMapping("/{ctxId}")
public Context getContext(@PathVariable final String ctxId) { public Context getContext(@PathVariable final String ctxId) throws InformationServiceException {
return contextRepository.findById(ctxId).get(); return contextService.getContext(ctxId);
} }
@GetMapping("/{ctxId}/full") @GetMapping("/{ctxId}/full")
public ObjectNode getContextFull(@PathVariable final String ctxId) { public ObjectNode getContextFull(@PathVariable final String ctxId) throws InformationServiceException {
return contextService.getContextFull(ctxId);
final ObjectMapper mapper = new ObjectMapper();
final Context ctx = contextRepository.findById(ctxId).get();
final ObjectNode ctxNode = mapper.convertValue(ctx, ObjectNode.class);
final ArrayNode catArray = mapper.createArrayNode();
for (final Category cat : categoryRepository.findByParentOrderById(ctxId)) {
final ObjectNode catNode = mapper.convertValue(cat, ObjectNode.class);
catArray.add(catNode);
final ArrayNode c0Array = mapper.createArrayNode();
for (final ConceptLevel0 c0 : conceptLevel0Repository.findByParentOrderById(cat.getId())) {
final ObjectNode c0Node = mapper.convertValue(c0, ObjectNode.class);
c0Array.add(c0Node);
final ArrayNode c1Array = mapper.createArrayNode();
for (final ConceptLevel1 c1 : conceptLevel1Repository.findByParentOrderById(c0.getId())) {
final ObjectNode c1Node = mapper.convertValue(c1, ObjectNode.class);
c1Array.add(c1Node);
final ArrayNode c2Array = mapper.createArrayNode();
for (final ConceptLevel2 c2 : conceptLevel2Repository.findByParentOrderById(c1.getId())) {
final ObjectNode c2Node = mapper.convertValue(c2, ObjectNode.class);
c2Array.add(c2Node);
}
c1Node.set("concepts", c2Array);
}
c0Node.set("concepts", c1Array);
}
catNode.set("concepts", c0Array);
}
ctxNode.set("categories", catArray);
return ctxNode;
} }
@GetMapping("/{parent}/categories") @GetMapping("/{parent}/categories")
public Iterable<Category> listCategories(@PathVariable final String parent) { public Iterable<Category> listCategories(@PathVariable final String parent) {
return categoryRepository.findByParentOrderById(parent); return contextService.listCategories(parent);
} }
@GetMapping("/{level}/{parent}/concepts") @GetMapping("/{level}/{parent}/concepts")
public Iterable<? extends CtxChildInfo> listCategories(@PathVariable final int level, @PathVariable final String parent) { public Iterable<? extends CtxChildInfo> listCategories(@PathVariable final int level, @PathVariable final String parent)
switch (level) { throws InformationServiceException {
case 0: return contextService.listCategories(level, parent);
return conceptLevel0Repository.findByParentOrderById(parent);
case 1:
return conceptLevel1Repository.findByParentOrderById(parent);
case 2:
return conceptLevel2Repository.findByParentOrderById(parent);
default:
throw new RuntimeException("Invalid concept level - valid levels are 0, 1, 2");
}
} }
} }

View File

@ -0,0 +1,112 @@
package eu.dnetlib.is.context;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.dnetlib.is.context.model.Category;
import eu.dnetlib.is.context.model.ConceptLevel0;
import eu.dnetlib.is.context.model.ConceptLevel1;
import eu.dnetlib.is.context.model.ConceptLevel2;
import eu.dnetlib.is.context.model.Context;
import eu.dnetlib.is.context.model.CtxChildInfo;
import eu.dnetlib.is.context.model.repository.CategoryRepository;
import eu.dnetlib.is.context.model.repository.ConceptLevel0Repository;
import eu.dnetlib.is.context.model.repository.ConceptLevel1Repository;
import eu.dnetlib.is.context.model.repository.ConceptLevel2Repository;
import eu.dnetlib.is.context.model.repository.ContextRepository;
import eu.dnetlib.is.util.InformationServiceException;
@Service
public class ContextService {
@Autowired
private ContextRepository contextRepository;
@Autowired
private CategoryRepository categoryRepository;
@Autowired
private ConceptLevel0Repository conceptLevel0Repository;
@Autowired
private ConceptLevel1Repository conceptLevel1Repository;
@Autowired
private ConceptLevel2Repository conceptLevel2Repository;
private static final Log log = LogFactory.getLog(ContextService.class);
public List<Context> listContexts() {
return contextRepository.findAll()
.stream()
.sorted((v1, v2) -> StringUtils.compareIgnoreCase(v1.getId(), v2.getId()))
.collect(Collectors.toList());
}
public Context getContext(final String ctxId) throws InformationServiceException {
return contextRepository.findById(ctxId).orElseThrow(() -> new InformationServiceException("Context Not found"));
}
public ObjectNode getContextFull(final String ctxId) throws InformationServiceException {
final ObjectMapper mapper = new ObjectMapper();
final Context ctx = getContext(ctxId);
final ObjectNode ctxNode = mapper.convertValue(ctx, ObjectNode.class);
final ArrayNode catArray = mapper.createArrayNode();
for (final Category cat : categoryRepository.findByParentOrderById(ctxId)) {
final ObjectNode catNode = mapper.convertValue(cat, ObjectNode.class);
catArray.add(catNode);
final ArrayNode c0Array = mapper.createArrayNode();
for (final ConceptLevel0 c0 : conceptLevel0Repository.findByParentOrderById(cat.getId())) {
final ObjectNode c0Node = mapper.convertValue(c0, ObjectNode.class);
c0Array.add(c0Node);
final ArrayNode c1Array = mapper.createArrayNode();
for (final ConceptLevel1 c1 : conceptLevel1Repository.findByParentOrderById(c0.getId())) {
final ObjectNode c1Node = mapper.convertValue(c1, ObjectNode.class);
c1Array.add(c1Node);
final ArrayNode c2Array = mapper.createArrayNode();
for (final ConceptLevel2 c2 : conceptLevel2Repository.findByParentOrderById(c1.getId())) {
final ObjectNode c2Node = mapper.convertValue(c2, ObjectNode.class);
c2Array.add(c2Node);
}
c1Node.set("concepts", c2Array);
}
c0Node.set("concepts", c1Array);
}
catNode.set("concepts", c0Array);
}
ctxNode.set("categories", catArray);
return ctxNode;
}
public Iterable<Category> listCategories(final String parent) {
return categoryRepository.findByParentOrderById(parent);
}
public Iterable<? extends CtxChildInfo> listCategories(final int level, final String parent) throws InformationServiceException {
switch (level) {
case 0:
return conceptLevel0Repository.findByParentOrderById(parent);
case 1:
return conceptLevel1Repository.findByParentOrderById(parent);
case 2:
return conceptLevel2Repository.findByParentOrderById(parent);
default:
throw new InformationServiceException("Invalid concept level - valid levels are 0, 1, 2");
}
}
}

View File

@ -11,7 +11,7 @@ import org.dom4j.DocumentException;
import org.dom4j.Node; import org.dom4j.Node;
import org.dom4j.io.SAXReader; import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;
import eu.dnetlib.is.context.model.Category; import eu.dnetlib.is.context.model.Category;
import eu.dnetlib.is.context.model.ConceptLevel0; import eu.dnetlib.is.context.model.ConceptLevel0;
@ -27,7 +27,7 @@ import eu.dnetlib.is.context.model.repository.ConceptLevel1Repository;
import eu.dnetlib.is.context.model.repository.ConceptLevel2Repository; import eu.dnetlib.is.context.model.repository.ConceptLevel2Repository;
import eu.dnetlib.is.context.model.repository.ContextRepository; import eu.dnetlib.is.context.model.repository.ContextRepository;
@Component @Service
public class ContextImporter { public class ContextImporter {
@Autowired @Autowired

View File

@ -17,12 +17,13 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import eu.dnetlib.common.controller.AbstractDnetController;
import eu.dnetlib.is.resource.model.SimpleResource; import eu.dnetlib.is.resource.model.SimpleResource;
import eu.dnetlib.is.vocabulary.model.Vocabulary; import eu.dnetlib.is.vocabulary.model.Vocabulary;
@RestController @RestController
@RequestMapping("/api/import") @RequestMapping("/api/import")
public class ImporterController { public class ImporterController extends AbstractDnetController {
@Autowired @Autowired
private ContextImporter contextImporter; private ContextImporter contextImporter;

View File

@ -11,7 +11,7 @@ import org.dom4j.DocumentException;
import org.dom4j.Node; import org.dom4j.Node;
import org.dom4j.io.SAXReader; import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;
import eu.dnetlib.is.resource.model.SimpleResource; import eu.dnetlib.is.resource.model.SimpleResource;
import eu.dnetlib.is.resource.repository.SimpleResourceRepository; import eu.dnetlib.is.resource.repository.SimpleResourceRepository;
@ -22,7 +22,7 @@ import eu.dnetlib.is.vocabulary.model.VocabularyTerm;
import eu.dnetlib.is.vocabulary.repository.VocabularyRepository; import eu.dnetlib.is.vocabulary.repository.VocabularyRepository;
import eu.dnetlib.is.vocabulary.repository.VocabularyTermRepository; import eu.dnetlib.is.vocabulary.repository.VocabularyTermRepository;
@Component @Service
public class OldProfilesImporter { public class OldProfilesImporter {
@Autowired @Autowired

View File

@ -12,7 +12,7 @@ import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import eu.dnetlib.is.wf.model.WfProcessExecution; import eu.dnetlib.is.wf.model.WfProcessExecution;
import eu.dnetlib.is.wf.repository.WfProcessExecutionRepository; import eu.dnetlib.is.wf.repository.WfProcessExecutionRepository;
@Component @Service
public class WfHistoryImporter { public class WfHistoryImporter {
private static final Log log = LogFactory.getLog(WfHistoryImporter.class); private static final Log log = LogFactory.getLog(WfHistoryImporter.class);

View File

@ -19,12 +19,13 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import eu.dnetlib.common.controller.AbstractDnetController;
import eu.dnetlib.is.resource.model.SimpleResource; import eu.dnetlib.is.resource.model.SimpleResource;
import eu.dnetlib.is.util.InformationServiceException; import eu.dnetlib.is.util.InformationServiceException;
@RestController @RestController
@RequestMapping("/api/resources") @RequestMapping("/api/resources")
public class ResourcesRestController { public class ResourcesRestController extends AbstractDnetController {
@Autowired @Autowired
private SimpleResourceService service; private SimpleResourceService service;

View File

@ -1,11 +1,7 @@
package eu.dnetlib.is.vocabulary; package eu.dnetlib.is.vocabulary;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -16,74 +12,54 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import eu.dnetlib.common.controller.AbstractDnetController; import eu.dnetlib.common.controller.AbstractDnetController;
import eu.dnetlib.is.importer.OldProfilesImporter; import eu.dnetlib.is.util.InformationServiceException;
import eu.dnetlib.is.vocabulary.model.Vocabulary; import eu.dnetlib.is.vocabulary.model.Vocabulary;
import eu.dnetlib.is.vocabulary.model.VocabularyTerm; import eu.dnetlib.is.vocabulary.model.VocabularyTerm;
import eu.dnetlib.is.vocabulary.model.VocabularyTermPK;
import eu.dnetlib.is.vocabulary.repository.VocabularyRepository;
import eu.dnetlib.is.vocabulary.repository.VocabularyTermRepository;
@RestController @RestController
@RequestMapping("/api/vocs") @RequestMapping("/api/vocs")
public class VocabularyRestController extends AbstractDnetController { public class VocabularyRestController extends AbstractDnetController {
@Autowired @Autowired
private VocabularyRepository vocabularyRepository; private VocabularyService vocabularyService;
@Autowired
private VocabularyTermRepository vocabularyTermRepository;
@Autowired
private OldProfilesImporter oldProfilesImporter;
private static final Log log = LogFactory.getLog(VocabularyRestController.class);
@GetMapping("/") @GetMapping("/")
public List<Vocabulary> listVocs() { public List<Vocabulary> listVocs() {
return vocabularyRepository.findAll() return vocabularyService.listVocs();
.stream()
.sorted((v1, v2) -> StringUtils.compareIgnoreCase(v1.getId(), v2.getId()))
.collect(Collectors.toList());
} }
@GetMapping("/{vocabulary}") @GetMapping("/{vocabulary}")
public Vocabulary getVoc(@PathVariable final String vocabulary) { public Vocabulary getVoc(@PathVariable final String vocabulary) throws InformationServiceException {
return vocabularyRepository.getById(vocabulary); return vocabularyService.getVoc(vocabulary);
} }
@DeleteMapping("/{vocabulary}") @DeleteMapping("/{vocabulary}")
public List<Vocabulary> deleteVocs(@PathVariable final String vocabulary) { public List<Vocabulary> deleteVocs(@PathVariable final String vocabulary) {
log.info("Deleting vocabulary: " + vocabulary); vocabularyService.deleteVocs(vocabulary);
vocabularyRepository.deleteById(vocabulary); return vocabularyService.listVocs();
return listVocs();
} }
@PostMapping("/") @PostMapping("/")
public List<Vocabulary> saveVoc(@RequestBody final Vocabulary voc) { public List<Vocabulary> saveVoc(@RequestBody final Vocabulary voc) {
log.info("Saving vocabulary: " + voc); vocabularyService.saveVoc(voc);
vocabularyRepository.save(voc); return vocabularyService.listVocs();
return listVocs();
} }
@GetMapping("/{vocabulary}/terms") @GetMapping("/{vocabulary}/terms")
public Iterable<VocabularyTerm> listTerms(@PathVariable final String vocabulary) { public Iterable<VocabularyTerm> listTerms(@PathVariable final String vocabulary) {
return vocabularyTermRepository.findByVocabularyOrderByCode(vocabulary); return vocabularyService.listTerms(vocabulary);
} }
@PostMapping("/{vocabulary}/terms") @PostMapping("/{vocabulary}/terms")
public Iterable<VocabularyTerm> saveTerm(@PathVariable final String vocabulary, @RequestBody final VocabularyTerm term) { public Iterable<VocabularyTerm> saveTerm(@PathVariable final String vocabulary, @RequestBody final VocabularyTerm term) {
term.setVocabulary(vocabulary); vocabularyService.saveTerms(vocabulary, term);
vocabularyTermRepository.save(term); return vocabularyService.listTerms(vocabulary);
return vocabularyTermRepository.findByVocabularyOrderByCode(vocabulary);
} }
@DeleteMapping("/{vocabulary}/terms/{term}") @DeleteMapping("/{vocabulary}/terms/{term}")
public Iterable<VocabularyTerm> listTerms(@PathVariable final String vocabulary, @PathVariable final String term) { public Iterable<VocabularyTerm> deleteTerms(@PathVariable final String vocabulary, @PathVariable final String term) {
final VocabularyTermPK pk = new VocabularyTermPK(); vocabularyService.deleteTerms(vocabulary, term);
pk.setCode(term); return vocabularyService.listTerms(vocabulary);
pk.setVocabulary(vocabulary);
vocabularyTermRepository.deleteById(pk);
return vocabularyTermRepository.findByVocabularyOrderByCode(vocabulary);
} }
} }

View File

@ -0,0 +1,77 @@
package eu.dnetlib.is.vocabulary;
import java.util.List;
import java.util.stream.Collectors;
import javax.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import eu.dnetlib.is.util.InformationServiceException;
import eu.dnetlib.is.vocabulary.model.Vocabulary;
import eu.dnetlib.is.vocabulary.model.VocabularyTerm;
import eu.dnetlib.is.vocabulary.model.VocabularyTermPK;
import eu.dnetlib.is.vocabulary.repository.VocabularyRepository;
import eu.dnetlib.is.vocabulary.repository.VocabularyTermRepository;
@Service
public class VocabularyService {
@Autowired
private VocabularyRepository vocabularyRepository;
@Autowired
private VocabularyTermRepository vocabularyTermRepository;
private static final Log log = LogFactory.getLog(VocabularyService.class);
public List<Vocabulary> listVocs() {
return vocabularyRepository.findAll()
.stream()
.sorted((v1, v2) -> StringUtils.compareIgnoreCase(v1.getId(), v2.getId()))
.collect(Collectors.toList());
}
public Vocabulary getVoc(final String vocabulary) throws InformationServiceException {
return vocabularyRepository.findById(vocabulary).orElseThrow(() -> new InformationServiceException("Vocabulary not found"));
}
@Transactional
public void deleteVocs(final String... ids) {
for (final String id : ids) {
vocabularyRepository.deleteById(id);
}
}
public void saveVoc(final Vocabulary voc) {
log.info("Saving vocabulary: " + voc);
vocabularyRepository.save(voc);
}
public Iterable<VocabularyTerm> listTerms(final String vocabulary) {
return vocabularyTermRepository.findByVocabularyOrderByCode(vocabulary);
}
@Transactional
public void saveTerms(final String vocabulary, final VocabularyTerm... terms) {
for (final VocabularyTerm t : terms) {
t.setVocabulary(vocabulary);
vocabularyTermRepository.save(t);
}
}
@Transactional
public void deleteTerms(final String vocabulary, final String... terms) {
for (final String t : terms) {
final VocabularyTermPK pk = new VocabularyTermPK();
pk.setCode(t);
pk.setVocabulary(vocabulary);
vocabularyTermRepository.deleteById(pk);
}
}
}

View File

@ -24,7 +24,7 @@
<b>Parameters: </b><a href="javascript:void(0)" data-toggle="modal" data-target="#showParametersModal" ng-click="loadContextParameters()">[show]</a> <b>Parameters: </b><a href="javascript:void(0)" data-toggle="modal" data-target="#showParametersModal" ng-click="loadContextParameters()">[show]</a>
</p> </p>
<p> <p>
<a class="btn btn-sm btn-primary" href="/contexts">Return to contexts list</a> <a class="btn btn-sm btn-primary" href="./resources?type=context">Return to contexts list</a>
</p> </p>
<ul> <ul>

View File

@ -23,7 +23,7 @@
<b>Description: </b><span th:text="${vocDesc}"></span> <b>Description: </b><span th:text="${vocDesc}"></span>
</p> </p>
<p> <p>
<a class="btn btn-sm btn-primary" href="/vocabularies">Return to vocabulary list</a> <a class="btn btn-sm btn-primary" href="./resources?type=vocabulary">Return to vocabulary list</a>
</p> </p>
<p> <p>
<button class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editVocabularyTermModal" ng-click="prepareNewTerm()">create a new term</button> <button class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editVocabularyTermModal" ng-click="prepareNewTerm()">create a new term</button>