diff --git a/base/ctx/process.go b/base/ctx/process.go index 9dfe3dd0..b178c6c0 100644 --- a/base/ctx/process.go +++ b/base/ctx/process.go @@ -51,7 +51,7 @@ func ProcessField(m *ice.Message, cmd string, args ice.Any, arg ...string) *ice. m.Cmdy(COMMAND, cmd).Push(ARGS, kit.Format(_process_args(m, args))).Options(ice.MSG_INDEX, m.PrefixKey()).ProcessField(ACTION, m.ActionKey(), ice.RUN) } else { if pod := m.Option(ice.POD); pod != "" { - m.Options(ice.POD, "").Cmdy("web.space", pod, cmd, arg[1:]) + m.Options(ice.POD, []string{}, ice.MSG_USERPOD, pod).Cmdy("web.space", pod, cmd, arg[1:]) } else { kit.If(aaa.Right(m, cmd, arg[1:]), func() { m.Cmdy(cmd, arg[1:]) }) } diff --git a/base/mdb/hash.go b/base/mdb/hash.go index 93b77ffc..cb1c8138 100644 --- a/base/mdb/hash.go +++ b/base/mdb/hash.go @@ -76,6 +76,7 @@ func _hash_select_field(m *ice.Message, prefix, chain string, key string, field } func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) { fields := _hash_fields(m) + kit.If(kit.IndexOf(fields, HASH) == -1, func() { fields = append(fields, HASH) }) defer RLock(m, prefix, chain)() Richs(m, prefix, chain, FOREACH, func(key string, value Map) { switch value = kit.GetMeta(value); cb := m.OptionCB("").(type) { @@ -173,7 +174,8 @@ func HashShort(m *ice.Message) string { return kit.Select(HASH, Config(m, SHORT), Config(m, SHORT) != UNIQ) } func HashField(m *ice.Message) string { - return kit.Select(HASH_FIELD, Config(m, FIELD), Config(m, FIELDS)) + return kit.Select(HASH_FIELD, Config(m, FIELD)) + // return kit.Select(HASH_FIELD, Config(m, FIELD), Config(m, FIELDS)) } func HashInputs(m *ice.Message, arg ...Any) *ice.Message { return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, arg) diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index e1002c27..a40f709d 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -143,6 +143,8 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {}}, INPUTS: {Name: "inputs key sub type field value", Hand: func(m *ice.Message, arg ...string) { switch arg[3] { + case "space": + m.Cmdy("web.space").Cut(NAME) case "index": m.Cmdy("command") return @@ -246,7 +248,8 @@ func AutoConfig(arg ...Any) *ice.Action { m.Design(INSERT, "添加", inputs...) } if inputs := []Any{}; cmd.Meta[CREATE] == nil { - kit.For(kit.Filters(kit.Split(kit.Select(Config(m, SHORT), Config(m, FIELDS))), TIME, HASH, COUNT), func(k string) { inputs = append(inputs, k) }) + kit.For(kit.Filters(kit.Split(Config(m, SHORT)), TIME, HASH, COUNT), func(k string) { inputs = append(inputs, k) }) + // kit.For(kit.Filters(kit.Split(kit.Select(Config(m, SHORT), Config(m, FIELDS))), TIME, HASH, COUNT), func(k string) { inputs = append(inputs, k) }) m.Design(CREATE, "创建", inputs...) } } else if cmd.Actions[CREATE] != nil { diff --git a/base/web/flows.css b/base/web/flows.css new file mode 100644 index 00000000..f245ccd4 --- /dev/null +++ b/base/web/flows.css @@ -0,0 +1,5 @@ +fieldset.web.flows>div.output>div.layout>div.layout>div.content svg text { dominant-baseline:middle; } +fieldset.web.flows>div.output>div.layout>div.layout>div.content svg text.fail { stroke:red; fill:red; } +fieldset.web.flows>div.output>div.layout>div.layout>div.content svg rect.fail { stroke:red; } +fieldset.web.flows>div.output>div.layout>div.layout>div.content svg text.done { stroke:lightgreen; fill:lightgreen; } +fieldset.web.flows>div.output>div.layout>div.layout>div.content svg rect.done { stroke:lightgreen; } diff --git a/base/web/flows.go b/base/web/flows.go new file mode 100644 index 00000000..2c82fce0 --- /dev/null +++ b/base/web/flows.go @@ -0,0 +1,51 @@ +package web + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" +) + +const FLOWS = "flows" + +func init() { + Index.MergeCommands(ice.Commands{ + FLOWS: {Name: "flows zone hash auto", Help: "工作流", Actions: ice.MergeActions(ice.Actions{ + mdb.INSERT: {Name: "insert space index* args", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.INSERT, m.PrefixKey(), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(mdb.Config(m, mdb.FIELDS))) + }}, + mdb.DELETE: {Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.DELETE, m.PrefixKey(), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(mdb.HASH)) + }}, + mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.MODIFY, m.PrefixKey(), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(mdb.HASH), arg) + }}, + mdb.PLUGIN: {Hand: func(m *ice.Message, arg ...string) { + ctx.ProcessField(m, m.Option(ctx.INDEX), kit.Split(m.Option(ctx.ARGS)), arg...) + if !kit.HasPrefixList(arg, ice.RUN) { + m.Push("style", "float") + } + }}, + }, ctx.CmdAction(), mdb.HashAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,zone", mdb.FIELDS, "time,hash,space,index,args,prev,from,status")), Hand: func(m *ice.Message, arg ...string) { + if len(arg) == 0 || arg[0] == "" { + mdb.HashSelect(m).Action(mdb.CREATE) + } else { + arg = kit.Slice(arg, 0, 2) + m.Fields(len(arg)-1, mdb.Config(m, mdb.FIELDS), mdb.DETAIL) + m.Cmdy(mdb.SELECT, m.PrefixKey(), kit.KeyHash(arg[0]), mdb.HASH, arg[1:]) + m.Table(func(value ice.Maps) { + switch value[mdb.STATUS] { + case "done": + m.PushButton(mdb.PLUGIN, mdb.DELETE) + case "fail": + m.PushButton(mdb.PLUGIN, mdb.DELETE) + default: + m.PushButton(mdb.PLUGIN, mdb.DELETE) + } + }).Action(mdb.INSERT).StatusTimeCount() + } + m.Display("") + }}, + }) +} diff --git a/base/web/flows.js b/base/web/flows.js new file mode 100644 index 00000000..f251c375 --- /dev/null +++ b/base/web/flows.js @@ -0,0 +1,83 @@ +Volcanos(chat.ONIMPORT, { + _init: function(can, msg) { can.onmotion.clear(can), can.ui = can.onappend.layout(can), can.onmotion.hidden(can, can.ui.profile) + if (can.Option(mdb.ZONE)) { return can.onmotion.hidden(can, can.ui.project), can.onimport._content(can, msg) } can.onimport._project(can, msg) + }, + _project: function(can, msg) { var item; msg.Table(function(value) { + var _item = can.onimport.item(can, value, function(event) { + if (can.onmotion.cache(can, function(data, old) { + if (old) { data[old] = {_content_plugin: can._content_plugin, _profile_plugin: can._profile_plugin} } + var back = data[value.zone]; if (back) { can._content_plugin = back._content_plugin, can._profile_plugin = back._profile_plugin } + return value.zone + }, can.ui.content)) { return } + can.run(event, [value.zone], function(msg) { msg.Table(function() { msg.Push(mdb.ZONE, value.zone) }), can.onimport._content(can, msg) }) + }, null, can.ui.project); item = can.Option(mdb.ZONE) == value.zone? _item: item||_item + }), item && item.click() }, + _content: function(can, msg, zone) { can.onappend.plugin(can, {index: web.WIKI_DRAW, display: "/plugin/local/wiki/draw.js", style: "output"}, function(sub) { + sub.onexport.output = function(_sub, _msg) { can._content_plugin = _sub, can.onimport.layout(can) + sub.Action(svg.GO, "manual") + sub.Action(ice.MODE, web.RESIZE) + var list = {}; msg.Table(function(value) { list[value.hash] = value }) + var root = {}; can.core.Item(list, function(key, item) { if (!item.prev && !item.from) { root = item } item.prev && (list[item.prev].next = item), item.from && (list[item.from].to = item) }) + var margin = 20, width = 200, height = 100 + function show(root, _next, x, y) { can.onimport._block(can, _sub, root, x, y) + var to = {x: 0, y: 0}, next = {x: 0, y: 0} + if (_next) { + if (root.to) { + can.onimport._flows(can, _sub, [{x: x+width/2, y: y+height-margin}, {x: x+width/2, y: y+height+margin}]) + var to = show(root.to, false, x, y+height) + } + if (root.next) { + can.onimport._flows(can, _sub, [{x: x+width-margin, y: y+height/2}, {x: x+width+margin, y: y+height/2}]) + var next = show(root.next, true, x+(to.y+1)*width, y) + } + } else { + if (root.next) { + can.onimport._flows(can, _sub, [{x: x+width-margin, y: y+height/2}, {x: x+width+margin, y: y+height/2}]) + var next = show(root.next, true, x, y+height) + } + if (root.to) { + can.onimport._flows(can, _sub, [{x: x+width/2, y: y+height-margin}, {x: x+width/2, y: y+height+margin}]) + var to = show(root.to, false, x, y+(next.y+1)*height) + } + } + return {x: next.x, y: to.y} + } show(root, true, 0, 0) + can.onappend.table(can, msg, null, can.ui.display), can.onmotion.hidden(can, _sub._action), can.onimport.layout(can) + }, sub.run = function(event, cmds, cb) { cb(can.request(event)) } + }, can.ui.content) }, + _flows: function(can, _sub, points) { _sub.onimport.draw(_sub, {shape: svg.LINE, points: points}) }, + _block: function(can, _sub, item, x, y) { var margin = 20, width = 200, height = 100 + var rect = _sub.onimport.draw(_sub, {shape: svg.RECT, points: [{x: x+margin, y: y+margin}, {x: x+width-margin, y: y+height-margin}]}); item.status && rect.Value("class", item.status) + var text = _sub.onimport.draw(_sub, {shape: svg.TEXT, points: [{x: x+width/2, y: y+height/2}], style: {inner: item.index}}); item.status && text.Value("class", item.status) + rect.onclick = text.onclick = function(event) { switch (_sub.svg.style.cursor) { + case "e-resize": can.Update(can.request(event, {prev: item.hash, zone: item.zone||can.Option(mdb.ZONE)}), [ctx.ACTION, mdb.INSERT]); break + case "s-resize": can.Update(can.request(event, {from: item.hash, zone: item.zone||can.Option(mdb.ZONE)}), [ctx.ACTION, mdb.INSERT]); break + } can.onkeymap.prevent(event) } + rect.oncontextmenu = text.oncontextmenu = function(event) { can.user.carteItem(event, can, item) } + }, + layout: function(can) { + if (can.page.isDisplay(can.ui.profile)) { var profile = can._profile_plugin + can.page.style(can, profile._output, html.MAX_WIDTH, "") + var width = can.base.Max(profile._target.offsetWidth+1, (can.ConfWidth()-can.ui.project.offsetWidth)/2) + can.page.styleWidth(can, can.ui.profile, width) + } + if (can.page.isDisplay(can.ui.display)) { + can.page.styleHeight(can, can.ui.display, 0) + can.page.SelectChild(can, can.ui.display, "table", function(target) { + can.page.styleHeight(can, can.ui.display, can.base.Max(target.offsetHeight, can.ConfHeight()/2)) + }) + } + can.ui.layout(can.ConfHeight(), can.ConfWidth()), profile && profile.onimport.size(profile, can.ui.profile.offsetHeight, width-1, true) + can._content_plugin && can._content_plugin.ui.layout(can.ConfHeight()-can.ui.display.offsetHeight-0*html.ACTION_HEIGHT, can.ConfWidth()-can.ui.project.offsetWidth) + }, +}, [""]) +Volcanos(chat.ONACTION, { + plugin: function(event, can, msg) { + if (can.onmotion.cache(can, function() { return can.core.Keys(msg.Option(mdb.ZONE), msg.Option(mdb.HASH)) }, can.ui.profile)) { return } + can.onappend.plugin(can, {index: msg.Option(ctx.INDEX), args: msg.Option(ctx.ARGS)}, function(sub) { + can._profile_plugin = sub + sub.onexport.output = function() { can.onmotion.toggle(can, can.ui.profile, true), can.onimport.layout(can) } + sub.onaction._close = function() { can.onmotion.hidden(can, can.ui.profile), can.onimport.layout(can) } + }, can.ui.profile) + }, +}) diff --git a/base/web/route.go b/base/web/route.go index 9fa7e335..61cf11e2 100644 --- a/base/web/route.go +++ b/base/web/route.go @@ -56,10 +56,19 @@ const ROUTE = "route" func init() { Index.MergeCommands(ice.Commands{ - ROUTE: {Name: "route space:text cmds:text auto spide cmds build travel", Help: "路由表", Actions: ice.MergeActions(ice.Actions{ + ROUTE: {Name: "route space:text cmds:text auto spide cmds build travel prunes", Help: "路由表", Actions: ice.MergeActions(ice.Actions{ ice.MAIN: {Help: "首页", Hand: func(m *ice.Message, arg ...string) { ctx.ProcessField(m, CHAT_IFRAME, m.MergePod(kit.Select(m.Option(SPACE), arg, 0)), arg...) }}, + mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { + switch mdb.HashInputs(m, arg); arg[0] { + case SPACE: + list := map[string]bool{} + push := func(key string) { kit.If(!list[key], func() { m.Push(arg[0], key); list[key] = true }) } + mdb.HashSelect(m.Spawn()).Table(func(value ice.Maps) { push(kit.Format("=%s@", value[nfs.MODULE])) }) + kit.For([]string{WORKER, SERVER}, func(key string) { push(kit.Format(":%s=", key)) }) + } + }}, "spide": {Help: "导图", Hand: func(m *ice.Message, arg ...string) { ctx.DisplayStorySpide(m.Cmdy(""), nfs.DIR_ROOT, ice.Info.NodeName, mdb.FIELD, SPACE, lex.SPLIT, nfs.PT, ctx.ACTION, ice.MAIN) }}, @@ -103,7 +112,8 @@ func init() { }) PushPodCmd(m, "", m.ActionKey()) m.Table(func(value ice.Maps) { kit.If(value[SPACE], func() { mdb.HashCreate(m.Spawn(), kit.Simple(value)) }) }) - m.StatusTimeCount() + m.ProcessRefresh() + // m.StatusTimeCount() }}, }, ctx.CmdAction(), mdb.HashAction(mdb.SHORT, SPACE, mdb.FIELD, "time,space,type,module,version,md5,size,path,hostname", mdb.SORT, "type,space", mdb.ACTION, ice.MAIN)), Hand: func(m *ice.Message, arg ...string) { if len(arg) > 1 { diff --git a/base/web/serve.go b/base/web/serve.go index ddc4652e..7e0e440e 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -27,10 +27,10 @@ func _serve_start(m *ice.Message) { }) kit.If(m.Option(aaa.USERNAME), func() { aaa.UserRoot(m, m.Option(aaa.USERNICK), m.Option(aaa.USERNAME)) }) kit.If(m.Option(tcp.PORT) == tcp.RANDOM, func() { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) }) - kit.If(cli.IsWindows(), func() { - m.Go(func() { m.Cmd(SPIDE, ice.OPS, _serve_address(m)+"/exit", ice.Maps{CLIENT_TIMEOUT: "30ms"}) }) - m.Sleep("30ms") - }) + // kit.If(cli.IsWindows(), func() { + m.Go(func() { m.Cmd(SPIDE, ice.OPS, _serve_address(m)+"/exit", ice.Maps{CLIENT_TIMEOUT: "30ms"}) }) + m.Sleep("30ms") + // }) cli.NodeInfo(m, kit.Select(ice.Info.Hostname, m.Option(tcp.NODENAME)), SERVER) m.Start("", m.OptionSimple(tcp.HOST, tcp.PORT)...) } diff --git a/misc/webview/webview.go b/misc/webview/webview.go index fd6a0726..db4697d5 100644 --- a/misc/webview/webview.go +++ b/misc/webview/webview.go @@ -66,11 +66,7 @@ func (w WebView) Power() string { } return "" } -func (w WebView) Close() { - if !w.Menu() { - w.WebView.Terminate() - } -} +func (w WebView) Close() { kit.If(!w.Menu(), func() { w.WebView.Terminate() }) } func (w WebView) Terminate() { w.WebView.Terminate() } func (w WebView) navigate(url string) { w.WebView.SetSize(1200, 800, webview.HintNone) @@ -87,7 +83,5 @@ func Run(cb func(*WebView) ice.Any) { } else { kit.Reflect(cb(view), func(name string, value ice.Any) { w.Bind(name, value) }) } - if !view.Menu() { - view.navigate("http://localhost:9020") - } + kit.If(!view.Menu(), func() { view.navigate("http://localhost:9020") }) }