fixed config + cli-args + admin form
This commit is contained in:
parent
2671f43b8b
commit
af2e1bfdb2
24 changed files with 549 additions and 368 deletions
|
|
@ -34,3 +34,11 @@ manual scan (via cli?)
|
|||
curl -L -X 'GET' 'http://xrforge.isvery.ninja/models?page=1&order=name' -H 'accept: application/vnd.manyfold.v0+json'
|
||||
curl -L -X 'GET' 'http://xrforge.isvery.ninja/models?page=1&order=recent' -H 'accept: application/vnd.manyfold.v0+json'
|
||||
```
|
||||
|
||||
## Permacomputing Spirit
|
||||
|
||||
* developed on [Dillo](https://dillo-browser.github.io/) as lowest common denominator / compatibility
|
||||
* does not use javascript unless really needed (WebXR being the exception)
|
||||
* server is using lua-scripting via cosmopolitan libc's [redbean](https://redbean.dev)
|
||||
|
||||
> So yes in case you'd think the codebase is 90-ish: that's **exactly why it works** on potato-devices AND modern devices.
|
||||
|
|
|
|||
3
run.sh
Executable file
3
run.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
cd src
|
||||
../result/bin/xrforge.com -D . -- server
|
||||
|
|
@ -3,6 +3,8 @@ package.path = package.path .. ";src/.lua/?.lua"
|
|||
package.path = package.path .. ";middleware/?.lua"
|
||||
package.path = package.path .. ";cmd/?.lua"
|
||||
|
||||
print = function(...) Log(kLogInfo, ... or "''") end -- nice redbean logging from now on
|
||||
|
||||
util = require "util"
|
||||
json = require "json"
|
||||
|
||||
|
|
@ -15,24 +17,32 @@ dir = require "opendirectory"
|
|||
-- create
|
||||
app = require("soakbean") {
|
||||
bin = "./xrforge.com",
|
||||
bindir = arg[-1]:gsub("xrforge.com",""),
|
||||
cache = {},
|
||||
opts = {
|
||||
title="My XRForge experiences",
|
||||
subtitle="Portable XR experiences for PhoneVR, VRheadset, desktop & mobile."
|
||||
},
|
||||
opts = {},
|
||||
cmd={
|
||||
help = {file="help.lua", info="displays help cmds"},
|
||||
server = {file="server.lua", info="starts the webserver"}
|
||||
},
|
||||
title = 'XRForge - local-first XR experiences',
|
||||
subtitle = 'XRForge makes local-first XR easy',
|
||||
notes = {'🤩 portable selfsovereign', '🖧 JanusXR / XR Fragments', '♻ decentralized'}
|
||||
help = {file="cmd/help.lua", info="display all possible flags"},
|
||||
server = {file="cmd/server.lua", info="starts the webserver"}
|
||||
}
|
||||
}
|
||||
|
||||
-- api skeleton (implemented via soakbean's app.on(...))
|
||||
app.set = function(k,v) end
|
||||
app.init = function() end
|
||||
|
||||
-- load config
|
||||
app.opts = require('config')(app)
|
||||
|
||||
|
||||
app.runcmd(app) -- run clicmds
|
||||
|
||||
-- init URL router
|
||||
app.url['^/data'] = '/data.lua' -- setup custom file endpoint
|
||||
|
||||
app.url['^/$'] = '/index.lua' -- alias for app.tpl( LoadAsset('index.html'), app )
|
||||
app.get('^/admin/$', app.template('admin/index.html') ) -- alias for app.tpl( LoadAsset('index.html'), app )
|
||||
app.url['^/$'] = '/page/index.lua' -- alias for app.tpl( LoadAsset('index.html'), app )
|
||||
app.get('^/design[/]?$', util.pagerender('page/design.html'))
|
||||
|
||||
app.url['^/admin[/]?$'] = '/page/admin/index.lua'
|
||||
|
||||
app.post('^/save', function(req,res,next) -- setup inline POST endpoint
|
||||
-- also .get(), .put(), .delete(), .options()
|
||||
|
|
@ -43,23 +53,22 @@ app.post('^/save', function(req,res,next) -- setup inline POST endpoint
|
|||
end)
|
||||
|
||||
app --
|
||||
.use( require("httpauth")() )
|
||||
.use( require("middleware/httpauth")() )
|
||||
.use( require("json").middleware() ) -- try plug'n'play json API middleware
|
||||
.use( app.router( app.url ) ) -- try url router
|
||||
.use( app.response() ) -- try serve app response (if any)
|
||||
.use( function(req,next) Route() end) -- fallback default redbean fileserver
|
||||
|
||||
app.on('template', function(a,b,c,d,e)
|
||||
print("TEMPLATE!")
|
||||
end)
|
||||
|
||||
function OnHttpRequest() app.run() end
|
||||
|
||||
print("ja")
|
||||
--function OnHttpRequest()
|
||||
-- if( not dir.serve("./experiences") ) then
|
||||
-- print("default")
|
||||
-- Route()
|
||||
-- end
|
||||
--end
|
||||
--
|
||||
app.on('init', function()
|
||||
if assert(unix.fork()) == 0 then
|
||||
os.execute("ls ; sleep 5")
|
||||
print("ok")
|
||||
--local ok, headers, body = Fetch('http://127.0.0.1:8080/test')
|
||||
end
|
||||
end)
|
||||
|
||||
OnServerStart = function()
|
||||
app.init() -- this triggers init event
|
||||
end
|
||||
|
|
|
|||
1
src/.lua/cmd
Symbolic link
1
src/.lua/cmd
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../cmd
|
||||
51
src/.lua/config.lua
Normal file
51
src/.lua/config.lua
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
local util = require('util')
|
||||
|
||||
return function(app)
|
||||
|
||||
local config = { -- default
|
||||
name = "XRForge",
|
||||
baseurl="/",
|
||||
title="My XRForge experiences",
|
||||
subtitle="Portable XR experiences for Phone, VRheadset & desktop.",
|
||||
admin_title = "XRForge Admin",
|
||||
admin_subtitle = "Manage your XR experiences here",
|
||||
disk_dir = ".",
|
||||
manyfold_instance_1 = "https://xrforge.isvery.ninja",
|
||||
manyfold_instance_2 = "",
|
||||
manyfold_instance_3 = "",
|
||||
sync_interval = 30,
|
||||
sync_strategy = "recent"
|
||||
}
|
||||
|
||||
local configfile = "xrforge.lua"
|
||||
local savedconfig = util.readfile( app.bindir .. configfile, 'r', true) -- check local config
|
||||
or LoadAsset(configfile) -- then internal saved config
|
||||
|
||||
if savedconfig then
|
||||
local eval = function(str) return load(str)() end
|
||||
local status, result = pcall(eval, savedconfig ) -- Pass "string" as the first argument
|
||||
if not status then
|
||||
print("error: xrforge.lua contains errors:")
|
||||
else
|
||||
config = result -- overrule default config
|
||||
end
|
||||
end
|
||||
|
||||
app.on('set', function(k,v)
|
||||
if k == 'app.opts' then
|
||||
app.opts = v
|
||||
app.opts.updated = os.time()
|
||||
local newconfig = "app.on('init', function()\n\tprint('config loaded')\nend)\n\nreturn " .. util.dump(app.opts)
|
||||
newconfig = newconfig:gsub("^}$"," init = function() print('xrforge.lua config loaded') end\n}")
|
||||
util.writefile( app.bindir .. configfile, newconfig )
|
||||
print("stored xrforge.lua")
|
||||
end
|
||||
end)
|
||||
|
||||
-- store local config if not exist
|
||||
if not util.readfile( app.bindir .. configfile, 'r', true) then
|
||||
app.set('app.opts', config )
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
1
src/.lua/middleware
Symbolic link
1
src/.lua/middleware
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../middleware
|
||||
|
|
@ -23,7 +23,7 @@ sb = {
|
|||
sb.data[k] = (function(k,v)
|
||||
return function(a,b,c,d,e,f)
|
||||
v(a,b,c,d,e,f)
|
||||
sb.pub(k,v)
|
||||
sb.pub(k,v,a,b,c,d,e,f)
|
||||
end
|
||||
end)(k,v)
|
||||
else
|
||||
|
|
@ -38,10 +38,14 @@ sb = {
|
|||
return sb.app
|
||||
end,
|
||||
|
||||
pub = function(k,v)
|
||||
pub = function(k,v,a,b,c,d,e,f)
|
||||
if sb.handler[k] ~= nil then
|
||||
for i,handler in pairs(sb.handler[k]) do
|
||||
coroutine.wrap(handler)(v,k)
|
||||
if a then --
|
||||
coroutine.wrap(handler)(a,b,c,d,e,f) -- forward function args
|
||||
else
|
||||
coroutine.wrap(handler)(v,k) -- forward assignment
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
|
@ -187,13 +191,12 @@ sb = {
|
|||
end,
|
||||
|
||||
init = function(app)
|
||||
for k,v in pairs(argv) do
|
||||
app.opts[ v:gsub("=.*","") ] = v:gsub(".*=","")
|
||||
end
|
||||
if( keys(app.cmd) > 0 ) then sb.runcmd(app) end
|
||||
end,
|
||||
|
||||
runcmd = function(app)
|
||||
for k,v in pairs(argv) do
|
||||
app.opts[ v:gsub("=.*","") ] = v:gsub(".*=","")
|
||||
end
|
||||
for k,v in pairs(app.opts) do
|
||||
if app.cmd[k] then
|
||||
local file = app.cmd[k].file
|
||||
|
|
|
|||
|
|
@ -1,5 +1,26 @@
|
|||
local util = { }
|
||||
|
||||
util.readfile = function(filename, mode, silent)
|
||||
local file, err = io.open(filename, mode or "r")
|
||||
if not file then
|
||||
if not silent then print("Error opening file:", err) end
|
||||
return
|
||||
end
|
||||
local content = file:read("*a")
|
||||
file:close()
|
||||
return content
|
||||
end
|
||||
|
||||
util.writefile = function(filename, content, mode)
|
||||
local file, err = io.open(filename, mode or "w") -- Default write mode
|
||||
if not file then
|
||||
return print("Error opening file:", err)
|
||||
end
|
||||
file:write(content)
|
||||
file:close()
|
||||
end
|
||||
|
||||
|
||||
util.clone = function(orig)
|
||||
local orig_type = type(orig)
|
||||
local copy
|
||||
|
|
@ -28,11 +49,20 @@ util.flatten = function(tbl, prefix, result)
|
|||
return result
|
||||
end
|
||||
|
||||
util.pagerender = function(file,data)
|
||||
return function(req,res,next)
|
||||
res.status(200)
|
||||
res.header('content-type','text/html; charset=utf-8')
|
||||
res.body( util.template( LoadAsset(file),data or app) )
|
||||
next()
|
||||
end
|
||||
end
|
||||
|
||||
util.template = function(content,data)
|
||||
local finaldata = util.merge(app,{})
|
||||
local finaldata = util.merge(data or app,{})
|
||||
finaldata = util.merge(finaldata, util.flatten(app.opts,"opts") )
|
||||
finaldata.header = app.tpl( LoadAsset('template/header.html'), finaldata )
|
||||
finaldata.footer = app.tpl( LoadAsset('template/footer.html'), finaldata )
|
||||
finaldata.header = app.tpl( LoadAsset('page/header.html'), finaldata )
|
||||
finaldata.footer = app.tpl( LoadAsset('page/footer.html'), finaldata )
|
||||
return app.tpl( content, finaldata )
|
||||
end
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,13 +1,13 @@
|
|||
return function(app,argv)
|
||||
print("help!")
|
||||
foreach( app.cmd, function(k,v)
|
||||
io.write( app.bin .. " " .. k .. "\t\t # " .. v.info .. "\n")
|
||||
end)
|
||||
io.write("\nexample: " .. app.bin .. " title='My XRForge experiences'\n\n")
|
||||
io.write("Flags: (overrides xrforge.lua configfile)\n\n")
|
||||
foreach( app.opts, function(k,v)
|
||||
if not k:match("/") and not k:match("^help") then
|
||||
print( app.bin .. " -- " .. k .. "=...\t # '" .. v .. "' e.g." )
|
||||
if not k:match("/") and not k:match("^help") and not k:match("updated") then
|
||||
io.write( " " .. k .. "='" .. v .. "'\n")
|
||||
end
|
||||
end)
|
||||
foreach( app.cmd, function(k,v)
|
||||
print( app.bin .. " -- " .. k .. "\t\t # " .. v.info )
|
||||
end)
|
||||
|
||||
os.exit()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
.col2{ color:#AAD; }
|
||||
.col3{ color:#878; }
|
||||
.col4{ color:#7070ff; }
|
||||
.col5{ color:#557; }
|
||||
.col5{ color:#447; }
|
||||
.col5{ color:#224; }
|
||||
.col5{ color:#112; }
|
||||
|
||||
|
|
@ -40,7 +40,28 @@ td,div,p{
|
|||
line-height:24px;
|
||||
}
|
||||
|
||||
.btn{
|
||||
/* form elements */
|
||||
|
||||
input,
|
||||
select{
|
||||
box-sizing: border-box;
|
||||
margin: 0px 0px 10px 0px;
|
||||
padding:7px;
|
||||
display:block;
|
||||
max-width:300px;
|
||||
width:100%;
|
||||
background: #000;
|
||||
border: 1px solid #557;
|
||||
color: #AAD;
|
||||
}
|
||||
input[type=checkbox]{
|
||||
transform:scale(1.7) translate(3px,4px)
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
|
||||
.btn,
|
||||
input[type=submit]{
|
||||
display: inline-block;
|
||||
margin: 0px 10px 10px 0px;
|
||||
}
|
||||
|
|
@ -48,21 +69,28 @@ td,div,p{
|
|||
.btn a,
|
||||
.btn a:active,
|
||||
.btn a:visited,
|
||||
.btn a:link {
|
||||
.btn a:link,
|
||||
input[type=submit] {
|
||||
font-size:15px;
|
||||
display: inline-block;
|
||||
padding:8px 16px;
|
||||
color: #f3f;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.btn a:hover{
|
||||
.btn a:hover,
|
||||
input[type=submit] {
|
||||
color:#F7F;
|
||||
background:#000;
|
||||
}
|
||||
|
||||
.btn a, .border{ border:1px dotted #AAD; }
|
||||
.btn a,
|
||||
.border,
|
||||
input[type=submit]{
|
||||
border:1px dotted #AAD;
|
||||
}
|
||||
|
||||
a, a:active, a:visited, a:link {
|
||||
a, a:active, a:visited, a:link, input[type=submit] {
|
||||
text-decoration: none;
|
||||
color:#FFF;
|
||||
border-bottom: 1px dotted #AAD;
|
||||
|
|
@ -74,6 +102,27 @@ a:hover{
|
|||
border-bottom:1px dotted #f3f;
|
||||
}
|
||||
|
||||
table{
|
||||
table-layout: fixed;
|
||||
}
|
||||
table tr td {
|
||||
vertical-align: top;
|
||||
}
|
||||
form > table > tbody > tr > td{
|
||||
height:32px;
|
||||
}
|
||||
form > table > tbody > tr > td:nth-child(1) {
|
||||
font-weight:bold;
|
||||
padding-top: 4px;
|
||||
}
|
||||
form > table > tbody > tr > td:nth-child(3) {
|
||||
font-size: 13px;
|
||||
padding-top: 4px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.border.primary{ border:1px dotted #87a; }
|
||||
.border.secondary{ border:1px dotted #7070ff; }
|
||||
|
||||
|
|
@ -123,10 +172,17 @@ ul{
|
|||
padding-left:0.8em;
|
||||
}
|
||||
|
||||
.menu{
|
||||
text-align: right;
|
||||
}
|
||||
.menu a {
|
||||
padding-right:30px;
|
||||
}
|
||||
|
||||
.menu br {
|
||||
display:none
|
||||
}
|
||||
|
||||
.grid .tile{ border-radius:5px; }
|
||||
.grid .tile .text{ padding:3px 0px; }
|
||||
.grid .tile .img{
|
||||
|
|
@ -136,6 +192,35 @@ ul{
|
|||
|
||||
img.icon{ display:none; }
|
||||
|
||||
/* tab */
|
||||
|
||||
.tab{
|
||||
border-bottom: 1px solid #224;
|
||||
margin-bottom: 25px;
|
||||
margin-left: 140px;
|
||||
}
|
||||
.tab .label{
|
||||
display: block;
|
||||
background: #000;
|
||||
margin-bottom: -4px;
|
||||
width: 158px;
|
||||
margin-left: -140px;
|
||||
border-top: 1px dotted #557;
|
||||
border-left: 1px dotted #556;
|
||||
border-right: 1px dotted #556;
|
||||
padding: 9px 0px 0px 20px;
|
||||
|
||||
}
|
||||
|
||||
.notification{
|
||||
background: #7070ff;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border: 4px dashed #222;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
/* progressive enhancement quirks */
|
||||
@media (min-width:1px) {
|
||||
.grid .tile{
|
||||
|
|
@ -29,6 +29,13 @@ body{
|
|||
width:100%;
|
||||
margin: 0px 0px 15px 0px;
|
||||
}
|
||||
form table tr > th:nth-child(3),
|
||||
form table tr > td:nth-child(3) {
|
||||
display:none;
|
||||
}
|
||||
.menu br {
|
||||
display:initial !important;
|
||||
}
|
||||
}
|
||||
|
||||
.grid .tile .text{
|
||||
|
|
@ -44,8 +51,12 @@ body{
|
|||
}
|
||||
|
||||
.jumbotron{
|
||||
padding:20px 0px;
|
||||
padding:20px 20px;
|
||||
background:linear-gradient(45deg,#0000,#0000,#F7F2,#0000,#07F2,#0000,#0000);
|
||||
background:url(./../img/backdrop.jpg);
|
||||
background-size: cover;
|
||||
background-position: bottom;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
img.icon{
|
||||
|
|
@ -55,6 +66,6 @@ img.icon{
|
|||
width: 17px;
|
||||
}
|
||||
|
||||
.btn a.primary{ background: #ff33Ff; color:#000 !important;}
|
||||
.btn a.secondary{ background: #7070ff; color:#000 !important;}
|
||||
.btn .primary{ background: #ff33Ff; color:#000 !important;}
|
||||
.btn .secondary{ background: #7070ff; color:#000 !important;}
|
||||
|
||||
BIN
src/img/backdrop.jpg
Normal file
BIN
src/img/backdrop.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
128
src/page/admin/index.html
Normal file
128
src/page/admin/index.html
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
${header}
|
||||
|
||||
<div style="height:120px;" class="jumbotron">
|
||||
<h1>${opts.admin_title}</h1>
|
||||
${opts.admin_subtitle}
|
||||
</div>
|
||||
<hr style="margin-top:0">
|
||||
|
||||
${notification}
|
||||
|
||||
<div class="tab">
|
||||
<div class="label col2">
|
||||
Local content
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<div class="margin1">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<th width="165"/>
|
||||
<th />
|
||||
<th />
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Directory
|
||||
</td>
|
||||
<td >
|
||||
<input type="text" value="${opts.disk_dir}"></input>
|
||||
</td>
|
||||
<td class="col3">
|
||||
Directory to scan for experiences (use '.' for current)
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div class="tab">
|
||||
<div class="label col2">
|
||||
Manyfold instances
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="margin1">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<th width="165"/>
|
||||
<th />
|
||||
<th />
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Instance URL 1
|
||||
</td>
|
||||
<td >
|
||||
<input type="text" name="opts.manyfold_instance_1" value="${opts.manyfold_instance_1}"></input>
|
||||
</td>
|
||||
<td class="col3">
|
||||
<a href="https://manyfold.app/" target="_blank">Manyfold</a> URL goes here (https://xrforge.isvery.ninja e.g.)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Instance URL 2
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="opts.manyfold_instance_2" value="${opts.manyfold_instance_2}"></input>
|
||||
</td>
|
||||
<td class="col3">
|
||||
<a href="https://manyfold.app/" target="_blank">Manyfold</a> URL goes here (https://xrforge.isvery.ninja e.g.)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Instance URL 3
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="opts.manyfold_instance_3" value="${opts.manyfold_instance_3}"></input>
|
||||
</td>
|
||||
<td class="col3">
|
||||
<a href="https://manyfold.app/" target="_blank">Manyfold</a> URL goes here (https://xrforge.isvery.ninja e.g.)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Sync strategy
|
||||
</td>
|
||||
<td>
|
||||
<select value="${opts.manyfold_sync_strategy}">
|
||||
<option value="recent" default>only recent</option>
|
||||
<option value="all+recent">everything + recent</option>
|
||||
<option value="disabled">disabled</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="col3">
|
||||
Specify how manyfold instances should be synced.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Sync interval
|
||||
</td>
|
||||
<td>
|
||||
<select value="${opts.manyfold_sync_interval}">
|
||||
<option value="30">every 30 mins</option>
|
||||
<option value="15" selected>every 15 mins</option>
|
||||
<option value="5">every 5 minutes</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="col3">
|
||||
Specify how often manyfold instances should be checked for recent items.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="margin-left:165px">
|
||||
<br/>
|
||||
<div class="btn">
|
||||
<input type="submit" class="btn secondary" value="save" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
${footer}
|
||||
27
src/page/admin/index.lua
Normal file
27
src/page/admin/index.lua
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
local util = require("util")
|
||||
|
||||
local data = util.merge({notification=''},{ opts = app.opts })
|
||||
|
||||
if GetMethod() == 'POST' then
|
||||
local params = GetParams()
|
||||
local saveconfig = false
|
||||
foreach(params, function(k,v)
|
||||
if v[1]:match("^opts.") then
|
||||
app.opts[ v[1]:gsub("^opts.","") ] = v[2] -- update
|
||||
saveconfig = true
|
||||
end
|
||||
end)
|
||||
if saveconfig then
|
||||
app.set('app.opts', app.opts )
|
||||
data.notification = '<div class="notification">updated</div>'
|
||||
else
|
||||
data.notification = '<div class="notification">no changes detected</div>'
|
||||
end
|
||||
end
|
||||
|
||||
local html = util.template( LoadAsset("page/admin/index.html"),data)
|
||||
|
||||
|
||||
SetStatus(200)
|
||||
SetHeader('Content-Type', 'text/html; charset=utf-8')
|
||||
Write( html )
|
||||
127
src/page/design.html
Normal file
127
src/page/design.html
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
${header}
|
||||
|
||||
<h1>HEADER 1</h1>
|
||||
Lorem ipsum dolor sit amter.<br>
|
||||
Amet puti solor fati corpus <a href="#foo" >a link</a> flap.<br><br>
|
||||
<hr>
|
||||
|
||||
<div class="btn">
|
||||
<a href="#foo">button</a>
|
||||
</div>
|
||||
|
||||
<div class="btn">
|
||||
<a href="#foo" class="btn primary">button primary ⮮</a>
|
||||
</div>
|
||||
|
||||
<div class="btn">
|
||||
<a href="https://foo.com" target="_blank" class="btn secondary">button secondary ⮩</a>
|
||||
</div>
|
||||
<br>
|
||||
<hr>
|
||||
|
||||
<div class="tab">
|
||||
<div class="label col3">
|
||||
Category B
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="margin1">
|
||||
<form>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="165">
|
||||
Instance URL 1
|
||||
</td>
|
||||
<td >
|
||||
<input type="text"/>
|
||||
</td>
|
||||
<td class="col3">
|
||||
Infotext about input
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Sync interval
|
||||
</td>
|
||||
<td>
|
||||
<select>
|
||||
<option value="30">every 30 mins</option>
|
||||
<option value="15" selected>every 15 mins</option>
|
||||
<option value="5">every 5 minutes</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="col3">
|
||||
Infotext about select (tip: use selectboxes not checkboxes)
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<ul>
|
||||
<li>foo bar</li>
|
||||
<li>flop flap</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<pre>
|
||||
</pre>
|
||||
<pre>
|
||||
|
||||
┌─────────────────┐┌────────────────┐
|
||||
│ Foo CLI ││ Foo Web │
|
||||
└─────────────────┘└────────────────┘
|
||||
┌───────────────────────────────────┐
|
||||
│ Foo Repository │
|
||||
│ ┌────────┐ ┌────────┐ ┌─────────┐ │
|
||||
│ │ code │ │ issues │ │ patches │ │
|
||||
│ └────────┘ └────────┘ └─────────┘ │
|
||||
├───────────────────────────────────┤
|
||||
│ Foo Storage (Git) │
|
||||
└───────────────────────────────────┘
|
||||
┌────────────────┐┌─────────────────┐
|
||||
│ Foo Node ││ Foo HTTPD │
|
||||
├────────────────┤├─────────────────┤
|
||||
│ NoiseXK ││ HTTP + JSON │
|
||||
└────────────────┘└─────────────────┘
|
||||
</pre>
|
||||
<pre class="primary">
|
||||
|
||||
┌─────────────────┐┌────────────────┐
|
||||
│ Foo CLI ││ Foo Web │
|
||||
└─────────────────┘└────────────────┘
|
||||
┌───────────────────────────────────┐
|
||||
│ Foo Repository │
|
||||
│ ┌────────┐ ┌────────┐ ┌─────────┐ │
|
||||
│ │ code │ │ issues │ │ patches │ │
|
||||
│ └────────┘ └────────┘ └─────────┘ │
|
||||
├───────────────────────────────────┤
|
||||
│ Foo Storage (Git) │
|
||||
└───────────────────────────────────┘
|
||||
┌────────────────┐┌─────────────────┐
|
||||
│ Foo Node ││ Foo HTTPD │
|
||||
├────────────────┤├─────────────────┤
|
||||
│ NoiseXK ││ HTTP + JSON │
|
||||
└────────────────┘└─────────────────┘
|
||||
</pre>
|
||||
<pre class="secondary">
|
||||
|
||||
┌─────────────────┐┌────────────────┐
|
||||
│ Foo CLI ││ Foo Web │
|
||||
└─────────────────┘└────────────────┘
|
||||
┌───────────────────────────────────┐
|
||||
│ Foo Repository │
|
||||
│ ┌────────┐ ┌────────┐ ┌─────────┐ │
|
||||
│ │ code │ │ issues │ │ patches │ │
|
||||
│ └────────┘ └────────┘ └─────────┘ │
|
||||
├───────────────────────────────────┤
|
||||
│ Foo Storage (Git) │
|
||||
└───────────────────────────────────┘
|
||||
┌────────────────┐┌─────────────────┐
|
||||
│ Foo Node ││ Foo HTTPD │
|
||||
├────────────────┤├─────────────────┤
|
||||
│ NoiseXK ││ HTTP + JSON │
|
||||
└────────────────┘└─────────────────┘
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
${footer}
|
||||
|
|
@ -3,25 +3,28 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<base href="${opts.baseurl}" />
|
||||
<title>XRForge - selfsovereign interoperable XR experiences</title>
|
||||
<link rel="stylesheet" href="xrforge.css"></link>
|
||||
<link rel="stylesheet" href="css/xrforge.css"></link>
|
||||
</head>
|
||||
<body background="#000000">
|
||||
|
||||
<table width="100%" class="header">
|
||||
<tr>
|
||||
<td style="width:120px">
|
||||
<td width="100">
|
||||
<div class="margin1L">
|
||||
<div class="logo col1">XR<div class="logo col2">f̅o̅r̅g̅e̅</div>
|
||||
</div>
|
||||
<a href="${opts.baseurl}">
|
||||
<div class="logo col1">XR<div class="logo col2">f̅o̅r̅g̅e̅</div>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
<td class="menu">
|
||||
<div class="margin1L">
|
||||
<a href="#">Experiences</a>
|
||||
<a href="#">Collections</a>
|
||||
<a href="#">About</a>
|
||||
<a href="#">Howto</a>
|
||||
<a href="#">Experiences</a><br/>
|
||||
<a href="#">Collections</a><br/>
|
||||
<a href="#">About</a><br/>
|
||||
<a href="#">Howto</a><br/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -4,7 +4,7 @@ if not app.cache['index.html'] then
|
|||
app.cache['index.html'] = util.memoize(
|
||||
function()
|
||||
print("processing!")
|
||||
local html = util.template( LoadAsset("template/index.html"),app)
|
||||
local html = util.template( LoadAsset("page/index.html"),app)
|
||||
return html
|
||||
end,
|
||||
60*5 -- re-run every 5 mins (otherwise return cache)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
../result/bin/xrforge.com -D . -p 8081 -- server
|
||||
147
src/ui-kit.html
147
src/ui-kit.html
File diff suppressed because one or more lines are too long
1
src/xrforge.lua
Symbolic link
1
src/xrforge.lua
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../result/bin/xrforge.lua
|
||||
|
|
@ -25,7 +25,7 @@ download(){
|
|||
build(){
|
||||
download redbean
|
||||
cd src
|
||||
zip -r ../result/bin/xrforge.com * .lua .init.lua
|
||||
zip -r ../result/bin/xrforge.com * .lua .init.lua .args
|
||||
}
|
||||
|
||||
"$@"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue