Skip to content
Snippets Groups Projects
Commit be3a661e authored by Tóth Miklós Tibor's avatar Tóth Miklós Tibor :shrug:
Browse files

Google Sheets import done

parent 18d53d0c
No related branches found
No related tags found
No related merge requests found
Pipeline #30486 passed
<component name="ArtifactManager">
<artifact type="jar" name="kemence-js-1.0">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="kemence-js-1.0.jar">
<element id="module-output" name="kemence.jsMain" />
</root>
<root id="archive" name="kemence-js-1.0.jar" />
</artifact>
</component>
\ No newline at end of file
......@@ -3,7 +3,7 @@ package datasources
import com.github.doyaaaaaken.kotlincsv.dsl.csvReader
import pekstuff.trimAsPrinciple
class CSVTable(data: String) {
class CSVTable(data: String): DataSource {
private val rows = csvReader().readAll(data)
companion object {
private val filterList = listOf(
......@@ -20,7 +20,7 @@ class CSVTable(data: String) {
}
.toMap()
val principles get() = principleIndexes.keys
override val principles get() = principleIndexes.keys
private val peopleIndexes = rows
.mapIndexed { i, p -> p[0] to i }
......@@ -28,16 +28,9 @@ class CSVTable(data: String) {
.filter { it.first.isNotBlank() }
.toMap()
val people: List<String>
get() {
val ret = mutableListOf<String>()
rows.drop(1)
.filter { it[0].isNotEmpty() }
.forEach { ret.add(it[0]) }
return ret
}
override val people get() = peopleIndexes.keys
operator fun get(person: String, principle: String): Int {
override operator fun get(person: String, principle: String): Int {
val pers = peopleIndexes[person]!!
val princ = principleIndexes[principle]!!
return rows[pers][princ].toIntOrNull() ?: 0
......
package datasources
interface DataSource {
val principles: Set<String>
val people: Set<String>
operator fun get(person: String, principle: String): Int
}
interface NoteDataSource {
val principles: Set<String>
val people: Set<String>
fun getNote(person: String, principle: String): String
}
\ No newline at end of file
package datasources
import androidx.compose.runtime.NoLiveLiterals
import gapi.gapi
import gapi.isSignedIn
import gapi.sheets
import kotlinx.browser.window
import pekstuff.trimAsPrinciple
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
class GSheet private constructor() {
class GSheet private constructor(private val sheet: sheets.Spreadsheet): DataSource, NoteDataSource {
companion object {
private val filterList = listOf(
"szumma", "színes belépő"
)
suspend fun new(url: String): GSheet {
if (!isSignedIn()) throw Error("You must sign in to get gapi.sheets")
val sheet = GSheet()
sheet.setUrl(url)
return sheet
}
}
private var _url = ""
suspend fun setUrl(value: String){
_url = value
loadSheet()
val sheet = getSheetFromUrl(url)
window.asDynamic().test = sheet
return GSheet(sheet)
}
val url: String get() = _url
private suspend fun getSheetFromUrl() = suspendCoroutine<sheets.Spreadsheet> { cont ->
gapi.client.sheets.spreadsheets.get(object: sheets.SpreadsheetGetType {
override var spreadsheetId = url
@NoLiveLiterals
private suspend fun getSheetFromUrl(url: String) = suspendCoroutine<sheets.Spreadsheet> { cont ->
val obj = js("{}")
obj["spreadsheetId"] = url
.removePrefix("https://docs.google.com/spreadsheets/d/")
.split("/")[0]
}).execute {
if (it.status != 200) {
cont.resumeWithException(Error("unable to load sheet: ${it.statusText}"))
return@execute Unit
}
obj["includeGridData"] = true
gapi.client.sheets.spreadsheets.get(obj).execute {
cont.resume(it.result)
}
}
}
private val rows = sheet.sheets!![0].data!![0].rowData!!
private val principleIndexes = rows[0].values!!.mapIndexed { i, data ->
(data.formattedValue?.trimAsPrinciple() ?: "") to i
}.drop(1).filter {
filterList.all { filter -> !it.first.lowercase().contains(filter) } &&
it.first.isNotBlank()
}.toMap()
override val principles get() = principleIndexes.keys
private suspend fun loadSheet() {
sheet = getSheetFromUrl()
private val peopleIndexes = rows
.mapIndexed { i, data -> (data.values!![0].formattedValue ?: "") to i }
.drop(1)
.filter { it.first.isNotBlank() }
.toMap()
override val people get() = peopleIndexes.keys
override operator fun get(person: String, principle: String): Int {
val pers = peopleIndexes[person]!!
val princ = principleIndexes[principle]!!
return rows[pers].values!![princ].formattedValue!!.toIntOrNull() ?: 0
}
private lateinit var sheet: sheets.Spreadsheet
override fun getNote(person: String, principle: String): String {
val pers = peopleIndexes[person]!!
val princ = principleIndexes[principle]!!
return rows[pers].values!![princ].note ?: ""
}
}
package pekstuff
import kotlinx.browser.document
import kotlinx.coroutines.delay
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLTextAreaElement
object PekNote {
val noteNameCnt get() = document.querySelector("#comment-container > div.uk-padding.uk-text-center")
val noteName get() = noteNameCnt?.textContent
val noteCnt get() = document.getElementById("comment-textarea") as? HTMLTextAreaElement
val btn get() = document.querySelector("#new_point_detail_comment > article > div.uk-clearfix > div.uk-float-right > input.uk-button") as? HTMLInputElement
var note
get() = noteCnt!!.value
set(value) {
noteCnt!!.value = value
btn!!.click()
}
suspend fun waitUntilLoaded(person: String, principle: String) {
val expected = "$person - $principle"
while (noteName != expected) {
println("$noteName != $expected")
delay(100)
}
}
}
\ No newline at end of file
package pekstuff
import kotlinx.browser.document
import kotlinx.browser.window
import kotlinx.coroutines.*
import org.w3c.dom.Element
import org.w3c.dom.HTMLInputElement
......@@ -59,13 +60,14 @@ object PekTable {
elem.style.background = origBg
}
elem.click()
if (elem.value.toIntOrNull() == value) { // don't update if up-to-date
// sort of ugly workaround, meh.
PekDelay.skipNext()
return
}
elem.click()
elem.value = value.toString()
elem.trigger()
tableElem.click()
......
package processing
import datasources.CSVTable
import datasources.DataSource
import datasources.NoteDataSource
import kotlinx.coroutines.delay
import pekstuff.PekDelay
import pekstuff.PekNote
import pekstuff.PekTable
import kotlin.math.max
......@@ -12,9 +15,11 @@ class ProcessingError(private val errors: List<String>): Exception(errors.toStri
}
}
suspend fun CSVTable.process(
suspend fun DataSource.process(
progress: (Double) -> Unit = {}
) {
// todo show comment stuff
progress(0.0)
val principleMappings = principles.associateWith {
PekTable.principles.findClosestMatch(it)
......@@ -22,7 +27,7 @@ suspend fun CSVTable.process(
val errors = mutableListOf<String>()
people.forEachIndexed { i, person ->
people.sorted().forEachIndexed { i, person ->
val pekPerson = PekTable.people.findClosestMatch(person)
if (pekPerson == null) {
......@@ -35,6 +40,11 @@ suspend fun CSVTable.process(
PekTable[pekPerson, pekPrinciple] = point
PekDelay()
if (this is NoteDataSource) {
PekNote.waitUntilLoaded(pekPerson, pekPrinciple)
PekNote.note = getNote(person, principle)
}
progress(calcProgress(i, j, people.size, principles.size))
if (person != pekPerson) {
......
package processing
\ No newline at end of file
......@@ -9,6 +9,7 @@ import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.disabled
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLElement
import processing.process
private object SheetsModal: ModalType {
override val title = "Google Sheets import"
......@@ -18,7 +19,7 @@ private object SheetsModal: ModalType {
closeId: String,
setState: (State) -> Unit,
hint: String,
setHint: (String) -> Unit
setHint: (String) -> Unit,
) {
val scope = rememberCoroutineScope()
......@@ -33,12 +34,15 @@ private object SheetsModal: ModalType {
}
}
var sheetUrl by remember { mutableStateOf("") }
var sheet by remember { mutableStateOf<GSheet?>(null) }
setHint(
if (!signedIn) "Jelentkezz be"
else if (sheet == null) "Adj meg egy Google Sheet URL-t"
else ""
when {
!signedIn -> "Jelentkezz be"
sheetUrl.isBlank() || !sheetUrl.contains("https://docs.google.com/spreadsheets") -> "Adj meg egy Google Sheet URL-t"
else -> ""
}
)
withLabel(
......@@ -72,12 +76,11 @@ private object SheetsModal: ModalType {
Br {}
var sheetUrl by remember { mutableStateOf("") }
withLabel("Google Sheet URL") { id ->
Input(type = InputType.Text, attrs = {
id(id)
classes("uk-input")
onChange { sheetUrl = it.value }
onInput { sheetUrl = it.value }
value(sheetUrl)
})
}
......@@ -87,7 +90,9 @@ private object SheetsModal: ModalType {
classes("uk-button", "uk-button-primary")
onClick {
scope.launch {
println("zsa")
sheet = GSheet.new(sheetUrl)
sheet?.process { setState(ImportInProgress(it)) }
setState(Ready)
}
(document.getElementById(closeId) as HTMLElement).click()
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment