Changeset 6043
- Timestamp:
- 02/24/15 16:58:55 (9 years ago)
- Location:
- SRUAggregator/trunk
- Files:
-
- 18 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
SRUAggregator/trunk/aggregator.yml
r5976 r6043 1 1 aggregatorParams: 2 CENTER_REGISTRY_URL: http://centres.clarin.eu/restxml/ 3 # additionalCQLEndpoints: 4 # - https://clarin.ids-mannheim.de/digibibsru-new 5 # - https://lux17.mpi.nl/ds/cqlsearch 6 # - http://www.meertens.knaw.nl/mimore/srucql/ 7 # - http://gysseling.corpus.taalbanknederlands.inl.nl/gyssru/ 8 # - http://brievenalsbuit.inl.nl/zbsru/ 9 # - http://corpus3.aac.ac.at/ddconsru/ 10 # - http://dspin.dwds.de:8088/ddc-sru/dta/ 2 # CENTER_REGISTRY_URL: http://centres.clarin.eu/restxml/ 3 additionalCQLEndpoints: 4 # - http://cqlservlet.mpi.nl/ 5 - http://dspin.dwds.de:8088/ddc-sru/dingler/ 6 - https://clarin.ids-mannheim.de/digibibsru-new 7 - https://lux17.mpi.nl/ds/cqlsearch 8 # - http://www.meertens.knaw.nl/mimore/srucql/ 9 # - http://gysseling.corpus.taalbanknederlands.inl.nl/gyssru/ 10 # - http://brievenalsbuit.inl.nl/zbsru/ 11 # - http://corpus3.aac.ac.at/ddconsru/ 12 # - http://dspin.dwds.de:8088/ddc-sru/dta/ 11 13 12 14 # AGGREGATOR_FILE_PATH: /data/fcsAggregator/fcsAggregatorCorpora.json … … 41 43 # Logger-specific levels. 42 44 loggers: 43 eu.clarin.sru.fcs.aggregator: WARN45 eu.clarin.sru.fcs.aggregator: INFO 44 46 eu.clarin.sru.client: WARN 45 47 -
SRUAggregator/trunk/pom.xml
r5976 r6043 8 8 <groupId>eu.clarin.sru.fcs</groupId> 9 9 <artifactId>Aggregator2</artifactId> 10 <version>2.0.0-alpha-2 0</version>10 <version>2.0.0-alpha-21</version> 11 11 <name>FCS Aggregator</name> 12 12 … … 26 26 <url>http://oss.sonatype.org/content/repositories/snapshots</url> 27 27 </repository> 28 <repository>29 <id>sardine-google-svn-repo</id>30 <snapshots>31 <enabled>true</enabled>32 </snapshots>33 <name>Sardine maven repo at Google Code</name>34 <url>http://sardine.googlecode.com/svn/maven/</url>35 </repository>36 28 </repositories> 37 29 … … 63 55 <artifactId>sru-client</artifactId> 64 56 <version>0.9.5-DEBUG</version> 57 <exclusions> 58 <exclusion> 59 <groupId>org.slf4j</groupId> 60 <artifactId>slf4j-api</artifactId> 61 </exclusion> 62 <exclusion> 63 <groupId>commons-codec</groupId> 64 <artifactId>commons-codec</artifactId> 65 </exclusion> 66 </exclusions> 65 67 </dependency> 66 68 … … 74 76 <artifactId>connectors</artifactId> 75 77 <version>1.0.6</version> 78 <exclusions> 79 <exclusion> 80 <groupId>com.sun.jersey</groupId> 81 <artifactId>jersey-client</artifactId> 82 </exclusion> 83 </exclusions> 76 84 </dependency> 77 85 <dependency> … … 89 97 <groupId>com.optimaize.languagedetector</groupId> 90 98 <artifactId>language-detector</artifactId> 91 <version>0.4</version> 99 <version>0.4</version> 100 <exclusions> 101 <exclusion> 102 <groupId>com.google.guava</groupId> 103 <artifactId>guava</artifactId> 104 </exclusion> 105 </exclusions> 92 106 </dependency> 93 107 94 <dependency>95 <groupId>com.googlecode.sardine</groupId>96 <artifactId>sardine</artifactId>97 <version>314</version>98 <type>jar</type>99 <exclusions>100 <exclusion>101 <groupId>org.apache.httpcomponents</groupId>102 <artifactId>httpcore</artifactId>103 </exclusion>104 <exclusion>105 <artifactId>commons-codec</artifactId>106 <groupId>commons-codec</groupId>107 </exclusion>108 </exclusions>109 </dependency>110 108 <dependency> 111 109 <groupId>org.apache.poi</groupId> 112 110 <artifactId>poi-ooxml</artifactId> 113 111 <version>3.11-beta2</version> 112 </dependency> 113 <dependency> 114 <groupId>com.sun.jersey</groupId> 115 <artifactId>jersey-client</artifactId> 116 <version>1.18.1</version> 117 <type>jar</type> 114 118 </dependency> 115 119 </dependencies> … … 130 134 </configuration> 131 135 <goals> 132 < !--<goal>enforce</goal>-->136 <goal>enforce</goal> 133 137 </goals> 134 138 </execution> -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/Aggregator.java
r5976 r6043 88 88 * @author edima 89 89 * 90 * TODO: Download search results as csv, excel, tcf, plain text91 *92 90 * TODO: Use weblicht with results 93 91 * 94 * TODO: Export search results to personal workspace as csv, excel, tcf, plain95 * text96 *97 92 * TODO: disable popups easily 98 * 99 * TODO: websockets 100 * 93 * 101 94 * TODO: atomic replace of cached corpora (file) 102 *103 * TODO: show multiple hits on the same result in multiple rows, linked visually104 95 * 105 96 * TODO: zoom into the results from a corpus, allow functionality only for 106 97 * the view (search for next set of results) 98 * 99 * TODO: fix search bug after going to stats 100 * 101 * TODO: Export search results to personal workspace as csv, excel, tcf, plain 102 * text: ask Marie/Wei about oauth ways to do that ndg oauth; ask Menzo, Willem, 103 * Twan (they did a test, it worked) 104 * 105 * TODO: websockets 106 * 107 * TODO: show multiple hits on the same result in multiple rows, linked visually 107 108 * 108 109 * TODO: optimise page load -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/lang/LanguagesISO693_3.java
r5931 r6043 28 28 public static class Language { 29 29 30 // code is ISO-639-3 (3 letters) while code_2 is ISO-639- 2(2 letters)31 String code , code_2, name;30 // code is ISO-639-3 (3 letters) while code_2 is ISO-639-1 (2 letters) 31 String code_3, code_1, name; 32 32 33 public Language(String code , String code_2, String name) {34 this.code = code;35 this.code_ 2 = code_2;33 public Language(String code_3, String code_1, String name) { 34 this.code_3 = code_3; 35 this.code_1 = code_1; 36 36 this.name = name; 37 37 } 38 38 } 39 39 40 private Map<String, Language> code ToLang = new HashMap<String, Language>();40 private Map<String, Language> code_3ToLang = new HashMap<String, Language>(); 41 41 private Map<String, Language> nameToLang = new HashMap<String, Language>(); 42 private Map<String, Language> code_ 2ToLang = new HashMap<String, Language>();42 private Map<String, Language> code_1ToLang = new HashMap<String, Language>(); 43 43 44 44 private LanguagesISO693_3() { … … 53 53 continue; 54 54 } 55 String code = toks[0].trim();56 String code_ 2= toks[3].trim().isEmpty() ? null : toks[3].trim();57 if (code_ 2 != null && code_2.length() != 2) {58 throw new RuntimeException("bad code_2 code: " + code_2);55 String code_3 = toks[0].trim(); 56 String code_1 = toks[3].trim().isEmpty() ? null : toks[3].trim(); 57 if (code_1 != null && code_1.length() != 2) { 58 throw new RuntimeException("bad ISO-639-1 code: " + code_1); 59 59 } 60 60 String name = toks[6].trim(); 61 Language l = new Language(code , code_2, name);62 code ToLang.put(code, l);63 if (code_ 2!= null) {64 code_ 2ToLang.put(code_2, l);61 Language l = new Language(code_3, code_1, name); 62 code_3ToLang.put(code_3, l); 63 if (code_1 != null) { 64 code_1ToLang.put(code_1, l); 65 65 } 66 66 nameToLang.put(name, l); … … 73 73 ObjectWriter ow = new ObjectMapper().writerWithDefaultPrettyPrinter(); 74 74 try { 75 System.out.println(ow.writeValueAsString(code ToLang));75 System.out.println(ow.writeValueAsString(code_3ToLang)); 76 76 } catch (JsonProcessingException ex) { 77 77 } … … 85 85 } 86 86 87 public Set<String> getCodes () {88 return code ToLang.keySet();87 public Set<String> getCodes_3() { 88 return code_3ToLang.keySet(); 89 89 } 90 90 91 public String code ForCode639_2(String code639_2) {92 if (code639_ 2== null) {91 public String code_3ForCode_1(String code639_1) { 92 if (code639_1 == null) { 93 93 return null; 94 94 } 95 Language l = code_ 2ToLang.get(code639_2);95 Language l = code_1ToLang.get(code639_1); 96 96 if (l == null) { 97 log.error("Unknown 639-2 code: " + code639_2);97 log.error("Unknown ISO-639-1 code: " + code639_1); 98 98 return null; 99 99 } 100 return l.code ;100 return l.code_3; 101 101 } 102 102 103 public String codeForName(String name) { 103 public String code_1ForCode_3(String code639_3) { 104 if (code639_3 == null) { 105 return null; 106 } 107 Language l = code_3ToLang.get(code639_3); 108 if (l == null) { 109 log.error("Unknown ISO-639-3 code: " + code639_3); 110 return null; 111 } 112 return l.code_1; 113 } 114 115 public String code_3ForName(String name) { 104 116 Language l = nameToLang.get(name); 105 117 if (l == null) { … … 107 119 return null; 108 120 } 109 return l.code ;121 return l.code_3; 110 122 } 111 123 112 public String nameForCode (String code) {113 Language l = code ToLang.get(code);124 public String nameForCode_3(String code) { 125 Language l = code_3ToLang.get(code); 114 126 if (l == null) { 115 127 log.error("Unknown language code: " + code); -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/rest/DataTransfer.java
r5937 r6043 1 package eu.clarin.sru.fcs.aggregator. search;1 package eu.clarin.sru.fcs.aggregator.rest; 2 2 3 import com.googlecode.sardine.Sardine;4 import com.googlecode.sardine.SardineFactory;5 import com.googlecode.sardine.impl.SardineException;6 3 import com.sun.jersey.api.client.Client; 7 4 import com.sun.jersey.api.client.ClientResponse; … … 10 7 import com.sun.jersey.api.client.config.DefaultClientConfig; 11 8 import java.util.logging.*; 12 import java.io.IOException;13 9 import java.text.SimpleDateFormat; 14 10 import java.util.Date; … … 27 23 private static final String WSPACE_AGGREGATOR_DIR = "aggregator_results/"; 28 24 private static final String DROP_OFF_URL = "http://ws1-clarind.esc.rzg.mpg.de/drop-off/storage/"; 29 30 static void uploadToPW(String user, String pass, byte[] bytes, String mimeType, String fileExtention) {31 try {32 Sardine sardine = SardineFactory.begin();33 sardine.setCredentials(user, pass);34 String outputDir = WSPACE_SERVER_URL + WSPACE_WEBDAV_DIR + WSPACE_AGGREGATOR_DIR;35 if (!sardine.exists(outputDir)) {36 sardine.createDirectory(outputDir);37 }38 Date currentDate = new Date();39 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");40 Random generator = new Random();41 int rn1 = generator.nextInt(1000000000);42 String createdFilePath = outputDir + format.format(currentDate) + "-" + rn1 + fileExtention;43 while (sardine.exists(createdFilePath)) {44 rn1 = generator.nextInt(1000000000);45 createdFilePath = outputDir + format.format(currentDate) + "-" + rn1 + fileExtention;46 }47 sardine.put(createdFilePath, bytes, mimeType);48 // "Export complete!\nCreated file:\n" + createdFilePath49 } catch (SardineException ex) {50 LOGGER.log(Level.SEVERE, "Error accessing " + WSPACE_SERVER_URL + WSPACE_WEBDAV_DIR, ex);51 //"Wrong name or password!"52 } catch (IOException ex) {53 LOGGER.log(Level.SEVERE, "Error exporting {0} {1} {2}", new String[]{fileExtention, ex.getClass().getName(), ex.getMessage()});54 //"Sorry, export error!"55 }56 }57 25 58 26 static String uploadToDropOff(byte[] bytes, String mimeType, String fileExtention) { -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/rest/RestService.java
r5976 r6043 13 13 import eu.clarin.sru.fcs.aggregator.search.Search; 14 14 import eu.clarin.sru.fcs.aggregator.lang.LanguagesISO693_3; 15 import eu.clarin.sru.fcs.aggregator.search.ExportException; 15 16 import eu.clarin.sru.fcs.aggregator.search.Exports; 16 17 import java.io.IOException; … … 21 22 import java.util.Map; 22 23 import java.util.Set; 24 import java.util.logging.Level; 25 import java.util.logging.Logger; 23 26 import javax.servlet.ServletContext; 24 27 import javax.servlet.http.HttpServletRequest; … … 33 36 import javax.ws.rs.core.MediaType; 34 37 import javax.ws.rs.core.Response; 38 import opennlp.tools.tokenize.TokenizerModel; 35 39 import org.slf4j.LoggerFactory; 36 40 … … 42 46 @Path("/") 43 47 public class RestService { 48 44 49 private static final String EXPORT_FILENAME_PREFIX = "ClarinDFederatedContentSearch-"; 45 50 private static final String TCF_MEDIA_TYPE = "text/tcf+xml"; 46 51 private static final String EXCEL_MEDIA_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 52 private static final String SEARCH_RESULTS_ENCODING = "UTF-8"; 47 53 48 54 private static final org.slf4j.Logger log = LoggerFactory.getLogger(RestService.class); … … 82 88 put("isScan", true); 83 89 put("institutions", scan.getInstitutions()); 90 put("date", scan.getDate()); 84 91 } 85 92 }); … … 91 98 put("isScan", false); 92 99 put("institutions", search.getInstitutions()); 100 put("date", scan.getDate()); 93 101 } 94 102 }); … … 105 113 log.info("get language codes", codes); 106 114 for (String code : codes) { 107 String name = LanguagesISO693_3.getInstance().nameForCode (code);115 String name = LanguagesISO693_3.getInstance().nameForCode_3(code); 108 116 languages.put(code, name != null ? name : code); 109 117 } … … 184 192 } 185 193 186 194 if (format == null || format.trim().isEmpty() || format.trim().equals("text")) { 187 195 String text = Exports.getExportText(search.getResults()); 188 196 return download(text, MediaType.TEXT_PLAIN, search.getQuery() + ".txt"); … … 215 223 .build(); 216 224 } 225 226 @GET 227 @Path("search/{id}/toWeblicht") 228 public Response sendSearchResultsToWeblicht(@PathParam("id") Long searchId, 229 @QueryParam("format") String format) throws Exception { 230 Search search = Aggregator.getInstance().getSearchById(searchId); 231 if (search == null) { 232 return Response.status(Response.Status.NOT_FOUND).entity("Search job not found").build(); 233 } 234 235 String url = null; 236 if (format == null || format.isEmpty() || format.trim().equals("text")) { 237 String text = Exports.getExportText(search.getResults()); 238 if (text != null) { 239 byte[] bytes = text.getBytes(SEARCH_RESULTS_ENCODING); 240 url = DataTransfer.uploadToDropOff(bytes, "text/plan", ".txt"); 241 } 242 } else if (format.equals("tokens")) { 243 byte[] bytes = Exports.getExportTokenizedTCF( 244 search.getResults(), search.getSearchLanguage(), 245 Aggregator.getInstance().getTokenizerModel()); 246 if (bytes != null) { 247 url = DataTransfer.uploadToDropOff(bytes, "text/tcf+xml", ".tcf"); 248 } 249 } else { 250 return Response.status(400).entity("incorrect format parameter").build(); 251 } 252 253 return url == null ? Response.status(503).entity("error while exporting to weblicht").build() 254 : Response.ok().entity(url).build(); 255 } 217 256 } -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/scan/Corpus.java
r5957 r6043 102 102 103 103 public void addLanguage(String language) { 104 if (LanguagesISO693_3.getInstance().getCodes ().contains(language)) {104 if (LanguagesISO693_3.getInstance().getCodes_3().contains(language)) { 105 105 this.languages.add(language); 106 106 } else { 107 String code = LanguagesISO693_3.getInstance().code ForName(language);107 String code = LanguagesISO693_3.getInstance().code_3ForName(language); 108 108 this.languages.add(code == null ? language : code); 109 109 } -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/scan/ScanCrawler.java
r5976 r6043 368 368 } else if (infoNode.getNodeType() == Node.ELEMENT_NODE && infoNode.getLocalName().equals("Title")) { 369 369 Element element = (Element) infoNode; 370 String descr = infoNode.getTextContent().replaceAll("<br/>", " "); 371 descr = descr.replaceAll("<br/>", " "); 372 descr = descr.replaceAll("[\t\n\r ]+", " "); 373 c.setTitle(descr.trim()); 370 String x = cleanup(infoNode.getTextContent()); 371 if (!x.isEmpty()) { 372 c.setTitle(x); 373 if ("en".equals(element.getAttribute("xml:lang"))) { 374 enTitle = x; 375 } 376 } 377 } else if (infoNode.getNodeType() == Node.ELEMENT_NODE && infoNode.getLocalName().equals("Description")) { 378 Element element = (Element) infoNode; 379 String x = cleanup(infoNode.getTextContent()); 380 c.setDescription(x); 374 381 //String lang = element.getAttributeNS("http://clarin.eu/fcs/1.0/resource-info", "lang"); 375 382 //System.out.println("ATTRIBUTE LANG: " + lang); 376 383 if ("en".equals(element.getAttribute("xml:lang"))) { 377 enTitle = c.getDescription(); 378 } 379 } else if (infoNode.getNodeType() == Node.ELEMENT_NODE && infoNode.getLocalName().equals("Description")) { 380 Element element = (Element) infoNode; 381 String descr = infoNode.getTextContent().replaceAll("<br/>", " "); 382 descr = descr.replaceAll("<br/>", " "); 383 descr = descr.replaceAll("[\t\n\r ]+", " "); 384 c.setDescription(descr.trim()); 385 //String lang = element.getAttributeNS("http://clarin.eu/fcs/1.0/resource-info", "lang"); 386 //System.out.println("ATTRIBUTE LANG: " + lang); 387 if ("en".equals(element.getAttribute("xml:lang"))) { 388 enDescription = c.getDescription(); 389 } 390 } 391 } 392 // title in Engish has priority 384 enDescription = x; 385 } 386 } 387 } 388 // title in English has priority 393 389 if (enTitle != null && !enTitle.isEmpty()) { 394 390 c.setTitle(enTitle); 395 391 } 396 // description in Eng ish has priority392 // description in English has priority 397 393 if (enDescription != null && !enDescription.isEmpty()) { 398 394 c.setDescription(enDescription); … … 400 396 } 401 397 } 398 399 private static String cleanup(String x) { 400 if (x == null) { 401 return ""; 402 } 403 x = x.replaceAll("<br/>", " "); 404 x = x.replaceAll("<br/>", " "); 405 x = x.replaceAll("[\t\n\r ]+", " "); 406 return x.trim(); 407 } 402 408 } -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/scan/Statistics.java
r5971 r6043 4 4 import java.util.ArrayList; 5 5 import java.util.Collections; 6 import java.util.Date; 6 7 import java.util.HashMap; 7 8 import java.util.List; … … 109 110 private final Object lock = new Object(); 110 111 112 Date date = new Date(); 113 114 public Date getDate() { 115 return date; 116 } 117 111 118 // institution to endpoint to statistics_per_endpoint map 112 119 Map<String, Map<String, EndpointStats>> institutions … … 186 193 return stats; 187 194 } 195 188 196 } -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/search/ExportException.java
r5718 r6043 11 11 } 12 12 13 public ExportException(String message) { 14 super(message); 15 } 13 16 } -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/search/Exports.java
r5957 r6043 2 2 3 3 import eu.clarin.sru.fcs.aggregator.lang.LanguagesISO693_2; 4 import eu.clarin.sru.fcs.aggregator.lang.LanguagesISO693_3; 4 5 import eu.clarin.weblicht.wlfxb.io.WLDObjector; 5 6 import eu.clarin.weblicht.wlfxb.io.WLFormatException; … … 12 13 import java.io.IOException; 13 14 import java.util.ArrayList; 15 import java.util.Collections; 14 16 import java.util.HashSet; 15 17 import java.util.List; … … 225 227 String searchLanguage, TokenizerModel tokenizerModel) throws ExportException { 226 228 StringBuilder text = new StringBuilder(); 227 Set<String> resultsLangs = new HashSet<String>(); 228 if (resultsProcessed != null && !resultsProcessed.isEmpty()) { 229 for (Result result : resultsProcessed) { 230 resultsLangs.addAll(result.getCorpus().getLanguages()); 231 for (Kwic kwic : result.getKwics()) { 232 text.append(kwic.getLeft()); 233 text.append(" "); 234 text.append(kwic.getKeyword()); 235 text.append(" "); 236 text.append(kwic.getRight()); 237 text.append("\n"); 229 if (resultsProcessed != null && !resultsProcessed.isEmpty()) { 230 for (Result result : resultsProcessed) { 231 for (Kwic kwic : result.getKwics()) { 232 int i = kwic.getFragments().size() - 1; 233 for (Kwic.TextFragment tf : kwic.getFragments()) { 234 text.append(tf.text); 235 if (i > 0) { 236 text.append(" "); 237 } 238 i--; 239 } 240 text.append("\n"); 238 241 } 239 242 } … … 244 247 } else { 245 248 WLData data; 246 MetaData md = new MetaData(); 247 String resultsLang = "unknown"; 248 if (resultsLangs.size() == 1) { 249 resultsLang = resultsLangs.iterator().next(); 250 String code2 = LanguagesISO693_2.getInstance().langForCode(resultsLang).getCode_639_1(); 251 if (code2 != null) { 252 resultsLang = code2; 253 } 254 } else if (!searchLanguage.equals("anylang")) { 255 String code2 = LanguagesISO693_2.getInstance().langForCode(resultsLang).getCode_639_1(); 256 if (code2 == null) { 257 resultsLang = searchLanguage; 258 } else { 259 resultsLang = code2; 260 } 261 } 262 TextCorpusStored tc = new TextCorpusStored(resultsLang); 249 MetaData md = new MetaData(); 250 String languageCode = LanguagesISO693_3.getInstance().code_1ForCode_3(searchLanguage); 251 TextCorpusStored tc = new TextCorpusStored(languageCode); 263 252 tc.createTextLayer().addText(text.toString()); 264 253 addTokensSentencesMatches(resultsProcessed, tc, tokenizerModel); … … 276 265 277 266 private static void addTokensSentencesMatches(List<Result> resultsProcessed, TextCorpusStored tc, TokenizerModel model) { 278 if (model == null || !tc.getLanguage().equals("de")) {267 if (model == null || !"de".equals(tc.getLanguage())) { 279 268 return; 280 269 } -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/search/Kwic.java
r5931 r6043 64 64 } 65 65 66 String code_iso639_ 2= Aggregator.getInstance().detectLanguage(hits.getText());67 language = code_iso639_ 2== null ? null68 : LanguagesISO693_3.getInstance().code ForCode639_2(code_iso639_2);66 String code_iso639_1 = Aggregator.getInstance().detectLanguage(hits.getText()); 67 language = code_iso639_1 == null ? null 68 : LanguagesISO693_3.getInstance().code_3ForCode_1(code_iso639_1); 69 69 } 70 70 -
SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/search/Search.java
r5976 r6043 17 17 import java.util.Random; 18 18 import java.util.concurrent.atomic.AtomicLong; 19 import java.util.logging.Level;20 import java.util.logging.Logger;21 import opennlp.tools.tokenize.TokenizerModel;22 19 import org.slf4j.LoggerFactory; 23 20 … … 68 65 ? ClarinFCSRecordData.LEGACY_RECORD_SCHEMA 69 66 : ClarinFCSRecordData.RECORD_SCHEMA); 70 searchRequest.setQuery( "\"" + searchString + "\"");67 searchRequest.setQuery(searchString); 71 68 searchRequest.setStartRecord(startRecord); 72 69 if (corpus.getHandle() != null) { … … 149 146 } 150 147 151 private void exportPWText(String user, String pass) {152 byte[] bytes = null;153 try {154 String text = Exports.getExportText(results);155 if (text != null) {156 bytes = text.getBytes(SEARCH_RESULTS_ENCODING);157 }158 } catch (Exception ex) {159 Logger.getLogger(Search.class.getName()).log(Level.SEVERE, null, ex);160 }161 if (bytes != null) {162 DataTransfer.uploadToPW(user, pass, bytes, "text/plan", ".txt");163 }164 }165 166 private String useWebLichtOnText() {167 String url = null;168 try {169 String text = Exports.getExportText(results);170 if (text != null) {171 byte[] bytes = text.getBytes(SEARCH_RESULTS_ENCODING);172 url = DataTransfer.uploadToDropOff(bytes, "text/plan", ".txt");173 }174 } catch (Exception ex) {175 Logger.getLogger(Search.class.getName()).log(Level.SEVERE, null, ex);176 }177 return url;178 }179 180 private String useWebLichtOnToks(TokenizerModel tokenizerModel) throws ExportException {181 String url = null;182 byte[] bytes = Exports.getExportTokenizedTCF(results, searchLanguage, tokenizerModel);183 if (bytes != null) {184 url = DataTransfer.uploadToDropOff(bytes, "text/tcf+xml", ".tcf");185 }186 return url;187 }188 189 private void exportPWExcel(String user, String pass) throws ExportException {190 byte[] bytes = Exports.getExportExcel(results);191 if (bytes != null) {192 DataTransfer.uploadToPW(user, pass, bytes, "application/vnd.ms-excel", ".xls");193 }194 }195 196 private void exportPWTCF(String user, String pass, TokenizerModel tokenizerModel) throws ExportException {197 byte[] bytes = Exports.getExportTokenizedTCF(results, searchLanguage, tokenizerModel);198 if (bytes != null) {199 DataTransfer.uploadToPW(user, pass, bytes, "text/tcf+xml", ".tcf");200 }201 }202 203 private void exportPWCSV(String user, String pass) {204 String csv = Exports.getExportCSV(results, ";");205 if (csv != null) {206 DataTransfer.uploadToPW(user, pass, csv.getBytes(), "text/csv", ".csv");207 }208 }209 210 148 public void shutdown() { 211 149 // nothing to do -
SRUAggregator/trunk/src/main/resources/assets/js/corpora.js
r5959 r6043 12 12 13 13 ///////////////////////////////// 14 15 var SearchCorpusBox = React.createClass({displayName: 'SearchCorpusBox',16 propTypes: {17 search: PT.func.isRequired,18 },19 20 getInitialState: function () {21 return {22 query: ""23 };24 },25 26 handleChange: function(event) {27 var query = event.target.value;28 this.setState({query: query});29 30 if (query.length === 0 || 2 <= query.length) {31 this.props.search(query);32 }33 event.stopPropagation();34 },35 36 handleKey: function(event) {37 if (event.keyCode==13) {38 this.props.search(event.target.value);39 }40 },41 42 render: function() {43 return React.createElement("div", {className: "form-group"},44 React.createElement("input", {className: "form-control search search-collection", type: "text",45 value: this.state.query, placeholder: "Search for collection",46 onChange: this.handleChange})47 );48 }49 });50 14 51 15 var CorpusView = window.MyAggregator.CorpusView = React.createClass({displayName: 'CorpusView', … … 281 245 }); 282 246 247 var SearchCorpusBox = React.createClass({displayName: 'SearchCorpusBox', 248 propTypes: { 249 search: PT.func.isRequired, 250 }, 251 252 getInitialState: function () { 253 return { 254 query: "" 255 }; 256 }, 257 258 handleChange: function(event) { 259 var query = event.target.value; 260 this.setState({query: query}); 261 262 if (query.length === 0 || 2 <= query.length) { 263 this.props.search(query); 264 } 265 event.stopPropagation(); 266 }, 267 268 handleKey: function(event) { 269 if (event.keyCode==13) { 270 this.props.search(event.target.value); 271 } 272 }, 273 274 render: function() { 275 return React.createElement("div", {className: "form-group"}, 276 React.createElement("input", {className: "form-control search search-collection", type: "text", 277 value: this.state.query, placeholder: "Search for collection", 278 onChange: this.handleChange}) 279 ); 280 } 281 }); 282 283 283 })(); -
SRUAggregator/trunk/src/main/resources/assets/js/corpora.jsx
r5959 r6043 12 12 13 13 ///////////////////////////////// 14 15 var SearchCorpusBox = React.createClass({16 propTypes: {17 search: PT.func.isRequired,18 },19 20 getInitialState: function () {21 return {22 query: ""23 };24 },25 26 handleChange: function(event) {27 var query = event.target.value;28 this.setState({query: query});29 30 if (query.length === 0 || 2 <= query.length) {31 this.props.search(query);32 }33 event.stopPropagation();34 },35 36 handleKey: function(event) {37 if (event.keyCode==13) {38 this.props.search(event.target.value);39 }40 },41 42 render: function() {43 return <div className="form-group">44 <input className="form-control search search-collection" type="text"45 value={this.state.query} placeholder="Search for collection"46 onChange={this.handleChange} />47 </div>;48 }49 });50 14 51 15 var CorpusView = window.MyAggregator.CorpusView = React.createClass({ … … 281 245 }); 282 246 247 var SearchCorpusBox = React.createClass({ 248 propTypes: { 249 search: PT.func.isRequired, 250 }, 251 252 getInitialState: function () { 253 return { 254 query: "" 255 }; 256 }, 257 258 handleChange: function(event) { 259 var query = event.target.value; 260 this.setState({query: query}); 261 262 if (query.length === 0 || 2 <= query.length) { 263 this.props.search(query); 264 } 265 event.stopPropagation(); 266 }, 267 268 handleKey: function(event) { 269 if (event.keyCode==13) { 270 this.props.search(event.target.value); 271 } 272 }, 273 274 render: function() { 275 return <div className="form-group"> 276 <input className="form-control search search-collection" type="text" 277 value={this.state.query} placeholder="Search for collection" 278 onChange={this.handleChange} /> 279 </div>; 280 } 281 }); 282 283 283 })(); -
SRUAggregator/trunk/src/main/resources/assets/js/main.js
r5976 r6043 3 3 "use strict"; 4 4 5 var VERSION = "VERSION 2.0.0.α2 0";5 var VERSION = "VERSION 2.0.0.α21"; 6 6 var URLROOT = "/Aggregator-testing"; 7 7 … … 13 13 var Main = React.createClass({displayName: 'Main', 14 14 componentWillMount: function() { 15 routeFromLocation (this);15 routeFromLocation.bind(this); 16 16 }, 17 17 … … 102 102 } 103 103 this.setState({navbarPageFn: pageFn}); 104 console.log("new page: " + document.location + ", name: " + pageFnName);104 // console.log("new page: " + document.location + ", name: " + pageFnName); 105 105 } 106 106 }, … … 193 193 success: function(json, textStatus, jqXHR) { 194 194 this.setState({stats: json}); 195 console.log("stats:", json);195 // console.log("stats:", json); 196 196 }.bind(this), 197 197 }); … … 294 294 295 295 renderInstitution: function(isScan, inst) { 296 return React.createElement("div", {style: {margin Bottom:30}, key: inst[0]},296 return React.createElement("div", {style: {marginTop:30}, key: inst[0]}, 297 297 React.createElement("h4", null, inst[0]), 298 298 React.createElement("div", {style: {marginLeft:20}}, " ", _.pairs(inst[1]).map(this.renderEndpoint.bind(this, isScan)) ) … … 302 302 renderStatistics: function(stats) { 303 303 return React.createElement("div", {className: "container statistics", style: {marginTop:20}}, 304 React.createElement("ul", {className: "list-inline list-unstyled"}, 305 stats.maxConcurrentScanRequestsPerEndpoint ? 306 React.createElement("li", null, "max concurrent scan requests per endpoint:", " ", 307 React.createElement("kbd", null, stats.maxConcurrentScanRequestsPerEndpoint), "," 308 ) : false, 304 React.createElement("div", null, 305 React.createElement("div", null, "Start date: ", new Date(stats.date).toLocaleString()), 306 stats.isScan ? 307 React.createElement("div", null, "Max concurrent scan requests per endpoint:", " ", 308 React.createElement("kbd", null, stats.maxConcurrentScanRequestsPerEndpoint) 309 ) 310 : 311 React.createElement("div", null, "Max concurrent search requests per endpoint:", " ", 312 React.createElement("kbd", null, stats.maxConcurrentSearchRequestsPerEndpoint) 313 ), 309 314 310 stats.maxConcurrentSearchRequestsPerEndpoint ? 311 React.createElement("li", null, "max concurrent search requests per endpoint:", " ", 312 React.createElement("kbd", null, stats.maxConcurrentSearchRequestsPerEndpoint), "," 313 ) : false, 314 315 React.createElement("li", null, "timeout:", " ", React.createElement("kbd", null, stats.timeout, " seconds")) 315 React.createElement("div", null, "Timeout: ", " ", React.createElement("kbd", null, stats.timeout, " seconds")) 316 316 ), 317 317 React.createElement("div", null, " ", _.pairs(stats.institutions).map(this.renderInstitution.bind(this, stats.isScan)), " ") … … 508 508 } 509 509 510 var routeFromLocation = function(com) { 510 var routeFromLocation = function() { 511 // console.log("routeFromLocation: " + document.location); 512 if (!this) throw "routeFromLocation must be bound to main"; 511 513 var path = window.location.pathname.split('/'); 512 514 if (path.length === 3) { 513 515 var p = path[2]; 514 516 if (p === 'help') { 515 com.toHelp(false);517 this.toHelp(false); 516 518 } else if (p === 'about') { 517 com.toAbout(false);519 this.toAbout(false); 518 520 } else if (p === 'stats') { 519 com.toStatistics(false);521 this.toStatistics(false); 520 522 } else { 521 com.toAggregator(false);523 this.toAggregator(false); 522 524 } 523 525 } else { 524 com.toAggregator(false);526 this.toAggregator(false); 525 527 } 526 528 }; … … 529 531 React.render(React.createElement(Footer, null), document.getElementById('footer') ); 530 532 531 window.onpopstate = function(event) { 532 console.log("popped location: " + document.location + ", state: " + JSON.stringify(event.state)); 533 routeFromLocation(main); 534 }; 535 536 window.main = main; 533 window.onpopstate = routeFromLocation.bind(main); 534 535 routeFromLocation.bind(main)(); 537 536 538 537 })(); … … 544 543 545 544 546 547 548 549 550 551 552 553 554 555 556 557 -
SRUAggregator/trunk/src/main/resources/assets/js/main.jsx
r5976 r6043 3 3 "use strict"; 4 4 5 var VERSION = "VERSION 2.0.0.α2 0";5 var VERSION = "VERSION 2.0.0.α21"; 6 6 var URLROOT = "/Aggregator-testing"; 7 7 … … 13 13 var Main = React.createClass({ 14 14 componentWillMount: function() { 15 routeFromLocation (this);15 routeFromLocation.bind(this); 16 16 }, 17 17 … … 102 102 } 103 103 this.setState({navbarPageFn: pageFn}); 104 console.log("new page: " + document.location + ", name: " + pageFnName);104 // console.log("new page: " + document.location + ", name: " + pageFnName); 105 105 } 106 106 }, … … 193 193 success: function(json, textStatus, jqXHR) { 194 194 this.setState({stats: json}); 195 console.log("stats:", json);195 // console.log("stats:", json); 196 196 }.bind(this), 197 197 }); … … 294 294 295 295 renderInstitution: function(isScan, inst) { 296 return <div style={{margin Bottom:30}} key={inst[0]}>296 return <div style={{marginTop:30}} key={inst[0]}> 297 297 <h4>{inst[0]}</h4> 298 298 <div style={{marginLeft:20}}> {_.pairs(inst[1]).map(this.renderEndpoint.bind(this, isScan)) }</div> … … 302 302 renderStatistics: function(stats) { 303 303 return <div className="container statistics" style={{marginTop:20}}> 304 <ul className='list-inline list-unstyled'> 305 { stats.maxConcurrentScanRequestsPerEndpoint ? 306 <li>max concurrent scan requests per endpoint:{" "} 307 <kbd>{stats.maxConcurrentScanRequestsPerEndpoint}</kbd>, 308 </li> : false 304 <div> 305 <div>Start date: {new Date(stats.date).toLocaleString()}</div> 306 { stats.isScan ? 307 <div>Max concurrent scan requests per endpoint:{" "} 308 <kbd>{stats.maxConcurrentScanRequestsPerEndpoint}</kbd> 309 </div> 310 : 311 <div>Max concurrent search requests per endpoint:{" "} 312 <kbd>{stats.maxConcurrentSearchRequestsPerEndpoint}</kbd> 313 </div> 309 314 } 310 { stats.maxConcurrentSearchRequestsPerEndpoint ? 311 <li>max concurrent search requests per endpoint:{" "} 312 <kbd>{stats.maxConcurrentSearchRequestsPerEndpoint}</kbd>, 313 </li> : false 314 } 315 <li>timeout:{" "}<kbd>{stats.timeout} seconds</kbd></li> 316 </ul> 315 <div>Timeout: {" "}<kbd>{stats.timeout} seconds</kbd></div> 316 </div> 317 317 <div> { _.pairs(stats.institutions).map(this.renderInstitution.bind(this, stats.isScan)) } </div> 318 318 </div> … … 508 508 } 509 509 510 var routeFromLocation = function(com) { 510 var routeFromLocation = function() { 511 // console.log("routeFromLocation: " + document.location); 512 if (!this) throw "routeFromLocation must be bound to main"; 511 513 var path = window.location.pathname.split('/'); 512 514 if (path.length === 3) { 513 515 var p = path[2]; 514 516 if (p === 'help') { 515 com.toHelp(false);517 this.toHelp(false); 516 518 } else if (p === 'about') { 517 com.toAbout(false);519 this.toAbout(false); 518 520 } else if (p === 'stats') { 519 com.toStatistics(false);521 this.toStatistics(false); 520 522 } else { 521 com.toAggregator(false);523 this.toAggregator(false); 522 524 } 523 525 } else { 524 com.toAggregator(false);526 this.toAggregator(false); 525 527 } 526 528 }; … … 529 531 React.render(<Footer />, document.getElementById('footer') ); 530 532 531 window.onpopstate = function(event) { 532 console.log("popped location: " + document.location + ", state: " + JSON.stringify(event.state)); 533 routeFromLocation(main); 534 }; 535 536 window.main = main; 533 window.onpopstate = routeFromLocation.bind(main); 534 535 routeFromLocation.bind(main)(); 537 536 538 537 })(); … … 544 543 545 544 546 547 548 549 550 551 552 553 554 555 556 557 -
SRUAggregator/trunk/src/main/resources/assets/js/search.js
r5971 r6043 62 62 corpus.selected = true; // selected in the corpus view 63 63 corpus.expanded = false; // not expanded in the corpus view 64 corpus.priority = 1; // priority in corpus view64 corpus.priority = 1; // used for ordering search results in corpus view 65 65 corpus.index = index; // original order, used for stable sort 66 66 }); … … 164 164 }, 165 165 166 timeout: 0,167 166 nohits: { 168 167 requests: [], … … 182 181 183 182 searchId: null, 184 hits: this.nohits, 183 timeout: 0, 184 hits: this.nohits, 185 185 }; 186 186 }, … … 195 195 url: 'rest/corpora', 196 196 success: function(json, textStatus, jqXHR) { 197 this.setState({corpora : new Corpora(json, this.updateCorpora)}); 197 if (this.isMounted()) { 198 this.setState({corpora : new Corpora(json, this.updateCorpora)}); 199 } 198 200 }.bind(this), 199 201 }); … … 204 206 url: 'rest/languages', 205 207 success: function(json, textStatus, jqXHR) { 206 this.setState({languageMap : json}); 208 if (this.isMounted()) { 209 this.setState({languageMap : json}); 210 } 207 211 }.bind(this), 208 212 }); … … 233 237 success: function(searchId, textStatus, jqXHR) { 234 238 // console.log("search ["+query+"] ok: ", searchId, jqXHR); 235 this.setState({searchId : searchId});236 this.timeout = 250;237 setTimeout(this.refreshSearchResults, this.timeout);239 var timeout = 250; 240 setTimeout(this.refreshSearchResults, timeout); 241 this.setState({ searchId: searchId, timeout: timeout }); 238 242 }.bind(this), 239 243 }); … … 241 245 242 246 refreshSearchResults: function() { 243 if (!this.state.searchId ) {247 if (!this.state.searchId || !this.isMounted()) { 244 248 return; 245 249 } … … 247 251 url: 'rest/search/'+this.state.searchId, 248 252 success: function(json, textStatus, jqXHR) { 253 var timeout = this.state.timeout; 249 254 if (json.requests.length > 0) { 250 if (t his.timeout < 10000) {251 t his.timeout = 1.5 * this.timeout;255 if (timeout < 10000) { 256 timeout = 1.5 * timeout; 252 257 } 253 setTimeout(this.refreshSearchResults, t his.timeout);254 // console.log("new search in: " + this.timeout + "ms");258 setTimeout(this.refreshSearchResults, timeout); 259 // console.log("new search in: " + this.timeout + "ms"); 255 260 } else { 256 261 console.log("search ended; hits:", json); 257 262 } 258 this.setState({ hits:json});263 this.setState({ hits: json, timeout: timeout }); 259 264 }.bind(this), 260 265 }); … … 656 661 }, 657 662 658 renderToolbox: function() {659 if (this.props.requests.length > 0) {660 return false;661 }662 return React.createElement("div", {className: "toolbox float-left"},663 React.createElement("a", {className: "btn btn-default", href: this.props.getDownloadLink("text")},664 React.createElement("span", {className: "glyphicon glyphicon-download-alt", 'aria-hidden': "true"}), " Download"665 )666 );667 },668 669 663 renderProgressBar: function() { 670 664 var percents = 100 * this.props.results.length / (this.props.requests.length + this.props.results.length); … … 693 687 }, 694 688 695 renderKwicCheckbox: function() { 696 return React.createElement("div", {className: "float-right", style: {marginRight:17}}, 697 React.createElement("div", {className: "btn-group", style: {display:"inline-block"}}, 698 React.createElement("label", {forHtml: "inputKwic", className: "btn-default"}, 699 this.state.displayKwic ? 700 React.createElement("input", {id: "inputKwic", type: "checkbox", value: "kwic", checked: true, onChange: this.toggleKwic}) : 701 React.createElement("input", {id: "inputKwic", type: "checkbox", value: "kwic", onChange: this.toggleKwic}), 702 703 "Â " + ' ' + 704 "Display as Key Word In Context" 689 renderDownloadLinks: function() { 690 return ( 691 React.createElement("div", {className: "dropdown"}, 692 React.createElement("button", {className: "btn btn-default", 'aria-expanded': "false", 'data-toggle': "dropdown"}, 693 React.createElement("span", {className: "glyphicon glyphicon-download-alt", 'aria-hidden': "true"}), 694 " ", " Download ", " ", 695 React.createElement("span", {className: "caret"}) 696 ), 697 React.createElement("ul", {className: "dropdown-menu"}, 698 React.createElement("li", null, " ", React.createElement("a", {href: this.props.getDownloadLink("csv")}, 699 " ", " As CSV file")), 700 React.createElement("li", null, " ", React.createElement("a", {href: this.props.getDownloadLink("excel")}, 701 " ", " As Excel file")), 702 React.createElement("li", null, " ", React.createElement("a", {href: this.props.getDownloadLink("tcf")}, 703 " ", " As TCF file")), 704 React.createElement("li", null, " ", React.createElement("a", {href: this.props.getDownloadLink("text")}, 705 " ", " As Plain Text file")) 706 ) 707 ) 708 ); 709 }, 710 711 renderToolbox: function(hits) { 712 if (hits <= 0) { 713 return false; 714 } 715 return React.createElement("div", {key: "-toolbox-", style: {marginBottom:10}}, 716 React.createElement("div", {className: "toolbox float-left inline"}, 717 this.renderDownloadLinks() 718 ), 719 React.createElement("div", {className: "float-right inline", style: {marginTop:15}}, 720 React.createElement("div", {className: "btn-group", style: {display:"inline-block"}}, 721 React.createElement("label", {forHtml: "inputKwic", className: "btn-default"}, 722 this.state.displayKwic ? 723 React.createElement("input", {id: "inputKwic", type: "checkbox", value: "kwic", checked: true, onChange: this.toggleKwic}) : 724 React.createElement("input", {id: "inputKwic", type: "checkbox", value: "kwic", onChange: this.toggleKwic}), 725 726 "Â " + ' ' + 727 "Display as Key Word In Context" 728 ) 705 729 ) 706 730 ) … … 719 743 React.createElement("div", {key: "-found-message-", style: margintop}, this.renderFoundMessage(hits), " "), 720 744 React.createElement("div", {key: "-progress-", style: margintop}, this.renderProgressBar()), 721 hits > 0 ? 722 React.createElement("div", {key: "-option-KWIC-", className: "row"}, 723 this.renderToolbox(), 724 this.renderKwicCheckbox() 725 ) 726 : false, 745 this.renderToolbox(hits), 727 746 this.props.results.map(this.renderResultPanels) 728 747 ) -
SRUAggregator/trunk/src/main/resources/assets/js/search.jsx
r5971 r6043 62 62 corpus.selected = true; // selected in the corpus view 63 63 corpus.expanded = false; // not expanded in the corpus view 64 corpus.priority = 1; // priority in corpus view64 corpus.priority = 1; // used for ordering search results in corpus view 65 65 corpus.index = index; // original order, used for stable sort 66 66 }); … … 164 164 }, 165 165 166 timeout: 0,167 166 nohits: { 168 167 requests: [], … … 182 181 183 182 searchId: null, 184 hits: this.nohits, 183 timeout: 0, 184 hits: this.nohits, 185 185 }; 186 186 }, … … 195 195 url: 'rest/corpora', 196 196 success: function(json, textStatus, jqXHR) { 197 this.setState({corpora : new Corpora(json, this.updateCorpora)}); 197 if (this.isMounted()) { 198 this.setState({corpora : new Corpora(json, this.updateCorpora)}); 199 } 198 200 }.bind(this), 199 201 }); … … 204 206 url: 'rest/languages', 205 207 success: function(json, textStatus, jqXHR) { 206 this.setState({languageMap : json}); 208 if (this.isMounted()) { 209 this.setState({languageMap : json}); 210 } 207 211 }.bind(this), 208 212 }); … … 233 237 success: function(searchId, textStatus, jqXHR) { 234 238 // console.log("search ["+query+"] ok: ", searchId, jqXHR); 235 this.setState({searchId : searchId});236 this.timeout = 250;237 setTimeout(this.refreshSearchResults, this.timeout);239 var timeout = 250; 240 setTimeout(this.refreshSearchResults, timeout); 241 this.setState({ searchId: searchId, timeout: timeout }); 238 242 }.bind(this), 239 243 }); … … 241 245 242 246 refreshSearchResults: function() { 243 if (!this.state.searchId ) {247 if (!this.state.searchId || !this.isMounted()) { 244 248 return; 245 249 } … … 247 251 url: 'rest/search/'+this.state.searchId, 248 252 success: function(json, textStatus, jqXHR) { 253 var timeout = this.state.timeout; 249 254 if (json.requests.length > 0) { 250 if (t his.timeout < 10000) {251 t his.timeout = 1.5 * this.timeout;255 if (timeout < 10000) { 256 timeout = 1.5 * timeout; 252 257 } 253 setTimeout(this.refreshSearchResults, t his.timeout);254 // console.log("new search in: " + this.timeout + "ms");258 setTimeout(this.refreshSearchResults, timeout); 259 // console.log("new search in: " + this.timeout + "ms"); 255 260 } else { 256 261 console.log("search ended; hits:", json); 257 262 } 258 this.setState({ hits:json});263 this.setState({ hits: json, timeout: timeout }); 259 264 }.bind(this), 260 265 }); … … 656 661 }, 657 662 658 renderToolbox: function() {659 if (this.props.requests.length > 0) {660 return false;661 }662 return <div className="toolbox float-left">663 <a className="btn btn-default" href={this.props.getDownloadLink("text")}>664 <span className="glyphicon glyphicon-download-alt" aria-hidden="true"/> Download665 </a>666 </div>;667 },668 669 663 renderProgressBar: function() { 670 664 var percents = 100 * this.props.results.length / (this.props.requests.length + this.props.results.length); … … 693 687 }, 694 688 695 renderKwicCheckbox: function() { 696 return <div className="float-right" style={{marginRight:17}}> 697 <div className="btn-group" style={{display:"inline-block"}}> 698 <label forHtml="inputKwic" className="btn-default"> 699 { this.state.displayKwic ? 700 <input id="inputKwic" type="checkbox" value="kwic" checked onChange={this.toggleKwic} /> : 701 <input id="inputKwic" type="checkbox" value="kwic" onChange={this.toggleKwic} /> 702 } 703 704 Display as Key Word In Context 705 </label> 689 renderDownloadLinks: function() { 690 return ( 691 <div className="dropdown"> 692 <button className="btn btn-default" aria-expanded="false" data-toggle="dropdown" > 693 <span className="glyphicon glyphicon-download-alt" aria-hidden="true"/> 694 {" "} Download {" "} 695 <span className="caret"/> 696 </button> 697 <ul className="dropdown-menu"> 698 <li> <a href={this.props.getDownloadLink("csv")}> 699 {" "} As CSV file</a></li> 700 <li> <a href={this.props.getDownloadLink("excel")}> 701 {" "} As Excel file</a></li> 702 <li> <a href={this.props.getDownloadLink("tcf")}> 703 {" "} As TCF file</a></li> 704 <li> <a href={this.props.getDownloadLink("text")}> 705 {" "} As Plain Text file</a></li> 706 </ul> 707 </div> 708 ); 709 }, 710 711 renderToolbox: function(hits) { 712 if (hits <= 0) { 713 return false; 714 } 715 return <div key="-toolbox-" style={{marginBottom:10}}> 716 <div className="toolbox float-left inline"> 717 {this.renderDownloadLinks()} 718 </div> 719 <div className="float-right inline" style={{marginTop:15}}> 720 <div className="btn-group" style={{display:"inline-block"}}> 721 <label forHtml="inputKwic" className="btn-default"> 722 { this.state.displayKwic ? 723 <input id="inputKwic" type="checkbox" value="kwic" checked onChange={this.toggleKwic} /> : 724 <input id="inputKwic" type="checkbox" value="kwic" onChange={this.toggleKwic} /> 725 } 726 727 Display as Key Word In Context 728 </label> 729 </div> 706 730 </div> 707 731 </div>; … … 719 743 <div key="-found-message-" style={margintop}>{this.renderFoundMessage(hits)} </div> 720 744 <div key="-progress-" style={margintop}>{this.renderProgressBar()}</div> 721 {hits > 0 ? 722 <div key="-option-KWIC-" className="row"> 723 {this.renderToolbox()} 724 {this.renderKwicCheckbox()} 725 </div> 726 : false } 745 {this.renderToolbox(hits)} 727 746 {this.props.results.map(this.renderResultPanels)} 728 747 </ReactCSSTransitionGroup>
Note: See TracChangeset
for help on using the changeset viewer.