From 18d53d0c277524d41392e0e843b8febe65689ff3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mikl=C3=B3s=20T=C3=B3th?= <tothmiklostibor@gmail.com>
Date: Tue, 1 Mar 2022 14:48:48 +0100
Subject: [PATCH] Google Sheets progress

---
 src/jsMain/kotlin/Main.kt           |  73 +---------------
 src/jsMain/kotlin/gapi/Gapi.kt      |  31 ++++++-
 src/jsMain/kotlin/pontozas.kt       | 125 ++++++++++++++++++++++++++++
 src/jsMain/kotlin/ui/Modal.kt       |   8 +-
 src/jsMain/kotlin/ui/Params.kt      |  37 --------
 src/jsMain/kotlin/ui/SheetsModal.kt |  69 ++++++++-------
 src/jsMain/kotlin/ui/Utils.kt       |  30 +++++++
 7 files changed, 227 insertions(+), 146 deletions(-)
 create mode 100644 src/jsMain/kotlin/pontozas.kt
 delete mode 100644 src/jsMain/kotlin/ui/Params.kt
 create mode 100644 src/jsMain/kotlin/ui/Utils.kt

diff --git a/src/jsMain/kotlin/Main.kt b/src/jsMain/kotlin/Main.kt
index c044e3b..32ec215 100644
--- a/src/jsMain/kotlin/Main.kt
+++ b/src/jsMain/kotlin/Main.kt
@@ -2,6 +2,7 @@ import androidx.compose.runtime.*
 import gapi.initGapi
 import gapi.loadGapi
 import kotlinx.browser.document
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import org.jetbrains.compose.web.attributes.disabled
 import org.jetbrains.compose.web.dom.*
@@ -12,76 +13,6 @@ import ui.State
 
 
 fun main() {
-    val row = document.querySelector("#content-main > div.uk-clearfix.uk-margin-bottom")
-        ?: throw Error("couldn't find button row")
-    val rootDiv = document.createElement("div")
-    rootDiv.id = "kemence-root"
-    row.appendChild(rootDiv)
-
-    document.title = document.title.replace("PéK", "PéK \uD83D\uDC68\u200D\uD83C\uDF73")
-
-    renderComposable(root = rootDiv) {
-        var google by remember { mutableStateOf(false) }
-        var state by remember { mutableStateOf<State>(Ready) }
-        val scope = rememberCoroutineScope()
-        scope.launch {
-            loadGapi()
-            initGapi()
-            google = true
-        }
-
-        divFloatRight {
-            val magicId = "csv-magic"
-            Button({
-                classes("uk-button", "uk-button-small", "uk-button-success")
-                attr("data-uk-ui.modal", "{ target: '#$magicId' }")
-                if (state != Ready)
-                    disabled()
-            }){
-                var txt = "..."
-                val curState = state
-                if (curState == Ready) {
-                    txt = "CSV import \uD83D\uDC68\u200D\uD83C\uDF73"
-                } else if (curState is ImportInProgress) {
-                    val progress = (curState.progress * 100.0).format()
-                    txt = "Importálás ($progress%)"
-                }
-
-                Text(txt)
-            }
-            Div({
-                id(magicId)
-                classes("uk-ui.modal")
-            }) {
-                csvModal { state = it }
-            }
-        }
-        divFloatRight {
-            val magicId = "google-magic"
-            Button({
-                classes("uk-button", "uk-button-small", "uk-button-success")
-                attr("data-uk-ui.modal", "{ target: '#$magicId' }")
-                if (state != Ready || !google)
-                    disabled()
-            }){
-                var txt = "..."
-                val curState = state
-                if (curState == Ready) {
-                    txt = "Google Sheets import \uD83D\uDC68\u200D\uD83C\uDF73"
-                } else if (curState is ImportInProgress) {
-                    val progress = (curState.progress * 100.0).format()
-                    txt = "Importálás ($progress%)"
-                }
-
-                Text(txt)
-            }
-            Div({
-                id(magicId)
-                classes("uk-ui.modal")
-            }) {
-                sheetsModal { state = it }
-            }
-        }
-    }
+    pontozas()
 }
 
diff --git a/src/jsMain/kotlin/gapi/Gapi.kt b/src/jsMain/kotlin/gapi/Gapi.kt
index 92b6da6..b4ecbef 100644
--- a/src/jsMain/kotlin/gapi/Gapi.kt
+++ b/src/jsMain/kotlin/gapi/Gapi.kt
@@ -1,6 +1,8 @@
 package gapi
 
