Let user specify encoding for export
This commit is contained in:
@@ -23,6 +23,8 @@ import javax.servlet.http.HttpServletResponse
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import org.jeudego.pairgoth.model.TimeSystem.TimeSystemType.*
|
import org.jeudego.pairgoth.model.TimeSystem.TimeSystemType.*
|
||||||
|
import java.io.OutputStreamWriter
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
object StandingsHandler: PairgothApiHandler {
|
object StandingsHandler: PairgothApiHandler {
|
||||||
@@ -71,17 +73,29 @@ object StandingsHandler: PairgothApiHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val accept = request.getHeader("Accept")?.substringBefore(";")
|
val acceptHeader = request.getHeader("Accept") as String?
|
||||||
return when(accept) {
|
val accept = acceptHeader?.substringBefore(";")
|
||||||
|
val acceptEncoding = acceptHeader?.substringAfter(";charset=", "utf-8") ?: "utf-8"
|
||||||
|
val encoding = when (acceptEncoding) {
|
||||||
|
"utf-8" -> StandardCharsets.UTF_8
|
||||||
|
"iso-8859-1" -> StandardCharsets.ISO_8859_1
|
||||||
|
else -> ApiHandler.badRequest("unknown encoding in Accept header: $accept")
|
||||||
|
}
|
||||||
|
val writer by lazy {
|
||||||
|
PrintWriter(OutputStreamWriter(response.outputStream, encoding))
|
||||||
|
}
|
||||||
|
return when (accept) {
|
||||||
"application/json" -> sortedPairables.toJsonArray()
|
"application/json" -> sortedPairables.toJsonArray()
|
||||||
"application/egf" -> {
|
"application/egf" -> {
|
||||||
|
response.contentType = "text/plain;charset=${encoding}"
|
||||||
val neededCriteria = ArrayList(tournament.pairing.placementParams.criteria)
|
val neededCriteria = ArrayList(tournament.pairing.placementParams.criteria)
|
||||||
if (!neededCriteria.contains(NBW)) neededCriteria.add(NBW)
|
if (!neededCriteria.contains(NBW)) neededCriteria.add(NBW)
|
||||||
exportToEGFFormat(tournament, sortedPairables, neededCriteria, response.writer)
|
exportToEGFFormat(tournament, sortedPairables, neededCriteria, writer)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
"application/ffg" -> {
|
"application/ffg" -> {
|
||||||
exportToFFGFormat(tournament, sortedPairables, response.writer)
|
response.contentType = "text/plain;charset=${encoding}"
|
||||||
|
exportToFFGFormat(tournament, sortedPairables, writer)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
else -> ApiHandler.badRequest("invalid Accept header: $accept")
|
else -> ApiHandler.badRequest("invalid Accept header: $accept")
|
||||||
@@ -159,7 +173,6 @@ ${
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun exportToFFGFormat(tournament: Tournament<*>, lines: List<Json.Object>, writer: PrintWriter) {
|
private fun exportToFFGFormat(tournament: Tournament<*>, lines: List<Json.Object>, writer: PrintWriter) {
|
||||||
// let's try in UTF-8
|
|
||||||
val ret =
|
val ret =
|
||||||
""";name=${tournament.shortName}
|
""";name=${tournament.shortName}
|
||||||
;date=${frDate.format(tournament.startDate)}
|
;date=${frDate.format(tournament.startDate)}
|
||||||
|
@@ -235,7 +235,7 @@ class ApiServlet: HttpServlet() {
|
|||||||
// 2) there will be other content types: .tou, .h9, .html
|
// 2) there will be other content types: .tou, .h9, .html
|
||||||
if (!isJson(accept) &&
|
if (!isJson(accept) &&
|
||||||
(!isXml(accept) || !request.requestURI.matches(Regex("/api/tour/\\d+"))) &&
|
(!isXml(accept) || !request.requestURI.matches(Regex("/api/tour/\\d+"))) &&
|
||||||
(accept != "application/ffg" && accept != "application/egf" || !request.requestURI.matches(Regex("/api/tour/\\d+/standings/\\d+")))
|
(!accept.startsWith("application/ffg") && !accept.startsWith("application/egf") || !request.requestURI.matches(Regex("/api/tour/\\d+/standings/\\d+")))
|
||||||
|
|
||||||
) throw ApiException(
|
) throw ApiException(
|
||||||
HttpServletResponse.SC_BAD_REQUEST,
|
HttpServletResponse.SC_BAD_REQUEST,
|
||||||
|
@@ -32,6 +32,7 @@ Dates Dates
|
|||||||
Download Télécharger
|
Download Télécharger
|
||||||
Download the standalone web interface module which suits your need, then follow Télécharger le module d’interface web qui correspond à vos besoins, puis suivez
|
Download the standalone web interface module which suits your need, then follow Télécharger le module d’interface web qui correspond à vos besoins, puis suivez
|
||||||
Edit Éditer
|
Edit Éditer
|
||||||
|
Encoding Encodage
|
||||||
Enter the magic word Entrer le mot magique
|
Enter the magic word Entrer le mot magique
|
||||||
Export Exporter
|
Export Exporter
|
||||||
Export tournament Exporter le tournoi
|
Export tournament Exporter le tournoi
|
||||||
|
@@ -1,15 +1,18 @@
|
|||||||
function publish(format, extension) {
|
function publish(format, extension) {
|
||||||
let form = $('#tournament-infos')[0];
|
let form = $('#tournament-infos')[0];
|
||||||
let shortName = form.val('shortName');
|
let shortName = form.val('shortName');
|
||||||
|
let encoding = $('#encoding')[0].value;
|
||||||
let hdrs = headers();
|
let hdrs = headers();
|
||||||
hdrs['Accept'] = `application/${format}`
|
hdrs['Accept'] = `application/${format};charset=${encoding}`
|
||||||
fetch(`api/tour/${tour_id}/standings/${activeRound}`, {
|
fetch(`api/tour/${tour_id}/standings/${activeRound}`, {
|
||||||
headers: hdrs
|
headers: hdrs
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
if (resp.ok) return resp.text()
|
if (resp.ok) return resp.arrayBuffer()
|
||||||
else throw "publish error"
|
else throw "publish error"
|
||||||
}).then(txt => {
|
}).then(bytes => {
|
||||||
let blob = new Blob(['\uFEFF', txt.trim()], {type: 'text/plain;charset=utf-8'});
|
let blob = new Blob(
|
||||||
|
encoding === 'utf-8' ? ['\uFEFF', bytes] : [bytes],
|
||||||
|
{ type: `text/plain;charset=${encoding}` });
|
||||||
downloadFile(blob, `${shortName}.${extension}`);
|
downloadFile(blob, `${shortName}.${extension}`);
|
||||||
close_modal();
|
close_modal();
|
||||||
}).catch(err => showError(err));
|
}).catch(err => showError(err));
|
||||||
|
@@ -88,7 +88,10 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="right form-actions">
|
<div class="right form-actions">
|
||||||
<button id="publish" class="ui yellow floating button">Publish</button>
|
<button id="publish" class="ui yellow floating right labeled icon button">
|
||||||
|
<i class="paper plane outline icon"></i>
|
||||||
|
Publish
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="publish-modal" class="popup">
|
<div id="publish-modal" class="popup">
|
||||||
@@ -97,12 +100,23 @@
|
|||||||
Publish standings
|
Publish standings
|
||||||
</div>
|
</div>
|
||||||
<div class="popup-content">
|
<div class="popup-content">
|
||||||
<div class="horz">
|
<form class="ui edit form">
|
||||||
<span>Choose format</span>
|
<div class="field">
|
||||||
<button type="button" class="ui blue floating publish-html button">HTML</button>
|
<label>Encoding</label>
|
||||||
<button type="button" class="ui blue floating publish-egf button">EGF</button>
|
<select id="encoding">
|
||||||
<button type="button" class="ui blue floating publish-ffg button">FFG</button>
|
<option value="utf-8">UTF-8</option>
|
||||||
</div>
|
<option value="iso-8859-1">ISO 8859-1</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Choose format</label>
|
||||||
|
<div class="inline fields">
|
||||||
|
<button type="button" class="ui blue floating publish-html button">HTML</button>
|
||||||
|
<button type="button" class="ui blue floating publish-egf button">EGF</button>
|
||||||
|
<button type="button" class="ui blue floating publish-ffg button">FFG</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="popup-footer">
|
<div class="popup-footer">
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
|
Reference in New Issue
Block a user