Add paging to Spinner browser.

This commit is contained in:
Greyson Parrelli 2022-02-17 20:03:48 -05:00
parent a84c971cbe
commit 2d1efb604c
3 changed files with 81 additions and 5 deletions

View file

@ -23,7 +23,21 @@
{{/if}} {{/if}}
{{#if queryResult}} {{#if queryResult}}
<p>{{queryResult.rowCount}} row(s).</p> <p>Viewing rows {{pagingData.startRow}}-{{pagingData.endRow}} of {{pagingData.rowCount}}.</p>
<!-- Paging Controls -->
<form action="browse" method="post">
<input type="hidden" name="table" value="{{table}}" />
<input type="hidden" name="pageSize" value="{{pagingData.pageSize}}" />
<input type="hidden" name="pageIndex" value="{{pagingData.pageIndex}}" />
<input type="submit" name="action" value="first" {{#if pagingData.firstPage}}disabled{{/if}} />
<input type="submit" name="action" value="previous" {{#if pagingData.firstPage}}disabled{{/if}} />
<input type="submit" name="action" value="next" {{#if pagingData.lastPage}}disabled{{/if}} />
<input type="submit" name="action" value="last" {{#if pagingData.lastPage}}disabled{{/if}} />
</form>
<!-- Data Rows -->
<table> <table>
<tr> <tr>
{{#each queryResult.columns}} {{#each queryResult.columns}}
@ -42,6 +56,20 @@
Select a table from above and click 'browse'. Select a table from above and click 'browse'.
{{/if}} {{/if}}
<br />
<!-- Paging Controls -->
<form action="browse" method="post">
<input type="hidden" name="table" value="{{table}}" />
<input type="hidden" name="pageSize" value="{{pagingData.pageSize}}" />
<input type="hidden" name="pageIndex" value="{{pagingData.pageIndex}}" />
<input type="submit" name="action" value="first" {{#if pagingData.firstPage}}disabled{{/if}} />
<input type="submit" name="action" value="previous" {{#if pagingData.firstPage}}disabled{{/if}} />
<input type="submit" name="action" value="next" {{#if pagingData.lastPage}}disabled{{/if}} />
<input type="submit" name="action" value="last" {{#if pagingData.lastPage}}disabled{{/if}} />
</form>
{{> suffix}} {{> suffix}}
</body> </body>
</html> </html>

View file

@ -25,3 +25,13 @@ fun SupportSQLiteDatabase.getIndexes(): Cursor {
fun SupportSQLiteDatabase.getTriggers(): Cursor { fun SupportSQLiteDatabase.getTriggers(): Cursor {
return this.query("SELECT * FROM sqlite_master WHERE type='trigger' ORDER BY name ASC") return this.query("SELECT * FROM sqlite_master WHERE type='trigger' ORDER BY name ASC")
} }
fun SupportSQLiteDatabase.getTableRowCount(table: String): Int {
return this.query("SELECT COUNT(*) FROM $table").use {
if (it.moveToFirst()) {
it.getInt(0)
} else {
0
}
}
}

View file

@ -11,7 +11,9 @@ import fi.iki.elonen.NanoHTTPD
import org.signal.core.util.ExceptionUtil import org.signal.core.util.ExceptionUtil
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import java.lang.IllegalArgumentException import java.lang.IllegalArgumentException
import kotlin.math.ceil
import kotlin.math.max import kotlin.math.max
import kotlin.math.min
/** /**
* The workhorse of this lib. Handles all of our our web routing and response generation. * The workhorse of this lib. Handles all of our our web routing and response generation.
@ -31,6 +33,7 @@ internal class SpinnerServer(
private val handlebars: Handlebars = Handlebars(AssetTemplateLoader(context)).apply { private val handlebars: Handlebars = Handlebars(AssetTemplateLoader(context)).apply {
registerHelper("eq", ConditionalHelpers.eq) registerHelper("eq", ConditionalHelpers.eq)
registerHelper("neq", ConditionalHelpers.neq)
} }
override fun serve(session: IHTTPSession): Response { override fun serve(session: IHTTPSession): Response {
@ -86,7 +89,22 @@ internal class SpinnerServer(
private fun postBrowse(dbName: String, db: SupportSQLiteDatabase, session: IHTTPSession): Response { private fun postBrowse(dbName: String, db: SupportSQLiteDatabase, session: IHTTPSession): Response {
val table: String = session.parameters["table"]?.get(0).toString() val table: String = session.parameters["table"]?.get(0).toString()
val query = "select * from $table" val pageSize: Int = session.parameters["pageSize"]?.get(0)?.toInt() ?: 1000
var pageIndex: Int = session.parameters["pageIndex"]?.get(0)?.toInt() ?: 0
val action: String? = session.parameters["action"]?.get(0)
val rowCount = db.getTableRowCount(table)
val pageCount = ceil(rowCount.toFloat() / pageSize.toFloat()).toInt()
when (action) {
"first" -> pageIndex = 0
"next" -> pageIndex = min(pageIndex + 1, pageCount - 1)
"previous" -> pageIndex = max(pageIndex - 1, 0)
"last" -> pageIndex = pageCount - 1
}
val query = "select * from $table limit $pageSize offset ${pageSize * pageIndex}"
val queryResult = db.query(query).toQueryResult()
return renderTemplate( return renderTemplate(
"browse", "browse",
@ -96,7 +114,15 @@ internal class SpinnerServer(
databases = databases.keys.toList(), databases = databases.keys.toList(),
tableNames = db.getTableNames(), tableNames = db.getTableNames(),
table = table, table = table,
queryResult = db.query(query).toQueryResult() queryResult = queryResult,
pagingData = PagingData(
rowCount = rowCount,
pageSize = pageSize,
pageIndex = pageIndex,
pageCount = pageCount,
startRow = pageSize * pageIndex,
endRow = min(pageSize * (pageIndex + 1), rowCount)
)
) )
) )
} }
@ -275,7 +301,8 @@ internal class SpinnerServer(
val databases: List<String>, val databases: List<String>,
val tableNames: List<String>, val tableNames: List<String>,
val table: String? = null, val table: String? = null,
val queryResult: QueryResult? = null val queryResult: QueryResult? = null,
val pagingData: PagingData? = null,
) )
data class QueryPageModel( data class QueryPageModel(
@ -308,4 +335,15 @@ internal class SpinnerServer(
val name: String, val name: String,
val sql: String val sql: String
) )
data class PagingData(
val rowCount: Int,
val pageSize: Int,
val pageIndex: Int,
val pageCount: Int,
val firstPage: Boolean = pageIndex == 0,
val lastPage: Boolean = pageIndex == pageCount - 1,
val startRow: Int,
val endRow: Int
)
} }