Let user specify encoding for export

This commit is contained in:
Claude Brisson
2024-03-01 12:58:27 +01:00
parent d991d28116
commit 4780953ff5
5 changed files with 48 additions and 17 deletions

View File

@@ -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)}

View File

@@ -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,

View File

@@ -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 dinterface web qui correspond à vos besoins, puis suivez Download the standalone web interface module which suits your need, then follow Télécharger le module dinterface 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

View File

@@ -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));

View File

@@ -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">