1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-26 01:04:06 +08:00

mac opt web.render

This commit is contained in:
shaoying 2018-08-15 00:45:04 +08:00
parent 8f37fd7b23
commit 7ef9f2d59f
8 changed files with 152 additions and 163 deletions

View File

@ -1,5 +1,4 @@
login root root login root root
source etc/local.shy source etc/local.shy
~file1 ~file1

View File

@ -83,12 +83,10 @@ func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
} }
if m.Has("pub") { if m.Has("pub") {
s.public = m.Optionv("public").(*rsa.PublicKey) s.public = m.Optionv("public").(*rsa.PublicKey)
m.Log("fuck", "public %v", s.public)
} }
if m.Has("key") { if m.Has("key") {
s.private = m.Optionv("private").(*rsa.PrivateKey) s.private = m.Optionv("private").(*rsa.PrivateKey)
s.public = &s.private.PublicKey s.public = &s.private.PublicKey
m.Log("fuck", "public %v", s.public)
} }
@ -194,7 +192,6 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
m.Optionv("private", private) m.Optionv("private", private)
} }
m.Log("fuck", "stream %s", stream)
if stream != "" { if stream != "" {
m.Start(m.Confx("aaa_name"), m.Confx("aaa_help"), arg[0], "", aaa.Session(arg[0])) m.Start(m.Confx("aaa_name"), m.Confx("aaa_help"), arg[0], "", aaa.Session(arg[0]))
m.Cap("stream", stream) m.Cap("stream", stream)
@ -244,7 +241,6 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
m.Travel(func(m *ctx.Message, line int) bool { m.Travel(func(m *ctx.Message, line int) bool {
if line > 0 && m.Cap("username") == arg[0] { if line > 0 && m.Cap("username") == arg[0] {
if m.Cap("password") == aaa.Password(arg[1]) { if m.Cap("password") == aaa.Password(arg[1]) {
m.Log("fuck", "%v", m.Format())
m.Sess("aaa", m.Target()) m.Sess("aaa", m.Target())
m.Echo(m.Cap("sessid")) m.Echo(m.Cap("sessid"))
} else { } else {
@ -442,7 +438,6 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
b := make([]byte, bsize) b := make([]byte, bsize)
copy(b, content[pos:end]) copy(b, content[pos:end])
m.Log("fuck", "pos: %d end: %d", pos, end)
aaa.encrypt.CryptBlocks(buf[pos:pos+bsize], b) aaa.encrypt.CryptBlocks(buf[pos:pos+bsize], b)
} }
@ -466,7 +461,6 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
content, arg = []byte(arg[0]), arg[1:] content, arg = []byte(arg[0]), arg[1:]
} }
m.Log("fuck", "why %v", content)
buf := make([]byte, 1024) buf := make([]byte, 1024)
n, e := base64.StdEncoding.Decode(buf, content) n, e := base64.StdEncoding.Decode(buf, content)
m.Assert(e) m.Assert(e)

View File

@ -203,7 +203,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
// }}} // }}}
}}, }},
"cli_help": &ctx.Config{Name: "cli_help", Value: "shell", Help: "模块文档"}, "cli_help": &ctx.Config{Name: "cli_help", Value: "shell", Help: "模块文档"},
"cmd_timeout": &ctx.Config{Name: "cmd_timeout", Value: "10s", Help: "系统命令超时"}, "cmd_timeout": &ctx.Config{Name: "cmd_timeout", Value: "60s", Help: "系统命令超时"},
"time_format": &ctx.Config{Name: "time_format", Value: "2006-01-02 15:04:05", Help: "时间格式"}, "time_format": &ctx.Config{Name: "time_format", Value: "2006-01-02 15:04:05", Help: "时间格式"},
"time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"}, "time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"},

View File

