280 lines
11 KiB
Nim
280 lines
11 KiB
Nim
import dom
|
|
import htmlutils.utils
|
|
import json
|
|
import streams
|
|
import tables
|
|
import strutils
|
|
import sets
|
|
from sequtils import map, apply
|
|
|
|
var pkgMap : JsonNode
|
|
|
|
const serverURL {.strdefine.}: string = "http://oggio88.soon.it/jpacrepo/"
|
|
|
|
type DownloadPanel = ref object
|
|
badge : Node
|
|
listgroup : Node
|
|
pkgs : HashSet[string]
|
|
footer : Node
|
|
|
|
proc newDownloadPanel(parent : Node) : DownloadPanel =
|
|
let dp = DownloadPanel()
|
|
dp.pkgs = initSet[string]()
|
|
htmlDocument(document, parent):
|
|
"div":
|
|
class ["panel", "panel-default"]
|
|
"div":
|
|
class ["panel-heading"]
|
|
"h3":
|
|
class ["panel-title"]
|
|
"a":
|
|
text "Package list "
|
|
"span":
|
|
class ["badge", "pull-right"]
|
|
style {"display" :"none"}
|
|
cb:
|
|
dp.badge = node
|
|
|
|
"ul":
|
|
class ["list-group"]
|
|
cb:
|
|
dp.listgroup = node
|
|
"div":
|
|
class ["panel-footer"]
|
|
style {
|
|
"text-align" : "right",
|
|
"display" :"none"
|
|
}
|
|
"button":
|
|
class ["btn", "btn-primary"]
|
|
attrs {"type" : "button"}
|
|
"span":
|
|
class ["glyphicon", "glyphicon-download"]
|
|
cb:
|
|
node.appendChild(document.createTextNode(" Download"))
|
|
let clickHandler = proc(e : Event) =
|
|
let pkglist : seq[string] = sequtils.toSeq(dp.pkgs.items())
|
|
let form = cast[Formelement](document.createElement("form"))
|
|
form.style.display = "none"
|
|
form.setAttribute("method", "post")
|
|
form.setAttribute("action", serverURL & "rest/pkg/downloadTar")
|
|
let tf= document.createElement("input")
|
|
tf.setAttribute("name", "pkgs")
|
|
let txt = sequtils.foldl(pkglist, a & " " & b)
|
|
echo txt
|
|
tf.value(txt)
|
|
form.appendChild(tf)
|
|
document.body.appendChild(form)
|
|
form.submit()
|
|
node.addEventListener("click", clickHandler)
|
|
cb:
|
|
dp.footer = node
|
|
dp
|
|
|
|
|
|
proc updateBadge(dp : DownloadPanel) =
|
|
let st = if dp.pkgs.len() > 0: "block" else: "none"
|
|
dp.footer.style.display = st
|
|
dp.badge.style.display = st
|
|
dp.badge.textContent = $dp.pkgs.len()
|
|
|
|
proc addPkg(dp : DownloadPanel, pkgfile : string) =
|
|
if not dp.pkgs.contains(pkgfile):
|
|
dp.pkgs.incl(pkgfile)
|
|
htmlDocument(document, dp.listgroup):
|
|
"li":
|
|
var listElement : Node
|
|
class ["list-group-item"]
|
|
text pkgfile
|
|
"span":
|
|
class ["glyphicon", "glyphicon-remove", "pull-right"]
|
|
cb:
|
|
let fn = proc(e : Event) =
|
|
dp.pkgs.excl(pkgfile)
|
|
listElement.remove()
|
|
dp.updateBadge
|
|
node.addEventListener("click", fn)
|
|
cb:
|
|
listElement = node
|
|
|
|
dp.updateBadge
|
|
|
|
proc createDropdown(parent : Node, data :seq[string], onchange : proc(value : string)) =
|
|
htmlDocument(document, parent):
|
|
"div":
|
|
var button : Node
|
|
class ["dropdown"]
|
|
"button":
|
|
class ["btn", "btn-default", "dropdown-toggle"]
|
|
attrs {"data-toggle": "dropdown", "type": "button"}
|
|
cb:
|
|
for line in data:
|
|
node.textContent = line
|
|
break
|
|
button = node
|
|
"ul":
|
|
class ["dropdown-menu"]
|
|
cb:
|
|
for line in data:
|
|
htmlDocument(document, node):
|
|
"li":
|
|
"a":
|
|
text line
|
|
cb:
|
|
let fn = proc(e: Event) =
|
|
button.textContent = node.textContent
|
|
onchange($node.textContent)
|
|
node.addEventListener("click", fn)
|
|
|
|
type PkgTable = ref object
|
|
addButton : Node
|
|
|
|
proc newPkgTable(parent: Node, searchString : string) : PkgTable =
|
|
var pkgtable = PkgTable()
|
|
var fragments = newSeq[string]()
|
|
for fragment in searchString.splitWhitespace():
|
|
fragments.add(fragment)
|
|
var searchResult = newOrderedTable[string,JsonNode]()
|
|
for key, value in pkgMap:
|
|
for fragment in fragments:
|
|
if fragment in key:
|
|
searchResult.add(key,value)
|
|
for table in document.querySelectorAll("table.pkgtable"):
|
|
table.parentNode.removeChild(table)
|
|
htmlDocument(document, parent):
|
|
"table":
|
|
class ["table", "table-striped","pkgtable"]
|
|
"thead":
|
|
"tr":
|
|
"th":
|
|
"button":
|
|
class ["btn", "btn-default"]
|
|
attrs {"type": "button"}
|
|
"span":
|
|
class ["glyphicon", "glyphicon-plus"]
|
|
cb:
|
|
let txt = document.createTextNode(" Add")
|
|
node.appendChild(txt)
|
|
pkgtable.addButton = node
|
|
"th":
|
|
text "Name"
|
|
"th":
|
|
text "Version"
|
|
"th":
|
|
text "Arch"
|
|
"tbody":
|
|
cb:
|
|
var i = 0
|
|
for name, versions in searchResult:
|
|
closureScope:
|
|
htmlDocument(document, node):
|
|
"tr":
|
|
var archCell : Node
|
|
"td":
|
|
"div":
|
|
class ["checkbox"]
|
|
"label":
|
|
"input":
|
|
attrs {"type" : "checkbox"}
|
|
"td":
|
|
text $name
|
|
"td":
|
|
cb:
|
|
var data = newSeq[string]()
|
|
for version, arches in versions:
|
|
data.add(version)
|
|
let vs = versions
|
|
let change_callback = proc(newValue : string) =
|
|
archCell.removeChildren()
|
|
var newdata = newSeq[string]()
|
|
for arch, pkgname in vs[newValue]:
|
|
newdata.add(arch)
|
|
createDropdown(archCell, newdata, proc(s : string) = discard)
|
|
createDropdown(node, data, change_callback)
|
|
"td":
|
|
cb:
|
|
archCell = node
|
|
var data = newSeq[string]()
|
|
var arches : JsonNode
|
|
for v, a in versions:
|
|
arches = a
|
|
for arch, pkgname in arches:
|
|
data.add(arch)
|
|
createDropdown(node, data, proc(s : string) = discard)
|
|
pkgtable
|
|
|
|
var dp : DownloadPanel
|
|
# var pkgTable : PkgTable
|
|
htmlDocument document, document.body:
|
|
# "img":
|
|
# attrs {"src" : "img/background.bpg"}
|
|
# style {
|
|
# "width" : "100%",
|
|
# "position" : "fixed",
|
|
# "bottom" : "0",
|
|
# "left" : "0",
|
|
# "z-index" : "-10"
|
|
# }
|
|
"div":
|
|
var table : Node
|
|
style {"background-color" : "rgba(255, 255, 255, 0.25)"}
|
|
class ["container"]
|
|
"div":
|
|
style {
|
|
"margin-top" : "20px",
|
|
"background-color" : "rgba(224, 224, 224, 0.5)"
|
|
}
|
|
class ["jumbotron"]
|
|
"h1":
|
|
text "Jpacrepo"
|
|
"p":
|
|
text "Personal archlinux package repository"
|
|
"div":
|
|
"form":
|
|
class ["form-horizontal"]
|
|
"div":
|
|
class ["form-group"]
|
|
"label":
|
|
class ["control-label", "col-sm-2"]
|
|
text " Search package"
|
|
"div":
|
|
class ["col-sm-10"]
|
|
"input":
|
|
class ["form-control"]
|
|
attrs {"type" : "text"}
|
|
cb :
|
|
proc add2DownloadList(e : Event) =
|
|
let rows = table.querySelectorAll("tbody tr")
|
|
for row in rows:
|
|
let cbox = row.querySelector("td:first-child input")
|
|
if cbox.checked:
|
|
let pkgname = $row.querySelector("td:nth-child(2)").textContent
|
|
let version = $row.querySelector("td:nth-child(3) button").textContent
|
|
let arch = $row.querySelector("td:nth-child(4) button").textContent
|
|
dp.addPkg(pkgMap[pkgname][version][arch].getStr)
|
|
proc oninput(e : Event) =
|
|
if pkgMap.len == 0 or node.value.len < 2: return
|
|
let pkgtable = newPkgTable(table, $node.value)
|
|
pkgtable.addButton.addEventListener("click", add2DownloadList)
|
|
node.addEventListener("input", oninput)
|
|
"div":
|
|
class ["row"]
|
|
"div":
|
|
class ["col-sm-3"]
|
|
cb:
|
|
dp = newDownloadPanel(node)
|
|
"div":
|
|
class ["col-sm-9"]
|
|
cb:
|
|
table = node
|
|
|
|
|
|
|
|
let r = newXMLHTTPRequest()
|
|
let load_cb = proc(e : Event) =
|
|
pkgMap = parseJson($r.responseText)
|
|
r.addEventListener("load", load_cb)
|
|
r.open("get", serverURL & "rest/pkg/map")
|
|
r.setRequestHeader("Accept", "application/json")
|
|
r.send()
|