diff --git a/pkg/arvo/app/neo.hoon b/pkg/arvo/app/neo.hoon index 20dc2b9b77..4db6f4c742 100644 --- a/pkg/arvo/app/neo.hoon +++ b/pkg/arvo/app/neo.hoon @@ -923,6 +923,7 @@ :~ [(weld #/[p/our.bowl] here) %make %sky `!>([%system ~ 0]) ~] [#/[p/our.bowl]/home/diary %make %diary `!>('') ~] + [#/[p/our.bowl]/home/tasks %make %task `!>(['' | ~]) ~] [#/[p/our.bowl]/home/iframes/wiki %make %iframe `!>('https://en.wikipedia.org/wiki/Main_Page') ~] == |- @@ -965,25 +966,53 @@ :: =/ stud (@tas (~(got by pam.purl) 'stud')) =/ conv !<($-([@ manx] vase) (all-grab %node)) - ?@ vert=(mole |.((conv [stud body]))) - (send (manx-response:gen:serv ;/("failed to convert"))) - =/ =pail:neo [stud u.vert] - =. run - %- poke-move - :- #/[p/our.bowl]/$/eyre/req/[eyre-id] - [(pave here) %poke pail] - %- send - :: - %- manx-response:gen:serv - =+ !<(grow=$-(pail:neo $-(=bowl:neo manx)) (all-grow %htmx)) - ?^ man=(mole |.((grow pail))) - %- u.man - =+ b=*bowl.neo :: manually constructing a bowl. this is ugly - %= b - here (pave pax.purl) - == - ;div: some sorta error occured - :: + =/ vert (mule |.((conv [stud body]))) + ?- -.vert + %.n + %- send + =- -(status-code.response-header 400) + %- manx-response:gen:serv + ;div.fc.p2.border.br1.scroll-x.scroll-y.wf.pre.mono + =style "max-height: 400px;" + =here (en-tape:pith:neo pith) + ;* + %+ turn (tang p.vert) + |= =tank + ;div: {(of-wall:format (~(win re tank) 0 55))} + == + %.y + =/ =pail:neo [stud p.vert] + =. run + %- poke-move + :- #/[p/our.bowl]/$/eyre/req/[eyre-id] + [(pave:neo here) %poke pail] + :: + =+ !<(grow=$-(pail:neo $-(=bowl:neo manx)) (all-grow %htmx)) + =/ man (mule |.((grow pail))) + %- send + ?- -.man + %.y + %- manx-response:gen:serv + %- p.man + =+ b=*bowl.neo + %= b + here pith + == + %.n + =- -(status-code.response-header 500) + %- manx-response:gen:serv + ;div.fc.p2.border.br1.scroll-x.scroll-y.wf.pre.mono + =style "max-height: 400px;" + =here (en-tape:pith:neo (pave:neo pax.purl)) + ;* + %+ turn (tang p.man) + |= =tank + ;div: {(of-wall:format (~(win re tank) 0 55))} + == + :: + == + :: + == ?: =(%'PUT' method.request.req) :: %make :: =/ stud (@tas (~(got by pam.purl) 'stud')) @@ -994,16 +1023,16 @@ =. run %- poke-move :- #/[p/our.bowl]/$/eyre/req/[eyre-id] - [(pave here) %make p.pail `q.pail ~] - %- send + [(pave:neo here) %make p.pail `q.pail ~] :: + %- send %- manx-response:gen:serv =+ !<(grow=$-(pail:neo $-(=bowl:neo manx)) (all-grow %htmx)) ?^ man=(mole |.((grow pail))) %- u.man =+ b=*bowl.neo :: manually constructing a bowl. this is ugly %= b - here (pave pax.purl) + here (pave:neo pax.purl) == ;div: some sorta error occured :: diff --git a/pkg/arvo/neo/src/std/con/node-task-diff.hoon b/pkg/arvo/neo/src/std/con/node-task-diff.hoon new file mode 100644 index 0000000000..7134dd1569 --- /dev/null +++ b/pkg/arvo/neo/src/std/con/node-task-diff.hoon @@ -0,0 +1,53 @@ +/@ node +/@ task-diff +:- [%node %task-diff] +|= nod=node +^- task-diff +=/ head (@tas (crip (~(got by (malt a.g.nod)) %head))) +%- task-diff +?+ head + ~| [%unknown-head head] + !! + %become + =/ path-el (snag 0 c.nod) + ~& path-el + =/ path (stab (crip (~(got by (malt a.g.path-el)) %value))) + [head (pave:neo path)] +:: + %nest + =/ name-el (snag 0 c.nod) + =/ name (@tas (crip (~(got by (malt a.g.name-el)) %value))) + [head name '' | ~] +:: + %prep + =/ name-el (snag 0 c.nod) + =/ name (@tas (crip (~(got by (malt a.g.name-el)) %value))) + [head name '' | ~] +:: + %oust + =/ path (stab (crip (~(got by (malt a.g.nod)) %pith))) + [head (pave:neo path)] +:: + %edit + =/ done-label (snag 0 c.nod) + =/ done-el (snag 0 c.done-label) + =/ text-el (snag 1 c.nod) + =/ text (crip (~(got by (malt a.g.text-el)) %value)) + =/ done (~(has by (malt a.g.done-el)) %checked) + [head text done] +:: + %kid-done + =/ path (stab (crip (~(got by (malt a.g.nod)) %pith))) + [head (pave:neo path)] +:: + %reorder + =/ piths + %+ turn c.nod + |= =manx + =/ here (~(get by (malt a.g.manx)) %here) + ?~ here + ~& >>> [%bad-here manx] + !! + (pave:neo /[(rear (stab (crip (need here))))]) + [head piths] +== diff --git a/pkg/arvo/neo/src/std/con/sky-htmx.hoon b/pkg/arvo/neo/src/std/con/sky-htmx.hoon index d4b18e12c1..22c25f5680 100644 --- a/pkg/arvo/neo/src/std/con/sky-htmx.hoon +++ b/pkg/arvo/neo/src/std/con/sky-htmx.hoon @@ -21,7 +21,7 @@ --f2: #999; --f3: #777; --f4: #555; - --f-error: orange; + --f-error: #531; --f-success: lightgreen; --link: lightblue; --hover: 115%; diff --git a/pkg/arvo/neo/src/std/con/task-diff-htmx.hoon b/pkg/arvo/neo/src/std/con/task-diff-htmx.hoon new file mode 100644 index 0000000000..561cf8d251 --- /dev/null +++ b/pkg/arvo/neo/src/std/con/task-diff-htmx.hoon @@ -0,0 +1,12 @@ +/@ task-diff +:- [%task-diff %htmx] +|= t=task-diff +|= =bowl:neo +;div.loading + =hx-get "/neo/hawk{(en-tape:pith:neo here.bowl)}" + =hx-target "closest ha-wk" + =hx-indicator "closest .loader" + =hx-swap "innerHTML" + =hx-trigger "load" + ; +++ +== diff --git a/pkg/arvo/neo/src/std/con/task-htmx.hoon b/pkg/arvo/neo/src/std/con/task-htmx.hoon new file mode 100644 index 0000000000..bdaa7b9e48 --- /dev/null +++ b/pkg/arvo/neo/src/std/con/task-htmx.hoon @@ -0,0 +1,273 @@ +/@ task +:- [%task %htmx] +|= t=task +|= =bowl:neo +|^ + shell +++ kids ~(tap by kids.bowl) +++ id + ^- tape + %- zing + %+ turn (pout here.bowl) + |= smeg=@ta + %+ weld "--" + (trip smeg) +++ form-edit + ^- manx + ;form.fc.g2.br1 + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=task-diff" + =hx-trigger "input changed delay:0.4s from:find textarea, input from:find input" + =hx-swap "none" + =head "edit" + ;label.fr.g2.ac.js + ;+ =- ?. done.t:+ - + -(a.g [[%checked ""] a.g.-]) + ^- manx + ;input + =type "checkbox" + =onclick (trip 'if (this.checked) { this.setAttribute("checked", "")} else {this.removeAttribute("checked")}') + ; + == + ;span.grow: Done + ;div.htmx-indicator + ; --- + == + == + ;textarea.wf.p2.border.br1.ma.mono + =name "text" + =autocomplete "off" + =spellcheck "false" + =rows "{<(add 2 (lent (fand ~[10] (trip text.t))))>}" + =oninput "this.setAttribute('value', this.value); this.rows = this.value.split('\\n').length" + =value (trip (@t text.t)) + ; {(trip (@t text.t))} + == + == +++ form-create + |= [head=@tas label=tape] + ^- manx + ;div.fc.g1 + ;button.b0.br1.hover.p2.wfc.mono.f3 + =onclick + """ + this.classList.toggle('toggled'); + this.nextElementSibling.classList.toggle('hidden'); + this.nextElementSibling.firstChild.focus(); + """ + ; {label} + == + ;form.fr.g1.hidden + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=task-diff" + =head (trip head) + =hx-swap "outerHTML" + =hx-target "find button .loading" + ;input.wf.p1.border.br1.grow + =name "text" + =autocomplete "off" + =type "text" + =pattern (trip '[a-z]{1}[a-z0-9\\-]+') + =title "lowercase and heps" + =required "" + =placeholder "name" + =oninput "this.setAttribute('value', this.value);" + ; + == + ;button.b1.br1.hover.p1.wfc.loader + ;span.loaded: create + ;span.loading: --- + == + == + == +++ part-kid + |= [=pith =pail:neo] + =/ t=task !<(task q.pail) + =- ?. done.t - + -(a.g [[%done ""] a.g.-]) + ^- manx + ;div.fc.g1 + =here (en-tape:pith:neo (welp here.bowl pith)) + ;div.fr.g1 + ;button + =class "b0 br1 hover p1 tl action mono fr g3 f2" + =style "padding: 4px 9px;" + =type "button" + =onclick + """ + this.textContent = this.textContent === "=" ? "|" : "="; toggleChildren(this); + """ + ;span.bold: = + == + ;+ =- + =/ that - + =/ classes + %+ weld + "b0 br1 hover p1 grow tl action mono fr g3" + ?:(done.t " strike f3" "") + that(a.g [[%class classes] a.g.that]) + ^- manx + ;button + =type "button" + =onclick + """ + this.classList.toggle('toggled'); this.parentNode.nextElementSibling.classList.toggle('hidden'); + """ + ;span.bold: {(trip -:(pout pith))} + ;span.break.f2: {(scag (fall (find [10 ~] (trip text.t)) 30) (trip text.t))} + == + ;a + =class "b0 br1 hover p1 loader f3" + =hx-indicator "this" + =href "/neo/hawk{(en-tape:pith:neo here.bowl)}{(en-tape:pith:neo pith)}" + =hx-swap "innerHTML" + ;span.loaded: → + ;span.loading: . + == + == + ;div.border.p2.br1.frw.g2.hidden + =hx-disinherit "hx-indicator" + =style "margin-left: 20px;" + ;button.b1.br1.p2.hover + =onclick "this.parentNode.parentNode.parentNode?.insertAdjacentElement('beforeend', this.parentNode.parentNode); center(this);" + ; ↧ + == + ;button.b1.br1.p2.hover + =onclick "this.parentNode.parentNode.nextElementSibling?.insertAdjacentElement('afterend', this.parentNode.parentNode); center(this);" + ; ↓ + == + ;button.b1.br1.p2.hover + =onclick "this.parentNode.parentNode.previousElementSibling?.insertAdjacentElement('beforebegin', this.parentNode.parentNode); center(this);" + ; ↑ + == + ;button.b1.br1.p2.hover + =onclick "this.parentNode.parentNode.parentNode?.insertAdjacentElement('afterbegin', this.parentNode.parentNode); center(this);" + ; ↥ + == + ;div.htmx-indicator.reorder-indicator.p2.f2 + ; --- + == + ;div.basis-full; + ;button.b1.br1.p2.hover.loader + =type "button" + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=task-diff" + =hx-swap "outerHTML" + =hx-target "find .loading" + =head "kid-done" + =pith (en-tape:pith:neo pith) + ;span.loaded: toggle + ;span.loading: --- + == + ;button.b1.br1.p2.hover.loader + =type "button" + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=task-diff" + =hx-swap "none" + =hx-on--after-request "this.parentNode.parentNode.remove();" + =head "oust" + =pith (en-tape:pith:neo pith) + ;span.loaded: delete + ;span.loading: --- + == + ;button.b1.br1.p2.hover + =type "button" + =onclick "this.nextElementSibling.classList.toggle('hidden'); this.classList.toggle('toggled');" + ; become + == + ;div.basis-full.hidden.fr.g1 + =hx-post "/neo/hawk{(en-tape:pith:neo (welp here.bowl pith))}?stud=task-diff" + =hx-trigger "become" + =hx-target "find .loading" + =hx-swap "outerHTML" + =head "become" + ;input.grow.p2.br1.border + =type "text" + =value (en-tape:pith:neo (welp here.bowl pith)) + =oninput "this.setAttribute('value', this.value);" + ; + == + ;button.p2.b1.hover.br1.loader + =type "button" + =onclick "this.dispatchEvent(new CustomEvent('become', \{composed:true, bubbles: true}))" + ;span.loaded: become + ;span.loading: --- + == + == + ;div.basis-full.p2.pre.mono.scroll-x + ; {(trip text.t)} + == + == + ;div.fc.g2.hidden + =hx-disinherit "hx-indicator" + =style "margin-left: 20px;" + ; + == + == + :: +++ script + ;script + ;+ ;/ %- trip + ''' + function center(el) { + el.scrollIntoView({ + block: "center", + inline: "start", + behavior: "instant" + }) + } + function toggleChildren(el) { + let kidsDiv = el.parentNode.nextElementSibling.nextElementSibling; + if (!kidsDiv.children.length) { + let here = el.parentNode.parentNode.getAttribute('here'); + let stub = document.createElement("div"); + stub.setAttribute("hx-get", `/neo/hawk${here}`); + stub.setAttribute("hx-trigger", 'load'); + stub.setAttribute("hx-target", 'this'); + stub.setAttribute("hx-select", '.kids'); + stub.textContent = "+ + +" + stub.className = "fc as jc" + stub.style = "padding:10px; padding-left: 20px;" + stub.setAttribute("hx-swap", "outerHTML"); + kidsDiv.appendChild(stub); + htmx.process(kidsDiv); + } + kidsDiv.classList.toggle('hidden'); + } + ''' + == +++ form-ordered-kids + ;form.fc.g1 + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=task-diff" + =head "reorder" + =hx-indicator ".reorder-indicator" + =hx-swap "none" + ;* + %+ turn order.t + |= =pith + =/ kid (~(get by kids.bowl) pith) + ?~ kid + ;div: does not exist {(en-tape:pith:neo pith)} + (part-kid [pith (need kid)]) + ::;* + ::=/ orphans + :: %+ skim kids + :: |= [=pith *] + :: =(~ (find [pith ~] order.t)) + ::%+ turn + :: %+ sort orphans + :: |= [a=[=pith *] b=[=pith *]] + :: (lth ->.pith.a ->.pith.b) + ::part-kid + == +++ shell + ;div.fc.js.af.p2.wf.p1.g5.ma + =here (en-tape:pith:neo here.bowl) + =style "max-width: 650px; padding-bottom: 50vh; padding-top: 30px;" + ;+ script + ;+ form-edit + ;div.fc.g1.kids + ::;+ ?~ (lent order.t) ;/("") (form-create %prep "+") + ::;+ ?~ (lent order.t) (form-create %nest "+") ;/("") + ;+ form-ordered-kids + ::;+ ?~ (lent order.t) ;/("") (form-create %nest "+") + ;+ (form-create %nest "+") + == + == +-- diff --git a/pkg/arvo/neo/src/std/con/txt-htmx.hoon b/pkg/arvo/neo/src/std/con/txt-htmx.hoon index f4c1c02e6d..b876bacce7 100644 --- a/pkg/arvo/neo/src/std/con/txt-htmx.hoon +++ b/pkg/arvo/neo/src/std/con/txt-htmx.hoon @@ -4,7 +4,7 @@ |= =bowl:neo ;form.fc.p2 =here (en-tape:pith:neo here.bowl) - =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=txt" + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=txt&refresh" =hx-trigger "input changed delay:0.4s from:find textarea" =hx-swap "none" ;textarea.wf.p2.border.br1.ma diff --git a/pkg/arvo/neo/src/std/imp/task.hoon b/pkg/arvo/neo/src/std/imp/task.hoon new file mode 100644 index 0000000000..88e14f395b --- /dev/null +++ b/pkg/arvo/neo/src/std/imp/task.hoon @@ -0,0 +1,92 @@ +/@ task +/@ task-diff +|% +++ state %task +++ poke (sy %task-diff ~) +++ kids + ^- kids:neo + %- ~(gas by *kids:neo) + :~ :- ~[|/%tas] + [%task %task-diff] + == +++ deps *deps:neo +++ form + ^- form:neo + |_ [=bowl:neo =ever:neo state-vase=vase *] + ++ poke + |= [=stud:neo vax=vase] + ^- (quip card:neo vase) + =/ this (task !<(task state-vase)) + =/ diff (task-diff !<(task-diff vax)) + ?- -.diff + %become + :: XX if you try to become your own ancestor, then infinite loop + =/ there (welp [p/our.bowl]~ pith.diff) + :_ state-vase + ^- (list card:neo) + :~ + [there %poke %task-diff !>([%prayer +.here.bowl])] + == + :: + %prayer + :_ state-vase + %- flop + ^- (list card:neo) + :- + [(welp [p/our.bowl]~ pith.diff) %make %task `!>(this) ~] + %- zing + %+ turn ~(tap by kids.bowl) + |= [=pith =pail:neo] + :~ + [:(welp [p/our.bowl]~ pith.diff pith) %make %task `q.pail ~] + [(welp here.bowl pith) %poke %task-diff !>([%prayer (welp pith.diff pith)])] + == + :: + %nest + :_ !> this(order `(list pith)`(snoc order.this `pith`[`@tas`name.diff ~])) + :_ ~ + :* (snoc here.bowl name.diff) + %make %task `!>(task.diff) ~ + == + :: + %prep + :_ !> this(order `(list pith)`[[name.diff ~] order.this]) + :_ ~ + :* (snoc here.bowl name.diff) + %make %task `!>(task.diff) ~ + == + :: + %edit + :- ~ + !> this(text text.diff, done done.diff) + :: + %done + :- ~ + !> this(done !done.this) + :: + %kid-done + :_ !> this + :_ ~ + :* (welp here.bowl pith.diff) + %poke %task-diff !>([%done ~]) + == + :: + %oust + =/ i (find [pith.diff ~] order.this) + ?~ i `!>(this) + :_ !> this(order (oust [(need i) 1] order.this)) + ~ + :::_ ~ + :::* (welp here.bowl pith.diff) + :: %tomb + ::== + :: + %reorder + :- ~ + !> this(order order.diff) + == + ++ init + |= vas=(unit vase) + `(need vas) + -- +-- diff --git a/pkg/arvo/neo/src/std/pro/task-diff.hoon b/pkg/arvo/neo/src/std/pro/task-diff.hoon new file mode 100644 index 0000000000..1ff6b17172 --- /dev/null +++ b/pkg/arvo/neo/src/std/pro/task-diff.hoon @@ -0,0 +1,12 @@ +/@ task +$% + [%become =pith] + [%prayer =pith] + [%prep name=@tas =task] + [%nest name=@tas =task] + [%edit text=cord done=?] + [%done ~] :: toggles + [%kid-done =pith] :: toggles + [%oust =pith] + [%reorder order=(list pith)] +== diff --git a/pkg/arvo/neo/src/std/pro/task.hoon b/pkg/arvo/neo/src/std/pro/task.hoon new file mode 100644 index 0000000000..99cea9ba4d --- /dev/null +++ b/pkg/arvo/neo/src/std/pro/task.hoon @@ -0,0 +1 @@ +,[text=cord done=? order=(list pith)] diff --git a/pkg/arvo/web/style.css b/pkg/arvo/web/style.css index d1d5f14214..348423b352 100644 --- a/pkg/arvo/web/style.css +++ b/pkg/arvo/web/style.css @@ -15,8 +15,9 @@ font: inherit; color: inherit; } -form, p, li, ul, ol, div, button, h1, h2, h3, h4, h5, h6 { +form, a, input, p, li, ul, ol, div, button, h1, h2, h3, h4, h5, h6 { margin: 0; + line-height: 1; } html { height: 100%; @@ -36,6 +37,7 @@ body { a { cursor: pointer; text-decoration: none; + font: inherit; } button, input, textarea, iframe { border: unset; @@ -99,6 +101,9 @@ button, input, textarea, iframe { .bold { font-weight: bold; } +.strike { + text-decoration: line-through; +} .pre { white-space: pre; } @@ -324,11 +329,13 @@ select { border-radius: 0; background-color: inherit; color: inherit; + font: inherit; + line-height: inherit; } textarea { display: block; outline: none; - resize: vertical; + resize: none; border-radius: 0; border: 0; background-color: inherit;