@ -1934,10 +1934,11 @@ var CGI = template.FuncMap{
} }
return "" return ""
}, // }}} }, // }}}
"msg": func(arg ...interface{}) string { // {{{ "msg": func(arg ...interface{}) interface{} { // {{{
if len(arg) == 0 { if len(arg) == 0 {
return "" return ""
} }
if m, ok := arg[0].(*Message); ok { if m, ok := arg[0].(*Message); ok {
if len(arg) == 1 { if len(arg) == 1 {
return fmt.Sprintf("%v", m.Format()) return fmt.Sprintf("%v", m.Format())
@ -1946,8 +1947,10 @@ var CGI = template.FuncMap{
switch which := arg[1].(type) { switch which := arg[1].(type) {
case string: case string:
switch which { switch which {
case "spawn":
return m.Spawn()
case "code": case "code":
return fmt.Sprintf("%d", m.code) return m.code
case "time": case "time":
return m.time.Format("2006-01-02 15:04:05") return m.time.Format("2006-01-02 15:04:05")
case "source": case "source":
@ -1955,21 +1958,22 @@ var CGI = template.FuncMap{
case "target": case "target":
return m.target.Name return m.target.Name
case "message": case "message":
return fmt.Sprintf("%d", m.message.code) return m.message
case "messages": case "messages":
msg := []string{} return m.messages
for _, v := range m.messages {
msg = append(msg, fmt.Sprintf("%d", v.code))
}
return strings.Join(msg, " ")
case "sessions": case "sessions":
msg := []string{} return m.Sessions
for k, _ := range m.Sessions { default:
msg = append(msg, fmt.Sprintf("%s", k)) return m.Sess(which)
}
return strings.Join(msg, " ")
} }
case int: case int:
ms := []*Message{m}
for i := 0; i < len(ms); i++ {
if ms[i].code == which {
return ms[i]
}
ms = append(ms, ms[i].messages...)
}
} }
} }
return "" return ""
@ -2011,7 +2015,6 @@ var CGI = template.FuncMap{
} }
if m, ok := arg[0].(*Message); ok { if m, ok := arg[0].(*Message); ok {
if len(arg) == 1 { if len(arg) == 1 {
list := []string{} list := []string{}
for k, _ := range m.target.Configs { for k, _ := range m.target.Configs {
@ -3175,14 +3178,18 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
"right": &Command{ "right": &Command{
Name: "right [share|add|del group [cache|config|command item]]", Name: "right [share|add|del group [cache|config|command item]]",
Help: "用户组管理,查看、添加、删除用户组或是接口", Help: "用户组管理,查看、添加、删除用户组或是接口",
Form: map[string]int{"target": 1},
Hand: func(m *Message, c *Context, key string, arg ...string) { Hand: func(m *Message, c *Context, key string, arg ...string) {
index := m.target.Index // {{{ owner := m.target // {{{
if m.Has("target") {
owner = m.Find(m.Option("target")).target
}
index := owner.Index
if index == nil { if index == nil {
index = map[string]*Context{} index = map[string]*Context{}
m.target.Index = index owner.Index = index
} }
owner := m.target
aaa := m.Sess("aaa", false) aaa := m.Sess("aaa", false)
if aaa.Cap("username") != aaa.Conf("rootname") { if aaa.Cap("username") != aaa.Conf("rootname") {
owner = index[aaa.Cap("username")] owner = index[aaa.Cap("username")]
@ -3268,7 +3275,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
return return
} }
case "command": case "command":
m.Log("fuck", "what %v %v", share.Name, arg[2])
if x, ok := share.Commands[arg[2]]; ok { if x, ok := share.Commands[arg[2]]; ok {
m.Log("fuck", "what")
if len(arg) == 3 { if len(arg) == 3 {
m.Echo("ok") m.Echo("ok")
break break
@ -3292,6 +3301,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
} }
m.Echo("ok") m.Echo("ok")
} }
m.Log("fuck", "what")
} }
case "add": case "add":
switch arg[1] { switch arg[1] {

View File

@ -38,6 +38,7 @@ func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
func (log *LOG) Start(m *ctx.Message, arg ...string) bool { // {{{ func (log *LOG) Start(m *ctx.Message, arg ...string) bool { // {{{
log.nfs = m.Sess("nfs").Cmd("append", m.Confx("bench.log", arg, 0), "", "日志文件") log.nfs = m.Sess("nfs").Cmd("append", m.Confx("bench.log", arg, 0), "", "日志文件")
log.out = log.nfs.Optionv("out").(*os.File) log.out = log.nfs.Optionv("out").(*os.File)
fmt.Fprintln(log.out, "\n\n")
return false return false
} }
@ -58,7 +59,7 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心",
"nlog": &ctx.Cache{Name: "nlog", Value: "0", Help: "日志屏蔽类型"}, "nlog": &ctx.Cache{Name: "nlog", Value: "0", Help: "日志屏蔽类型"},
}, },
Configs: map[string]*ctx.Config{ Configs: map[string]*ctx.Config{
"silent": &ctx.Config{Name: "silent", Value: map[string]interface{}{}, Help: "日志屏蔽类型"}, "silent": &ctx.Config{Name: "silent", Value: map[string]interface{}{"cb": true}, Help: "日志屏蔽类型"},
"module": &ctx.Config{Name: "module", Value: map[string]interface{}{ "module": &ctx.Config{Name: "module", Value: map[string]interface{}{
"log": map[string]interface{}{"cmd": true}, "log": map[string]interface{}{"cmd": true},
"lex": map[string]interface{}{"cmd": true, "debug": true}, "lex": map[string]interface{}{"cmd": true, "debug": true},

View File

@ -15,7 +15,6 @@ import ( // {{{
"path" "path"
"bytes" "bytes"
"mime"
"mime/multipart" "mime/multipart"
"path/filepath" "path/filepath"
@ -336,6 +335,16 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
"template": "append", "title": "", "template": "append", "title": "",
}, },
}, },
"notice": []interface{}{
map[string]interface{}{
"template": "notice", "title": "notice",
},
},
"login": []interface{}{
map[string]interface{}{
"template": "login", "title": "login",
},
},
}, Help: "资源列表"}, }, Help: "资源列表"},
}, },
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
@ -603,90 +612,41 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
// }}} // }}}
}}, }},
"/index": &ctx.Command{Name: "/index", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "/index": &ctx.Command{Name: "/index", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
r := m.Optionv("request").(*http.Request) r := m.Optionv("request").(*http.Request) // {{{
w := m.Optionv("response").(http.ResponseWriter) w := m.Optionv("response").(http.ResponseWriter)
login := m.Spawn().Cmd("/login") //执行命令
if login.Has("template") {
m.Copy(login, "append")
return
}
aaa := login.Appendv("aaa").(*ctx.Message)
list := m.Confv("index", aaa.Cap("username"))
if list == nil {
m.Echo("no right, please contact manager")
m.Append("template", "result")
return
}
if m.Options("details") { if m.Options("details") {
if !ctx.Right(m.Find(m.Option("module")).Cmd("right", aaa.Cap("username"), "check", "command", m.Option("details")).Result(0)) { if check := m.Spawn().Cmd("/check", "target", m.Option("module"), "command", m.Option("details")); !check.Results(0) {
m.Echo("no right, please contact manager") m.Copy(check, "append")
m.Append("template", "result")
return return
} }
msg := m.Find(m.Option("module")).Cmd(m.Option("details")) msg := m.Find(m.Option("module")).Cmd(m.Option("details"))
m.Copy(msg, "result").Copy(msg, "append") m.Copy(msg, "result").Copy(msg, "append")
return return
} }
//权限检查
dir := path.Join(m.Cap("directory"), m.Option("dir")) dir := path.Join(m.Cap("directory"), m.Option("dir"))
check := m.Spawn(c).Cmd("/check", "command", "/index", "dir", dir)
if !check.Results(0) {
m.Copy(check, "append")
return
}
//下载文件
if s, e := os.Stat(dir); e == nil && m.Option("dir") != "" && !s.IsDir() { if s, e := os.Stat(dir); e == nil && m.Option("dir") != "" && !s.IsDir() {
w.Header().Set("Content-type", mime.TypeByExtension(dir))
http.ServeFile(w, r, dir) http.ServeFile(w, r, dir)
return return
} }
if !ctx.Right(m.Spawn(c).Cmd("right", aaa.Cap("username"), "check", "command", "/index", "dir", dir).Result(0)) { //浏览目录
m.Echo("no right, please contact manager") aaa := check.Appendv("aaa").(*ctx.Message)
m.Append("template", "result") m.Append("template", aaa.Cap("username"))
return m.Option("title", "index")
}
m.Option("dir", dir) m.Option("dir", dir)
w.Header().Add("Content-Type", "text/html") // }}}
tpl := template.New("render").Funcs(ctx.CGI)
tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("common_tmpl"))))
tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("upload_tmpl"))))
replace := [][]byte{
[]byte{27, 91, 51, 50, 109}, []byte("<span style='color:red'>"),
[]byte{27, 91, 51, 49, 109}, []byte("<span style='color:green'>"),
[]byte{27, 91, 109}, []byte("</span>"),
}
for _, v := range list.([]interface{}) {
val := v.(map[string]interface{})
if _, ok := val["detail"]; ok {
detail := val["detail"].([]interface{})
msg := m.Spawn().Add("detail", detail[0].(string), detail[1:])
msg.Option("title", val["title"])
msg.Option("module", val["module"])
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg))
continue
}
if _, ok := val["module"]; ok {
if _, ok := val["command"]; ok {
msg := m.Find(val["module"].(string)).Cmd(val["command"], val["argument"])
for i, v := range msg.Meta["result"] {
b := []byte(v)
for i := 0; i < len(replace)-1; i += 2 {
b = bytes.Replace(b, replace[i], replace[i+1], -1)
}
msg.Meta["result"][i] = string(b)
}
if msg.Option("title", val["title"]) == "" {
msg.Option("title", m.Option("dir"))
}
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg))
continue
}
}
if _, ok := val["template"]; ok {
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), m))
}
}
}}, }},
"/travel": &ctx.Command{Name: "/travel", Help: "文件上传", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "/travel": &ctx.Command{Name: "/travel", Help: "文件上传", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
// r := m.Optionv("request").(*http.Request) // {{{ // r := m.Optionv("request").(*http.Request) // {{{
@ -975,15 +935,15 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
// }}} // }}}
}}, }},
"/check": &ctx.Command{Name: "/check cache|config|command name args", Help: "权限检查, cache|config|command: 接口类型, name: 接口名称, args: 其它参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "/check": &ctx.Command{Name: "/check cache|config|command name args", Help: "权限检查, cache|config|command: 接口类型, name: 接口名称, args: 其它参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
w := m.Optionv("response").(http.ResponseWriter) //{{{ // w := m.Optionv("response").(http.ResponseWriter) //{{{
if login := m.Spawn().Cmd("/login"); login.Has("redirect") { if login := m.Spawn().Cmd("/login"); login.Has("redirect") {
aaa := m.Appendv("aaa").(*ctx.Message) aaa := m.Appendv("aaa").(*ctx.Message)
if msg := m.Spawn().Cmd("right", aaa.Cap("username"), "check", arg); msg.Results(0) { if msg := m.Spawn().Cmd("right", aaa.Cap("username"), "check", arg); msg.Results(0) {
m.Copy(login, "append").Echo(msg.Result(0)) m.Copy(login, "append").Echo(msg.Result(0))
return return
} }
w.WriteHeader(http.StatusForbidden) // w.WriteHeader(http.StatusForbidden)
m.Append("message", "please contact manager") m.Append("message", "no right, please contact manager")
m.Echo("no") m.Echo("no")
return return
} else { } else {
@ -1012,20 +972,58 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
} }
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
m.Append("template", "login.html") m.Append("template", "login")
// }}} // }}}
}}, }},
"/render": &ctx.Command{Name: "/render [main [tmpl]]", Help: "模板响应, main: 模板入口, tmpl: 附加模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "/render": &ctx.Command{Name: "/render index", Help: "模板响应, main: 模板入口, tmpl: 附加模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
w := m.Optionv("response").(http.ResponseWriter) // {{{ w := m.Optionv("response").(http.ResponseWriter) // {{{
w.Header().Add("Content-Type", "text/html") w.Header().Add("Content-Type", "text/html")
tpl := template.New("render").Funcs(ctx.CGI) tpl := template.New("render").Funcs(ctx.CGI)
tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("common_tmpl")))) tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("common_tmpl"))))
if len(arg) > 1 { tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("upload_tmpl"))))
tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), arg[1])))
replace := [][]byte{
[]byte{27, 91, 51, 50, 109}, []byte("<span style='color:red'>"),
[]byte{27, 91, 51, 49, 109}, []byte("<span style='color:green'>"),
[]byte{27, 91, 109}, []byte("</span>"),
} }
m.Assert(tpl.ExecuteTemplate(w, m.Confx("common_main", arg, 0), m.Message())) m.Assert(tpl.ExecuteTemplate(w, "head", m))
for _, v := range m.Confv("index", arg[0]).([]interface{}) {
val := v.(map[string]interface{})
//命令模板
if detail, ok := val["detail"].([]interface{}); ok {
msg := m.Spawn().Add("detail", detail[0].(string), detail[1:])
msg.Option("module", val["module"])
msg.Option("title", val["title"])
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg))
continue
}
//执行命令
if _, ok := val["command"]; ok {
msg := m.Find(val["module"].(string)).Cmd(val["command"], val["argument"])
for i, v := range msg.Meta["result"] {
b := []byte(v)
for i := 0; i < len(replace)-1; i += 2 {
b = bytes.Replace(b, replace[i], replace[i+1], -1)
}
msg.Meta["result"][i] = string(b)
}
if msg.Option("title", val["title"]) == "" {
msg.Option("title", m.Option("dir"))
}
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg))
continue
}
//解析模板
if _, ok := val["template"]; ok {
m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), m))
}
}
m.Assert(tpl.ExecuteTemplate(w, "tail", m))
// }}} // }}}
}}, }},
"/json": &ctx.Command{Name: "/json", Help: "json响应", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "/json": &ctx.Command{Name: "/json", Help: "json响应", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {

View File

@ -2,7 +2,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{meta .title}}</title> <title>{{option .Meta "title"}}</title>
<style> <style>
legend { legend {
font-size:16px; font-size:16px;
@ -10,9 +10,11 @@
} }
th { th {
cursor:pointer; cursor:pointer;
background-color:lightgray; background-color:lightgreen;
}
td {
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 20px;
} }
code { code {
font-size:14px; font-size:14px;
@ -22,9 +24,13 @@
<body> <body>
{{end}} {{end}}
{{define "code"}}
<pre><code>{{.}}</code></pre>
{{end}}
{{define "notice"}} {{define "notice"}}
<fieldset class="notice"><legend>notice</legend> <fieldset class="notice"><legend>notice</legend>
<pre>{{result .Meta}}</pre> {{template "code" result .Meta}}
</fieldset> </fieldset>
<style> <style>
.notice {color:red} .notice {color:red}
@ -33,51 +39,28 @@
{{define "detail"}} {{define "detail"}}
<fieldset><legend>{{append . "title"}}</legend> <fieldset><legend>{{append . "title"}}</legend>
<a onclick="return action('{{option .Meta "module"}}', '{{detail .Meta}}')" href="/"><code>{{detail .Meta}}</code></a> <a onclick="return action('{{option .Meta "module"}}', '{{detail .Meta}}')" href="/">{{template "code" detail .Meta}}</a>
<pre><code class="result"></code></pre> <pre><code class="{{append . "title"}}_result"></code></pre>
</fieldset> </fieldset>
<script> <script>
function action(module, detail, cb) { function action(module, details, cb) {
var xhr = new XMLHttpRequest(); ctx.POST("", {module:module, details:details}, function(msg) {
cb = function(msg) { var result = document.getElementsByClassName("{{append . "title"}}_result")[0];
var result = document.getElementsByClassName("result")[0]; result.innerHTML = msg.result || msg.message;
result.innerHTML = msg.result; })
}
xhr.onreadystatechange = function() {
switch (xhr.readyState) {
case 4:
switch (xhr.status) {
case 200:
try {
var msg = JSON.parse(xhr.responseText||'{"result":[]}');
} catch (e) {
msg = {"result": [xhr.responseText]}
}
msg && console.log(msg)
msg.result && console.log(msg.result.join(""));
typeof cb == "function" && cb(msg)
}
break;
}
}
xhr.open("POST", "?module="+encodeURIComponent(module)+"&details="+encodeURIComponent(detail));
xhr.send()
return false return false
} }
</script> </script>
{{end}} {{end}}
{{define "result"}} {{define "result"}}
<fieldset><legend>{{append . "title"}}</legend> <fieldset><legend>{{option . "title"}}</legend>
<pre><code>{{result .Meta|unscaped}}</code></pre> {{template "code" result .Meta|unscaped}}
</fieldset> </fieldset>
{{end}} {{end}}
{{define "append_link"}} {{define "append_link"}}
<td><a onclick="return jump('{{.}}')" href="{{.}}"><code>{{.}}</code></a></td> <a onclick="return jump('{{.}}')" href="{{.}}">{{.}}</a>
<script> <script>
function jump(to) { function jump(to) {
location.href = location.href + "/" +to; location.href = location.href + "/" +to;
@ -88,30 +71,34 @@ function jump(to) {
{{define "append"}} {{define "append"}}
<fieldset><legend>{{append . "title"}}</legend> <fieldset><legend>{{append . "title"}}</legend>
<table class="append"> <table class="append">
{{$msg := .}} {{$msg := .}}
{{$ncol := append . |len}} {{$ncol := append . |len}}
{{$nrow := append . 0|append .|len}} {{$nrow := append . 0|append .|len}}
<tr>{{range append .}}<th class="append_head">{{.}}</th>{{end}}</tr> <tr>{{range append .}}<th><code onclick="sort_table('{{.}}')">{{.}}</code></th>{{end}}</tr>
{{range $row, $val := append . 0|append .}} {{range $row, $val := append . 0|append .}}
<tr> <tr>
{{range append $msg}} {{range append $msg}}
{{$value := append $msg . $row}} {{$value := append $msg . $row}}
{{if eq . "filename"}} <td><code>
{{template "append_link" $value}} {{if eq . "filename"}}
{{else}} {{template "append_link" $value}}
<td><code>{{$value}}</code></td> {{else}}
{{end}} {{$value}}
{{end}}
</tr>
{{end}} {{end}}
</table> </code></td>
{{end}}
</tr>
{{end}}
</table>
</fieldset> </fieldset>
<style> <script>
.append td {padding-right:20px} var sort_field="";
.append th {background-color:lightgreen} function sort_table(field) {
.append code {font-size:14px} sort_field = field;
</style> console.log(sort_field);
}
</script>
{{end}} {{end}}
{{define "main"}} {{define "main"}}
@ -119,6 +106,6 @@ welcome to context world!
{{end}} {{end}}
{{define "tail"}} {{define "tail"}}
<script src="library/context.js"></script> <script src="/library/context.js"></script>
</body> </body>
{{end}} {{end}}

View File

@ -1,7 +1,7 @@
{{define "login"}} {{define "login"}}
<fieldset><legend>login</legend> <fieldset><legend>login</legend>
<form method="POST" action="/login"> <form method="POST" action="/login">
<label>username:</label><input type="text" name="username" value="{{meta .username}}" required autofocus> <label>username:</label><input type="text" name="username" required autofocus>
<label>password:</label><input type="password" name="password" required> <label>password:</label><input type="password" name="password" required>
<input type="submit"> <input type="submit">
</form> </form>