+import kotlinx.coroutines.delay
 import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
 import kotlin.coroutines.suspendCoroutine
 
 object authObj: client.AuthType {
@@ -17,7 +19,13 @@ fun listenForLoginEvents(callback: (Boolean) -> Unit) {
 }
 
 suspend fun loadGapi() = suspendCoroutine<Unit> { cont ->
-    gapi.load(apiName = "gapi.client:gapi.auth2") { cont.resume(Unit) }
+    try {
+        gapi.load(apiName = "client:auth2") { cont.resume(Unit) }
+    } catch (e: dynamic) {
+        cont.resumeWithException(
+            e as? Throwable ?: Error("$e")
+        )
+    }
 }
 
 private fun handleLoginEvent(isSignedIn: Boolean) {
@@ -46,6 +54,14 @@ suspend fun initGapi() = suspendCoroutine<Unit> { cont ->
             gapi.auth2.getAuthInstance().isSignedIn.get()
         }
 
+        username = {
+            gapi.auth2.getAuthInstance().currentUser.get().getBasicProfile().getName()
+        }
+
+        email = {
+            gapi.auth2.getAuthInstance().currentUser.get().getBasicProfile().getEmail()
+        }
+
         handleLoginEvent(isSignedIn())
     }, { error: Throwable ->
         println(error)
@@ -54,6 +70,13 @@ suspend fun initGapi() = suspendCoroutine<Unit> { cont ->
     Unit
 }
 
-var logIn: () -> Unit = { throw Error("gapi.getGapi has not been initialized yet") }
-var logOut: () -> Unit = { throw Error("gapi.getGapi has not been initialized yet") }
-var isSignedIn: () -> Boolean = { false }
\ No newline at end of file
+var logIn: () -> Unit = { throw Error("Gapi has not been initialized yet") }
+    private set
+var logOut: () -> Unit = { throw Error("Gapi has not been initialized yet") }
+    private set
+var isSignedIn: () -> Boolean = { false }
+    private set
+var username: () -> String = { "" }
+    private set
+var email: () -> String = { "" }
+    private set
\ No newline at end of file
diff --git a/src/jsMain/kotlin/pontozas.kt b/src/jsMain/kotlin/pontozas.kt
new file mode 100644
index 0000000..901be99
--- /dev/null
+++ b/src/jsMain/kotlin/pontozas.kt
@@ -0,0 +1,125 @@
+import androidx.compose.runtime.*
+import gapi.initGapi
+import gapi.loadGapi
+import kotlinx.browser.document
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import org.jetbrains.compose.web.attributes.disabled
+import org.jetbrains.compose.web.dom.Button
+import org.jetbrains.compose.web.dom.Div
+import org.jetbrains.compose.web.dom.Text
+import org.jetbrains.compose.web.renderComposable
+import org.w3c.dom.HTMLStyleElement
+import processing.format
+import ui.*
+import ui.State
+
+fun pontozas() {
+    val row = document.querySelector("#content-main > div.uk-clearfix.uk-margin-bottom")
+        ?: throw Error("couldn't find button row")
+    val rootDiv = document.createElement("div")
+    rootDiv.id = "kemence-root"
+    row.appendChild(rootDiv)
+
+    fixNameSpacing()
+
+    document.title = document.title.replace("PéK", "PéK \uD83D\uDC68\u200D\uD83C\uDF73")
+
+    renderComposable(root = rootDiv) {
+        var google by remember { mutableStateOf(false) }
+        var state by remember { mutableStateOf<State>(Ready) }
+        val scope = rememberCoroutineScope()
+        scope.launch {
+            while (true) {
+                try {
+                    loadGapi()
+                    break
+                } catch (e: Throwable) {
+                    console.error("Error loading Google API: $e, trying again...")
+                    delay(100)
+                }
+            }
+            initGapi()
+            google = true
+        }
+
+        divFloatRight {
+            val magicId = "csv-magic"
+            Button({
+                classes("uk-button", "uk-button-small", "uk-button-success")
+                attr("data-uk-modal", "{ target: '#$magicId' }")
+                if (state != Ready)
+                    disabled()
+            }){
+                var txt = "..."
+                val curState = state
+                if (curState == Ready) {
+                    txt = "CSV import \uD83D\uDC68\u200D\uD83C\uDF73"
+                } else if (curState is ImportInProgress) {
+                    val progress = (curState.progress * 100.0).format()
+                    txt = "Importálás ($progress%)"
+                }
+
+                Text(txt)
+            }
+            Div({
+                id(magicId)
+                classes("uk-modal")
+            }) {
+                csvModal { state = it }
+            }
+        }
+        divFloatRight {
+            val magicId = "google-magic"
+            Button({
+                classes("uk-button", "uk-button-small", "uk-button-success")
+                attr("data-uk-modal", "{ target: '#$magicId' }")
+                if (state != Ready || !google)
+                    disabled()
+            }){
+                var txt = "..."
+                val curState = state
+                if (curState == Ready) {
+                    txt = "Google Sheets import \uD83D\uDC68\u200D\uD83C\uDF73"
+                } else if (curState is ImportInProgress) {
+                    val progress = (curState.progress * 100.0).format()
+                    txt = "Importálás ($progress%)"
+                }
+
+                Text(txt)
+            }
+            Div({
+                id(magicId)
+                classes("uk-modal")
+            }) {
+                sheetsModal { state = it }
+            }
+        }
+    }
+}
+
+fun fixNameSpacing() {
+    val tbody = document.querySelector("#points-table > tbody")
+    val tfoot = document.querySelector("#points-table > tfoot")
+    if (
+        tbody == null ||
+        tfoot == null
+    ) throw Error("Not in pontozo view")
+
+    val children = tbody.childElementCount + tfoot.childElementCount
+    val height = tbody.clientHeight.toDouble() + tfoot.clientHeight.toDouble()
+
+    val liHeight = height/children - 10 // padding
+
+    val style = document.createElement("style") as HTMLStyleElement
+    style.type = "text/css"
+
+    style.appendChild(document.createTextNode("""
+        #name-list > li {
+            height: ${liHeight}px !important;
+        }
+    """.trimIndent()))
+
+    document.head!!.appendChild(style)
+}
+
diff --git a/src/jsMain/kotlin/ui/Modal.kt b/src/jsMain/kotlin/ui/Modal.kt
index aaf1b6b..4cb8888 100644
--- a/src/jsMain/kotlin/ui/Modal.kt
+++ b/src/jsMain/kotlin/ui/Modal.kt
@@ -2,7 +2,6 @@ package ui
 
 import pekstuff.PekTable
 import androidx.compose.runtime.*
-import clear
 import kotlinx.browser.document
 import kotlinx.coroutines.launch
 import org.jetbrains.compose.web.attributes.disabled
@@ -11,6 +10,7 @@ import org.jetbrains.compose.web.css.color
 import org.jetbrains.compose.web.css.rgb
 import org.jetbrains.compose.web.dom.*
 import org.w3c.dom.HTMLElement
+import pekstuff.clear
 
 interface ModalType {
     val title: String
@@ -21,12 +21,12 @@ interface ModalType {
 @Composable
 fun modal(type: ModalType, setState: (State) -> Unit) {
     Div({
-        classes("uk-ui.modal-dialog", "uk-text-justify")
+        classes("uk-modal-dialog", "uk-text-justify")
     }) {
-        val closeId = "kemence${type::class.simpleName}-ui.modal-close"
+        val closeId = "kemence${type::class.simpleName}-modal-close"
         A(attrs = {
             id(closeId)
-            classes("uk-ui.modal-close", "uk-close")
+            classes("uk-modal-close", "uk-close")
         }) {  }
         H2 {
             Text(type.title)
diff --git a/src/jsMain/kotlin/ui/Params.kt b/src/jsMain/kotlin/ui/Params.kt
deleted file mode 100644
index 7aee1f4..0000000
--- a/src/jsMain/kotlin/ui/Params.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package ui
-
-import androidx.compose.runtime.*
-import org.jetbrains.compose.web.dom.*
-
-@Composable
-fun inputWithLabel(
-    name: String,
-    value: String,
-    updated: (String) -> Unit,
-) {
-    Tr {
-        val id = "kemence-${id++}"
-        Td({
-            style {
-                property("vertical-align", "middle")
-            }
-        }) {
-            Label(forId = id, {
-                classes("uk-form-label")
-            }) {
-                Text(name)
-            }
-        }
-        Td {
-            TextInput(value) {
-                id(id)
-                classes("uk-input", "uk-input-width-1-1")
-                onInput {
-                    updated(it.value)
-                }
-            }
-        }
-    }
-}
-
-var id = 0
diff --git a/src/jsMain/kotlin/ui/SheetsModal.kt b/src/jsMain/kotlin/ui/SheetsModal.kt
index c40ab28..fe9f4c1 100644
--- a/src/jsMain/kotlin/ui/SheetsModal.kt
+++ b/src/jsMain/kotlin/ui/SheetsModal.kt
@@ -2,12 +2,9 @@ package ui
 
 import datasources.GSheet
 import androidx.compose.runtime.*
-import gapi.isSignedIn
+import gapi.*
 import kotlinx.browser.document
 import kotlinx.coroutines.launch
-import gapi.listenForLoginEvents
-import gapi.logIn
-import gapi.logOut
 import org.jetbrains.compose.web.attributes.InputType
 import org.jetbrains.compose.web.attributes.disabled
 import org.jetbrains.compose.web.dom.*
@@ -26,8 +23,14 @@ private object SheetsModal: ModalType {
         val scope = rememberCoroutineScope()
 
         var signedIn by remember { mutableStateOf(isSignedIn()) }
+        var username by remember { mutableStateOf(username()) }
+        var email by remember { mutableStateOf(email()) }
         SideEffect {
             listenForLoginEvents { signedIn = it }
+            scope.launch {
+                username = username()
+                email = email()
+            }
         }
 
         var sheet by remember { mutableStateOf<GSheet?>(null) }
@@ -38,40 +41,46 @@ private object SheetsModal: ModalType {
             else ""
         )
 
-        Button({
-            if (signedIn) {
-                classes("uk-button", "uk-button-danger")
-            } else {
-                classes("uk-button", "uk-button-primary")
-            }
-            onClick {
-                if(signedIn) {
-                    logOut()
+        withLabel(
+            if (signedIn) "$username ($email)"
+            else "Google Fiók"
+        ) { id ->
+            Button({
+                id(id)
+                if (signedIn) {
+                    classes("uk-button", "uk-button-danger")
                 } else {
-                    logIn()
+                    classes("uk-button", "uk-button-primary")
                 }
+                onClick {
+                    if (signedIn) {
+                        logOut()
+                    } else {
+                        logIn()
+                    }
+                }
+            }) {
+                Text(
+                    if (signedIn) {
+                        "Kijelentkezés"
+                    } else {
+                        "Bejelentkezés"
+                    }
+                )
             }
-        }) {
-            Text(
-                if(signedIn) { "Kijelentkezés" } else { "Bejelentkezés" }
-            )
         }
 
         Br {}
 
-        val inputId = "kemence-sheet-input"
-        Label(inputId, {
-            classes("form-label-required", "uk-margin-right")
-        }) {
-            Text("Google Sheet URL")
-        }
         var sheetUrl by remember { mutableStateOf("") }
-        Input(type = InputType.Text, attrs = {
-            id(inputId)
-            classes("uk-input")
-            onChange { sheetUrl = it.value }
-            value(sheetUrl)
-        })
+        withLabel("Google Sheet URL") { id ->
+            Input(type = InputType.Text, attrs = {
+                id(id)
+                classes("uk-input")
+                onChange { sheetUrl = it.value }
+                value(sheetUrl)
+            })
+        }
         Hr {  }
         divFloatRight {
             Button({
diff --git a/src/jsMain/kotlin/ui/Utils.kt b/src/jsMain/kotlin/ui/Utils.kt
new file mode 100644
index 0000000..f6073c0
--- /dev/null
+++ b/src/jsMain/kotlin/ui/Utils.kt
@@ -0,0 +1,30 @@
+package ui
+
+import androidx.compose.runtime.*
+import org.jetbrains.compose.web.dom.*
+
+@Composable
+fun withLabel(
+    label: String,
+    content: @Composable (id: String) -> Unit,
+) {
+    Tr {
+        val id = remember { "kemence-${id++}" }
+        Td({
+            style {
+                property("vertical-align", "middle")
+            }
+        }) {
+            Label(forId = id, {
+                classes("uk-form-label", "uk-margin-right")
+            }) {
+                Text(label)
+            }
+        }
+        Td {
+            content(id)
+        }
+    }
+}
+
+var id = 0
-- 
GitLab