removed Nim source
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "nim/lib/htmlutils"]
|
|
||||||
path = nim/lib/htmlutils
|
|
||||||
url = git.woggioni.net:htmlutils
|
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env nim
|
|
||||||
|
|
||||||
task build, "builds an example":
|
|
||||||
setCommand "js"
|
|
||||||
#os.copyfile("")
|
|
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
nim js src/jpacrepo.nim
|
|
||||||
cp nimcache/jpacrepo.js static
|
|
Submodule nim/lib/htmlutils deleted from 5ee04565fa
@@ -1 +0,0 @@
|
|||||||
path="lib/htmlutils/src"
|
|
@@ -1,375 +0,0 @@
|
|||||||
import dom
|
|
||||||
import htmlutils/tree
|
|
||||||
import htmlutils/utils
|
|
||||||
import json
|
|
||||||
import tables
|
|
||||||
import strutils
|
|
||||||
import sets
|
|
||||||
from sequtils import map, apply
|
|
||||||
|
|
||||||
var pkgMap : JsonNode
|
|
||||||
|
|
||||||
const serverURL {.strdefine.}: string = ""
|
|
||||||
|
|
||||||
proc last[T](s : seq[T]) : T = s[s.len - 1]
|
|
||||||
proc formatByteSize(size : BiggestInt) : string = size.float64.formatEng(precision=1, siPrefix=true, unit = "B")
|
|
||||||
|
|
||||||
type DownloadPanel = ref object
|
|
||||||
badge : Element
|
|
||||||
listgroup : Element
|
|
||||||
pkgs : HashSet[string]
|
|
||||||
footer : Element
|
|
||||||
sizeLabel : Element
|
|
||||||
size : BiggestInt
|
|
||||||
|
|
||||||
proc newDownloadPanel(parent : Element) : DownloadPanel =
|
|
||||||
let dp = DownloadPanel()
|
|
||||||
dp.pkgs = initHashSet[string]()
|
|
||||||
htmlTreeAppend(parent):
|
|
||||||
"div":
|
|
||||||
classList = ["panel", "panel-default"]
|
|
||||||
"div":
|
|
||||||
classList = ["panel-heading"]
|
|
||||||
"h3":
|
|
||||||
classList = ["panel-title"]
|
|
||||||
"a":
|
|
||||||
text = "Package list "
|
|
||||||
"span":
|
|
||||||
classList = ["badge", "pull-right"]
|
|
||||||
style {"display" :"none"}
|
|
||||||
cb:
|
|
||||||
dp.badge = elem
|
|
||||||
|
|
||||||
"ul":
|
|
||||||
classList = ["list-group"]
|
|
||||||
cb:
|
|
||||||
dp.listgroup = elem
|
|
||||||
"div":
|
|
||||||
classList = ["panel-footer"]
|
|
||||||
style = {
|
|
||||||
"text-align" : "right",
|
|
||||||
"display" :"none"
|
|
||||||
}
|
|
||||||
"span":
|
|
||||||
style = {
|
|
||||||
"font-weight" : "bold",
|
|
||||||
"padding-right" : "10px"
|
|
||||||
}
|
|
||||||
cb:
|
|
||||||
dp.sizeLabel = elem
|
|
||||||
"button":
|
|
||||||
classList = ["btn", "btn-primary"]
|
|
||||||
attrs = {"type" : "button"}
|
|
||||||
"span":
|
|
||||||
classList = ["glyphicon", "glyphicon-download"]
|
|
||||||
cb:
|
|
||||||
elem.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 & "api/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()
|
|
||||||
elem.addEventListener("click", clickHandler)
|
|
||||||
cb:
|
|
||||||
dp.footer = elem
|
|
||||||
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 updateSize(dp : DownloadPanel) =
|
|
||||||
dp.sizeLabel.textContent = "Total: " & dp.size.formatByteSize
|
|
||||||
|
|
||||||
proc addPkg(dp : DownloadPanel, pkgfile : string) =
|
|
||||||
if not dp.pkgs.contains(pkgfile):
|
|
||||||
dp.pkgs.incl(pkgfile)
|
|
||||||
let req = newXMLHTTPRequest()
|
|
||||||
let load_cb = proc(e : Event) =
|
|
||||||
let sz = parseInt($req.responseText)
|
|
||||||
dp.size += sz
|
|
||||||
dp.updateSize
|
|
||||||
htmlTreeAppend(dp.listgroup):
|
|
||||||
"li":
|
|
||||||
var listElement : Element
|
|
||||||
classList = ["list-group-item"]
|
|
||||||
text = pkgfile
|
|
||||||
"span":
|
|
||||||
classList = ["glyphicon", "glyphicon-remove", "pull-right"]
|
|
||||||
cb:
|
|
||||||
let fn = proc(e : Event) =
|
|
||||||
dp.pkgs.excl(pkgfile)
|
|
||||||
listElement.remove()
|
|
||||||
dp.updateBadge
|
|
||||||
dp.size -= sz
|
|
||||||
dp.updateSize
|
|
||||||
elem.addEventListener("click", fn)
|
|
||||||
cb:
|
|
||||||
listElement = elem
|
|
||||||
req.addEventListener("load", load_cb)
|
|
||||||
req.open("get", serverURL & "api/pkg/filesize/" & pkgfile)
|
|
||||||
req.setRequestHeader("Accept", "application/json")
|
|
||||||
req.send()
|
|
||||||
dp.updateBadge
|
|
||||||
|
|
||||||
proc readTableRow(arch : string, row : Element) : JsonNode =
|
|
||||||
let pkgname = $row.querySelector("td:nth-child(2)").textContent
|
|
||||||
let version = $row.querySelector("td:nth-child(3) button").textContent
|
|
||||||
let filename = $row.querySelector("td:nth-child(4) button").textContent
|
|
||||||
for candidate in pkgMap[arch][pkgname][version]:
|
|
||||||
if filename == candidate["fileName"].getStr:
|
|
||||||
return candidate
|
|
||||||
|
|
||||||
proc createDropdown(parent : Element, data :seq[string], onchange : proc(value : string)) =
|
|
||||||
|
|
||||||
htmlTreeAppend(parent):
|
|
||||||
"span":
|
|
||||||
var button : Element
|
|
||||||
classList = ["dropdown"]
|
|
||||||
"button":
|
|
||||||
classList = ["btn", "btn-default", "dropdown-toggle"]
|
|
||||||
attrs = {"data-toggle": "dropdown", "type": "button"}
|
|
||||||
cb:
|
|
||||||
elem.textContent = data[0]
|
|
||||||
button = elem
|
|
||||||
"ul":
|
|
||||||
classList = ["dropdown-menu"]
|
|
||||||
cb:
|
|
||||||
for line in data:
|
|
||||||
htmlTreeAppend(elem):
|
|
||||||
"li":
|
|
||||||
"a":
|
|
||||||
text = line
|
|
||||||
cb:
|
|
||||||
let fn = proc(e: Event) =
|
|
||||||
button.textContent = elem.textContent
|
|
||||||
onchange($elem.textContent)
|
|
||||||
elem.addEventListener("click", fn)
|
|
||||||
|
|
||||||
type PkgTable = ref object
|
|
||||||
addButton : Element
|
|
||||||
|
|
||||||
proc newPkgTable(parent: Element, arch: string, searchString : string, addButtonCallback : proc(e : Event)) : 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[arch]:
|
|
||||||
for fragment in fragments:
|
|
||||||
if fragment in key:
|
|
||||||
searchResult[key] = value
|
|
||||||
for node in parent.querySelectorAll("table.pkgtable"):
|
|
||||||
parent.removeChild(node)
|
|
||||||
htmlTreeAppend(parent):
|
|
||||||
"table":
|
|
||||||
classList = ["table", "table-striped","pkgtable"]
|
|
||||||
"thead":
|
|
||||||
"tr":
|
|
||||||
"th":
|
|
||||||
"button":
|
|
||||||
classList = ["btn", "btn-default"]
|
|
||||||
attrs = {"type": "button"}
|
|
||||||
"span":
|
|
||||||
classList = ["glyphicon", "glyphicon-plus"]
|
|
||||||
cb:
|
|
||||||
let txt = document.createTextNode(" Add")
|
|
||||||
elem.appendChild(txt)
|
|
||||||
pkgtable.addButton = elem
|
|
||||||
"th":
|
|
||||||
text = "Name"
|
|
||||||
"th":
|
|
||||||
text = "Version"
|
|
||||||
"th":
|
|
||||||
text = "File name"
|
|
||||||
"th":
|
|
||||||
text = "Installed size"
|
|
||||||
"tbody":
|
|
||||||
cb:
|
|
||||||
var i = 0
|
|
||||||
for name, versions in searchResult.mpairs:
|
|
||||||
|
|
||||||
closureScope:
|
|
||||||
htmlTreeAppend(elem):
|
|
||||||
"tr":
|
|
||||||
var row : Element
|
|
||||||
var fileNameCell : Element
|
|
||||||
var sizeCell : Element
|
|
||||||
let size_change_callback = proc(newValue : string) =
|
|
||||||
sizeCell.textContent = readTableRow(arch, row)["size"].getInt.formatByteSize
|
|
||||||
|
|
||||||
"td":
|
|
||||||
"div":
|
|
||||||
classList = ["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) =
|
|
||||||
fileNameCell.removeChildren()
|
|
||||||
var newdata = newSeq[string]()
|
|
||||||
for arch, pkgname in vs[newValue]:
|
|
||||||
newdata.add(arch)
|
|
||||||
createDropdown(fileNameCell, newdata, size_change_callback)
|
|
||||||
size_change_callback(newValue)
|
|
||||||
createDropdown(elem, data, change_callback)
|
|
||||||
"td":
|
|
||||||
cb:
|
|
||||||
fileNameCell = elem
|
|
||||||
var data = newSeq[string]()
|
|
||||||
var files : JsonNode
|
|
||||||
for v, f in versions:
|
|
||||||
files = f
|
|
||||||
break
|
|
||||||
for file in files:
|
|
||||||
data.add(file["fileName"].getStr)
|
|
||||||
createDropdown(elem, data, size_change_callback)
|
|
||||||
"td":
|
|
||||||
cb:
|
|
||||||
sizeCell = elem
|
|
||||||
for v, files in versions:
|
|
||||||
for file in files:
|
|
||||||
elem.textContent = file["size"].getInt.formatByteSize
|
|
||||||
return
|
|
||||||
cb:
|
|
||||||
row = elem
|
|
||||||
pkgtable.addButton.addEventListener("click", addButtonCallback)
|
|
||||||
pkgtable
|
|
||||||
|
|
||||||
var selectedArch : string
|
|
||||||
var archButtons : Element
|
|
||||||
var table : Element
|
|
||||||
var searchString : string
|
|
||||||
var add2DownloadList : proc(e : Event)
|
|
||||||
|
|
||||||
proc updateTable(e : Event) =
|
|
||||||
if pkgMap.len == 0 or searchString.len < 2: return
|
|
||||||
discard newPkgTable(table, selectedArch, searchString, add2DownloadList)
|
|
||||||
|
|
||||||
var dp : DownloadPanel
|
|
||||||
# var pkgTable : PkgTable
|
|
||||||
htmlTreeappend document.body:
|
|
||||||
# "img":
|
|
||||||
# attrs {"src" : "img/background.bpg"}
|
|
||||||
# style {
|
|
||||||
# "width" : "100%",
|
|
||||||
# "position" : "fixed",
|
|
||||||
# "bottom" : "0",
|
|
||||||
# "left" : "0",
|
|
||||||
# "z-index" : "-10"
|
|
||||||
# }
|
|
||||||
"div":
|
|
||||||
style = {"background-color" : "rgba(255, 255, 255, 0.25)"}
|
|
||||||
classList = ["container"]
|
|
||||||
"div":
|
|
||||||
style = {
|
|
||||||
"margin-top" : "20px",
|
|
||||||
"background-color" : "rgba(224, 224, 224, 0.5)"
|
|
||||||
}
|
|
||||||
classList = ["jumbotron"]
|
|
||||||
"h1":
|
|
||||||
text = "Jpacrepo"
|
|
||||||
"p":
|
|
||||||
text = "Personal archlinux package repository"
|
|
||||||
"div":
|
|
||||||
"form":
|
|
||||||
classList = ["form-horizontal"]
|
|
||||||
"div":
|
|
||||||
classList = ["form-group"]
|
|
||||||
"label":
|
|
||||||
classList = ["control-label", "col-sm-2"]
|
|
||||||
text = " Search package"
|
|
||||||
"div":
|
|
||||||
classList = ["col-sm-10"]
|
|
||||||
"input":
|
|
||||||
classList = ["form-control"]
|
|
||||||
attrs = {"type" : "text"}
|
|
||||||
cb :
|
|
||||||
add2DownloadList = proc(e : Event) =
|
|
||||||
let rows = table.querySelectorAll("tbody tr")
|
|
||||||
for row in rows:
|
|
||||||
let cbox = row.querySelector("td:first-child input")
|
|
||||||
if cbox.checked:
|
|
||||||
dp.addPkg(readTableRow(selectedArch, row)["fileName"].getStr)
|
|
||||||
oninput:
|
|
||||||
searchString = $elem.value
|
|
||||||
updateTable(event)
|
|
||||||
"div":
|
|
||||||
classList = ["row"]
|
|
||||||
"div":
|
|
||||||
classList = ["col-sm-3"]
|
|
||||||
cb:
|
|
||||||
dp = newDownloadPanel(elem)
|
|
||||||
"div":
|
|
||||||
"div":
|
|
||||||
classList = ["btn-group", "btn-group-justified"]
|
|
||||||
attrs = { "role" : "group" }
|
|
||||||
cb:
|
|
||||||
archButtons = elem
|
|
||||||
classList = ["col-sm-9"]
|
|
||||||
cb:
|
|
||||||
table = elem
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let r = newXMLHTTPRequest()
|
|
||||||
let load_cb = proc(e : Event) =
|
|
||||||
pkgMap = parseJson($r.responseText)
|
|
||||||
var buttons = newSeq[Element]()
|
|
||||||
var index = 0
|
|
||||||
for arch in pkgMap.keys:
|
|
||||||
closureScope:
|
|
||||||
htmlTreeAppend(archButtons):
|
|
||||||
"div":
|
|
||||||
classList = ["btn-group"]
|
|
||||||
attrs = { "role" : "group"}
|
|
||||||
"button":
|
|
||||||
classList = ["btn", "btn-default"]
|
|
||||||
attrs = {
|
|
||||||
"type": "button",
|
|
||||||
}
|
|
||||||
text = arch
|
|
||||||
let thisButtonIndex = index
|
|
||||||
let thisButtonArch = arch
|
|
||||||
onclick:
|
|
||||||
let update = thisButtonArch != selectedArch
|
|
||||||
selectedArch = thisButtonArch
|
|
||||||
for i in 0..<buttons.len:
|
|
||||||
let btn = buttons[i]
|
|
||||||
if(i == thisButtonIndex):
|
|
||||||
btn.classList.toggle("active")
|
|
||||||
else:
|
|
||||||
btn.classList.remove("active")
|
|
||||||
if update:
|
|
||||||
updateTable(event)
|
|
||||||
cb:
|
|
||||||
buttons.add(elem)
|
|
||||||
if index == 0:
|
|
||||||
selectedArch = arch
|
|
||||||
elem.classList.add("active")
|
|
||||||
inc(index)
|
|
||||||
# createDropdown(archDropDown, data, arch_change_callback)
|
|
||||||
|
|
||||||
r.addEventListener("load", load_cb)
|
|
||||||
r.open("get", serverURL & "api/pkg/map")
|
|
||||||
r.setRequestHeader("Accept", "application/json")
|
|
||||||
r.send()
|
|
@@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="jpacrepo.css" type="text/css">
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
|
||||||
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
|
||||||
<script src="jpacrepo.js" defer></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Reference in New Issue
Block a user