-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #599 Implement the save controller in the API Use it from the menu Make sure that we can deal with returned text instead of JSON
- Loading branch information
1 parent
9caf396
commit bdbe6fe
Showing
9 changed files
with
192 additions
and
3 deletions.
There are no files selected for viewing
128 changes: 128 additions & 0 deletions
128
...owser-api/src/main/java/org/schoellerfamily/gedbrowser/api/controller/SaveController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package org.schoellerfamily.gedbrowser.api.controller; | ||
|
||
import java.util.Collections; | ||
|
||
import javax.servlet.http.HttpServletResponse; | ||
|
||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
import org.schoellerfamily.gedbrowser.api.controller.exception.DataSetNotFoundException; | ||
import org.schoellerfamily.gedbrowser.datamodel.Root; | ||
import org.schoellerfamily.gedbrowser.persistence.mongo.loader.GedDocumentFileLoader; | ||
import org.schoellerfamily.gedbrowser.writer.GedWriterLine; | ||
import org.schoellerfamily.gedbrowser.writer.creator.GedObjectToGedWriterVisitor; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.CrossOrigin; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.ResponseBody; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
/** | ||
* Emits GEDCOM to the HTTP connection to download the GEDCOM state. | ||
* | ||
* @author Dick Schoeller | ||
*/ | ||
@CrossOrigin(origins = { | ||
"http://largo.schoellerfamily.org:4200", "http://localhost:4200" }) | ||
@RestController | ||
public class SaveController { | ||
/** Logger. */ | ||
private final transient Log logger = LogFactory.getLog(getClass()); | ||
|
||
/** */ | ||
@Autowired | ||
private transient GedDocumentFileLoader loader; | ||
|
||
/** | ||
* Connects HTML template file with data for saving the GEDCOM file. | ||
* | ||
* @param db name of database for the lookup | ||
* @param response the servlet response object, needed for tweaking headers | ||
* @return a string identifying which HTML template to use. | ||
*/ | ||
@GetMapping(value = "/v1/dbs/{db}/save", | ||
produces = MediaType.TEXT_PLAIN_VALUE) | ||
@ResponseBody | ||
public final ResponseEntity<String> save(@PathVariable final String db, | ||
final HttpServletResponse response) { | ||
logger.info("Starting save"); | ||
// check here whether authorized. | ||
final Root root = fetchRoot(db); | ||
|
||
setHeaders(response, root); | ||
|
||
final String contents = renderGedFile(root); | ||
final String filename = root.getDbName() + ".ged"; | ||
logger.info("filename: " + filename); | ||
final HttpHeaders headers = new HttpHeaders(); | ||
headers.setAccessControlExposeHeaders( | ||
Collections.singletonList("Content-Disposition")); | ||
headers.set("Content-Disposition", "attachment; filename=" + filename); | ||
headers.setContentType(MediaType.TEXT_PLAIN); | ||
logger.info("Exiting save"); | ||
return new ResponseEntity<>(contents, headers, HttpStatus.OK); | ||
} | ||
|
||
/** | ||
* @param dbName the name of the database | ||
* @return the root object | ||
*/ | ||
protected final Root fetchRoot(final String dbName) { | ||
final Root root = loader.loadDocument(dbName).getGedObject(); | ||
if (root == null) { | ||
throw new DataSetNotFoundException( | ||
"Data set " + dbName + " not found", dbName); | ||
} | ||
return root; | ||
} | ||
|
||
/** | ||
* @param root the dataset to render | ||
* @return the gedcom file as a string | ||
*/ | ||
private String renderGedFile(final Root root) { | ||
final GedObjectToGedWriterVisitor visitor = | ||
new GedObjectToGedWriterVisitor(); | ||
root.accept(visitor); | ||
final StringBuilder builder = new StringBuilder(); | ||
for (final GedWriterLine line : visitor.getLines()) { | ||
if (line.getLine().isEmpty()) { | ||
continue; | ||
} | ||
builder.append(line.getLine()).append("\n"); | ||
} | ||
return builder.toString(); | ||
} | ||
|
||
/** | ||
* Fill in response headers to make this save the file instead of | ||
* displaying it. | ||
* | ||
* @param response the servlet response | ||
* @param root the root of the dataset being saved | ||
*/ | ||
private void setHeaders(final HttpServletResponse response, | ||
final Root root) { | ||
response.setHeader("content-type", "application/octet-stream"); | ||
response.setHeader("content-disposition", | ||
"attachment; filename=" + getSaveFilename(root)); | ||
} | ||
|
||
/** | ||
* @param root the root object we are saving | ||
* @return the href string with the base filename. | ||
*/ | ||
private String getSaveFilename(final Root root) { | ||
final String filename = root.getFilename(); | ||
final int lastIndexOf = filename.lastIndexOf("/"); | ||
if (lastIndexOf == -1) { | ||
return filename; | ||
} | ||
return filename.substring(lastIndexOf + 1); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,26 @@ | ||
import { Component } from '@angular/core'; | ||
import {HttpResponse} from '@angular/common/http'; | ||
import {Component} from '@angular/core'; | ||
import {saveAs} from 'file-saver/FileSaver'; | ||
import {SaveService} from './shared/services'; | ||
|
||
@Component({ | ||
selector: 'app-root', | ||
templateUrl: './app.component.html', | ||
styleUrls: ['./app.component.css'] | ||
}) | ||
export class AppComponent { | ||
title = 'gedbrowser'; | ||
|
||
constructor(private saveService: SaveService) { } | ||
|
||
saveFile() { | ||
this.saveService.getTextFile('schoeller').subscribe( | ||
results => this.saveToFileSystem(results) | ||
); | ||
} | ||
|
||
private saveToFileSystem(response) { | ||
const blob = new Blob([response], {type: 'text/plain'}); | ||
saveAs(blob, 'schoeller.ged'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
gedbrowser-client/src/app/shared/services/save.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { TestBed, inject } from '@angular/core/testing'; | ||
|
||
import { PersonService } from './person.service'; | ||
|
||
describe('PersonService', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
providers: [PersonService] | ||
}); | ||
}); | ||
|
||
it('should be created', inject([PersonService], (service: PersonService) => { | ||
expect(service).toBeTruthy(); | ||
})); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {Injectable} from '@angular/core'; | ||
import {HttpClient, HttpHeaders, HttpResponse} from '@angular/common/http'; | ||
import {Observable} from 'rxjs/Observable'; | ||
|
||
/** | ||
* Service for obtaining saving a db. | ||
*/ | ||
@Injectable() | ||
export class SaveService { | ||
constructor(private http: HttpClient) {} | ||
|
||
getTextFile(db: string) { | ||
return this.http.get( | ||
'http://largo.schoellerfamily.org:9084/gedbrowser-api/v1/dbs/' + db + '/save', {responseType: 'text'}); | ||
} | ||
} |