mirror of
https://github.com/urbit/shrub.git
synced 2025-01-08 14:09:29 +03:00
Merge branch 'apps' of https://github.com/urbit/urbit into work
This commit is contained in:
commit
0b8b8d3ef1
@ -494,14 +494,14 @@
|
||||
::
|
||||
++ poke-test
|
||||
%+ titl 'Poke'
|
||||
;= ;button(onclick "urb.testPoke('/~/to/hi/txt.json')"): Hi anonymous
|
||||
;button(onclick "urb.testPoke('/~/as/own/~/to/hi/txt.json')"): Hi
|
||||
;= ;button(onclick "urb.testPoke('/~/to/hood/helm-hi.json')"): Hi anonymous
|
||||
;button(onclick "urb.testPoke('/~/as/own/~/to/hood/helm-hi.json')"): Hi
|
||||
;pre:code#err;
|
||||
;script@"/~/at/~/auth.js";
|
||||
;script:'''
|
||||
show = function(t){err.innerText = ":) " + Date.now() + "\n" + t}
|
||||
urb.testPoke = function(url){
|
||||
req(url,{xyro:{test:true}}, show)
|
||||
req(url,{wire:"/",xyro:'test'}, show)
|
||||
}
|
||||
'''
|
||||
==
|
||||
@ -748,7 +748,7 @@
|
||||
$(tee q.tee, q.q.p.q.sih (add-json jon q.q.cay))
|
||||
::
|
||||
[%ha *]
|
||||
:: ~& e/ford/hen
|
||||
%- emule |. ^+ ..apex
|
||||
?. ?=(%& -.q.sih)
|
||||
(fail 404 p.sih p.q.sih)
|
||||
=* cay p.q.sih
|
||||
|
@ -1047,7 +1047,10 @@
|
||||
?. ?=(%2 -.q.raf)
|
||||
(cope raf (flux |=(vax=vase (some [for vax]))))
|
||||
=- ((slog 0 (flop `tang`-)) (flue cof))
|
||||
?^ t.pax ~ :: error on top-level marks
|
||||
=+ (lent t.pax)
|
||||
?: ?~ - | :: error if level above built
|
||||
(~(has by res) (tack i.pax (scag (dec -) t.pax)))
|
||||
~
|
||||
:_(q.q.raf leaf/"! {<`mark`for>} build failed, ignoring.")
|
||||
--
|
||||
::
|
||||
|
64
mar/work/command.hoon
Normal file
64
mar/work/command.hoon
Normal file
@ -0,0 +1,64 @@
|
||||
::
|
||||
:::: /hoon/command/work/mar
|
||||
::
|
||||
/- *work
|
||||
!:
|
||||
::::
|
||||
::
|
||||
|_ mad=command
|
||||
++ grab
|
||||
|% ++ noun command
|
||||
++ json
|
||||
=> [jo ..command]
|
||||
=< (corl need (cu |=(a=command a) coma))
|
||||
|%
|
||||
++ as
|
||||
:: |*(a=fist (cu sa (ar a))) :: XX types
|
||||
|* a=fist
|
||||
%- cu :_ (ar a)
|
||||
~(gas in *(set ,_(need *a)))
|
||||
++ id (ci (slat %uv) so)
|
||||
++ ship (su fed:ag)
|
||||
++ coma (of new/task old/(ot id/id dif/uppd ~) sort/(ar id) ~)
|
||||
++ task
|
||||
%- ot :~
|
||||
id/id date-created/di
|
||||
version/ni date-modified/di
|
||||
owner/ship status/(ci (soft status) so)
|
||||
tags/(as so) due-date/(mu di) title/so
|
||||
description/so discussion/(ar (ot date/di ship/ship body/so ~))
|
||||
==
|
||||
++ uppd
|
||||
%- of :~
|
||||
own/(of announce/ul claim/ul ~)
|
||||
add/(of comment/(ot date/di body/so ~) ~)
|
||||
:- %set
|
||||
%- of :~
|
||||
due-date/di
|
||||
title/so
|
||||
description/so
|
||||
tags/(as so)
|
||||
done/(mu di)
|
||||
audience/(as (ot ship/ship span/so ~))
|
||||
==
|
||||
==
|
||||
--
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ elem ;pre: {(zing `wall`(turn (wash 0^120 >mad<) |=(a=tape ['\0a' a])))}
|
||||
--
|
||||
--
|
||||
:: {new: {
|
||||
:: id:'0vaof.6df9u.2agc3.d0dp1',
|
||||
:: date-created:1440011611215,
|
||||
:: version:1,
|
||||
:: date-modified:1440011611215,
|
||||
:: owner:'fyr',
|
||||
:: status:'gave',
|
||||
:: tags:['tag'],
|
||||
:: due-date:null,
|
||||
:: title:'Test task',
|
||||
:: description:'The converter owrks right?',
|
||||
:: discussion:[{date:1440011611215,ship:'sondel',body:'hi'}]
|
||||
:: } }
|
118
mar/work/task.hoon
Normal file
118
mar/work/task.hoon
Normal file
@ -0,0 +1,118 @@
|
||||
::
|
||||
:::: /hoon/task/work/mar
|
||||
::
|
||||
/- *work
|
||||
!:
|
||||
::::
|
||||
::
|
||||
|%
|
||||
++ rend
|
||||
|= a=(list $|(char dime)) ^- cord
|
||||
%- crip
|
||||
|- ^- tape
|
||||
?~ a ~
|
||||
?@ i.a [i.a $(a t.a)]
|
||||
(weld (scow i.a) $(a t.a))
|
||||
::
|
||||
++ indent |=(a=wain (turn a |=(b=cord (cat 3 ' ' b))))
|
||||
::
|
||||
++ undent
|
||||
|* [a=wain b=$+(wain *)] ^+ [*b a]
|
||||
=^ c a
|
||||
|- ^- [c=wain a=wain]
|
||||
?~ a [~ a]
|
||||
?. =(' ' (end 3 2 i.a))
|
||||
[~ a]
|
||||
[[- c] a]:[(rsh 3 2 i.a) $(a t.a)]
|
||||
[(b `wain`c) a]
|
||||
++ keen |*(_[a=,* b=rule] |=(c=nail `(like a)`(b c)))
|
||||
++ parse
|
||||
|* [hed=?(~ $|(@tas tape)) tal=(pole)]
|
||||
?~ hed (..$ tal)
|
||||
?^ hed ;~(pfix (just (crip hed)) (..$ tal))
|
||||
=- ?~(tal had ;~(plug had (..$ tal)))
|
||||
=< had=(sear . nuck:so)
|
||||
|= a=coin ^- (unit (odo:raid hed))
|
||||
?. &(?=([%$ @ @] a) =(hed p.p.a)) ~
|
||||
(some q.p.a)
|
||||
::
|
||||
++ advance
|
||||
|* [a=wain b=_rule] ^+ [(wonk *b) a]
|
||||
?~(a !! ~|(i.a [(rash i.a b) t.a]))
|
||||
--
|
||||
!:
|
||||
::::
|
||||
::
|
||||
|_ taz=task
|
||||
++ grab
|
||||
|% ++ txt
|
||||
|= a=wain ^+ taz
|
||||
=+ ~[id=%uv "_" date-created=%da " " version=%ud date-modified=%da]
|
||||
=^ b a (advance a ;~(plug (parse -) (punt (parse " " %da ~))))
|
||||
=+ [-.b `due-date=(unit ,@da)`+.b]
|
||||
=^ tags a (undent a ~(gas in *(set cord)))
|
||||
=^ title a ?~(a !! a)
|
||||
=^ b a (advance a (parse owner=%p "." status=%tas ~))
|
||||
?> ?=(status.task status.b)
|
||||
=+ b
|
||||
=^ description a (undent a role)
|
||||
:* id date-created version date-modified
|
||||
owner status tags due-date title description
|
||||
|- ^- (list comment)
|
||||
?: =(~ a) ~
|
||||
=^ b a (advance a (parse ship=%p " " date=%da ~))
|
||||
=+ b
|
||||
=^ body a (undent a role)
|
||||
[[date ship body] $]
|
||||
==
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ elem ;pre: {(zing `wall`(turn (wash 0^120 >taz<) |=(a=tape ['\0a' a])))}
|
||||
++ mime [/text/x-task (taco (role txt))]
|
||||
++ txt
|
||||
=+ taz
|
||||
=+ due=?~(due-date ~ ~[' ' da/u.due-date])
|
||||
:- (rend uv/id '_' da/date-created ' ' ud/version da/date-modified due)
|
||||
%+ welp (indent (sort (~(tap in tags)) aor))
|
||||
:- title
|
||||
:- (rend p/owner '.' tas/status ~)
|
||||
%- zing ^- (list wain)
|
||||
:- (indent (lore description))
|
||||
%+ turn discussion
|
||||
|= comment ^- wain
|
||||
[(rend p/ship ' ' da/date ~) (indent (lore body))]
|
||||
++ json
|
||||
=+ taz
|
||||
%- jobe :~ id/(jape <id>)
|
||||
tags/[%a (turn (~(tap in tags)) |=(a=cord s/a))]
|
||||
owner/(jape <owner>)
|
||||
status/(jape <status>)
|
||||
title/[%s title]
|
||||
version/(jape <version>)
|
||||
date-created/(jode date-created)
|
||||
date-modified/(jode date-modified)
|
||||
description/[%s description]
|
||||
=< discussion/[%a (turn discussion .)]
|
||||
|=(comment (jobe date/(jode date) ship/(jape <ship>) body/[%s body] ~))
|
||||
due-date/?~(due-date ~ (jode u.due-date))
|
||||
==
|
||||
--
|
||||
++ grad %txt
|
||||
--
|
||||
:: {id}_{date-created} {version}{date-modified}{|(" {due-date}" ~)}
|
||||
:: {tag1}
|
||||
:: {tag2}
|
||||
:: ...
|
||||
:: {title}
|
||||
:: {owner}.{status}
|
||||
:: {description}
|
||||
:: {more description}
|
||||
:: {ship1} {date}
|
||||
:: {comment}
|
||||
:: {more comment}
|
||||
:: {more comment}
|
||||
:: {ship2} {date}
|
||||
:: {comment}
|
||||
:: {more comment}
|
||||
:: {more comment}
|
33
pub/work/fab/hymn.hook
Normal file
33
pub/work/fab/hymn.hook
Normal file
@ -0,0 +1,33 @@
|
||||
::
|
||||
::
|
||||
:::: /hook/hymn/fab/talk/pub/
|
||||
::
|
||||
|%
|
||||
++ cdnj
|
||||
|= a=wall ^- marl
|
||||
%+ turn a
|
||||
|= lib=tape
|
||||
;script(type "text/javascript", src "//cdnjs.cloudflare.com/ajax/libs/{lib}");
|
||||
--
|
||||
::
|
||||
::::
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;* %- cdnj :~
|
||||
"jquery/2.1.1/jquery.js"
|
||||
"lodash.js/2.4.1/lodash.min.js"
|
||||
"react/0.13.1/react.js"
|
||||
==
|
||||
;meta(name "viewport", content "width=device-width, height=device-height, ".
|
||||
"initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0");
|
||||
;link(type "text/css", rel "stylesheet", href "/home/pub/work/src/css/main.css");
|
||||
;title: Talk
|
||||
==
|
||||
;body
|
||||
;div#c;
|
||||
;script(type "text/javascript", src "/home/pub/work/src/js/main.js");
|
||||
==
|
||||
==
|
84
pub/work/src/css/fonts.styl
Normal file
84
pub/work/src/css/fonts.styl
Normal file
@ -0,0 +1,84 @@
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-black.woff");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
235
pub/work/src/css/main.css
Normal file
235
pub/work/src/css/main.css
Normal file
@ -0,0 +1,235 @@
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("http://storage.googleapis.com/urbit-extra/scp-black.woff");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
font-family: "bau";
|
||||
font-size: 18px;
|
||||
}
|
||||
#c {
|
||||
position: absolute;
|
||||
top: 0rem;
|
||||
left: 50%;
|
||||
width: 34rem;
|
||||
margin-left: -17rem;
|
||||
margin-bottom: 12rem;
|
||||
}
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
}
|
||||
.items {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
.item {
|
||||
display: block;
|
||||
max-height: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
width: 36rem;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
transition: max-height 200ms linear;
|
||||
}
|
||||
.item .comments {
|
||||
height: 0;
|
||||
}
|
||||
.item.expand {
|
||||
max-height: 16rem;
|
||||
transition: max-height 200ms linear;
|
||||
}
|
||||
.item .expand {
|
||||
margin-left: 2rem;
|
||||
cursor: pointer;
|
||||
transform-origin: 3px 12px;
|
||||
transition: transform 200ms linear;
|
||||
}
|
||||
.item.expand .expand {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms linear;
|
||||
}
|
||||
.item .sort,
|
||||
.item .title,
|
||||
.item .date,
|
||||
.item .tags,
|
||||
.item .comment {
|
||||
line-height: 2rem;
|
||||
}
|
||||
.item .sort,
|
||||
.item .date {
|
||||
font-family: 'scp';
|
||||
}
|
||||
.item .audience,
|
||||
.item .date {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
.item .audience,
|
||||
.item .sort {
|
||||
color: #ccc;
|
||||
}
|
||||
.item .audience {
|
||||
text-transform: uppercase;
|
||||
height: 1rem;
|
||||
letter-spacing: 0.07rem;
|
||||
margin-left: 2.2rem;
|
||||
}
|
||||
.item .done {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
margin-top: 0.5rem;
|
||||
border: 0.2rem solid #ccc;
|
||||
}
|
||||
.item .sort {
|
||||
font-size: 0.6rem;
|
||||
width: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
.item .title {
|
||||
min-width: 16rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
.item .date {
|
||||
min-width: 6rem;
|
||||
}
|
||||
.item .tags {
|
||||
min-width: 6rem;
|
||||
}
|
||||
.item .description,
|
||||
.item .discussion {
|
||||
line-height: 2rem;
|
||||
margin: 0.5rem 0 0.5rem 2.3rem;
|
||||
}
|
||||
.item .description textarea {
|
||||
min-width: 20rem;
|
||||
min-height: 6rem;
|
||||
}
|
||||
.item .hr {
|
||||
height: 0.2rem;
|
||||
width: 6rem;
|
||||
}
|
||||
.item .comp {
|
||||
width: 3rem;
|
||||
opacity: 0;
|
||||
}
|
||||
.item .comp .a {
|
||||
display: block;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
line-height: 0.9rem;
|
||||
}
|
||||
.item:hover .comp {
|
||||
opacity: 1;
|
||||
}
|
||||
/* global */
|
||||
.top {
|
||||
vertical-align: top;
|
||||
}
|
||||
.ib {
|
||||
display: inline-block;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.a {
|
||||
display: inline;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.input {
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
padding: 0 0.3rem;
|
||||
background-color: #f9f9f9;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
resize: none;
|
||||
}
|
||||
.input:focus {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.caret.left {
|
||||
border-left: 6px solid #000;
|
||||
border-top: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid transparent;
|
||||
margin-top: 0.4rem;
|
||||
}
|
158
pub/work/src/css/main.styl
Normal file
158
pub/work/src/css/main.styl
Normal file
@ -0,0 +1,158 @@
|
||||
//
|
||||
// fonts first
|
||||
//
|
||||
|
||||
@import 'fonts'
|
||||
|
||||
html
|
||||
body
|
||||
font-family "bau"
|
||||
font-size 18px
|
||||
|
||||
#c
|
||||
position absolute
|
||||
top 0rem
|
||||
left 50%
|
||||
width 34rem
|
||||
margin-left -17rem
|
||||
margin-bottom 12rem
|
||||
|
||||
h1
|
||||
font-weight 500
|
||||
|
||||
.items
|
||||
margin-top 4rem
|
||||
|
||||
.item
|
||||
display block
|
||||
max-height 3rem
|
||||
margin-bottom 1.5rem
|
||||
width 36rem
|
||||
overflow hidden
|
||||
background-color #fff
|
||||
transition max-height 200ms linear
|
||||
|
||||
.item .comments
|
||||
height 0
|
||||
|
||||
.item.expand
|
||||
max-height 16rem
|
||||
transition max-height 200ms linear
|
||||
|
||||
.item .expand
|
||||
margin-left 2rem
|
||||
cursor pointer
|
||||
transform-origin 3px 12px
|
||||
transition transform 200ms linear
|
||||
|
||||
.item.expand .expand
|
||||
transform rotate(90deg)
|
||||
transition transform 200ms linear
|
||||
|
||||
.item .sort
|
||||
.item .title
|
||||
.item .date
|
||||
.item .tags
|
||||
.item .comment
|
||||
line-height 2rem
|
||||
|
||||
.item .sort
|
||||
.item .date
|
||||
font-family 'scp'
|
||||
|
||||
.item .audience
|
||||
.item .date
|
||||
font-size .7rem
|
||||
|
||||
.item .audience
|
||||
.item .sort
|
||||
color #ccc
|
||||
|
||||
.item .audience
|
||||
text-transform uppercase
|
||||
height 1rem
|
||||
letter-spacing .07rem
|
||||
margin-left 2.2rem
|
||||
|
||||
.item .done
|
||||
width .7rem
|
||||
height .7rem
|
||||
margin-top .5rem
|
||||
border .2rem solid #ccc
|
||||
|
||||
.item .sort
|
||||
font-size .6rem
|
||||
width 2rem
|
||||
text-align center
|
||||
|
||||
.item .title
|
||||
min-width 16rem
|
||||
margin-left .5rem
|
||||
|
||||
.item .date
|
||||
min-width 6rem
|
||||
|
||||
.item .tags
|
||||
min-width 6rem
|
||||
|
||||
.item .description
|
||||
.item .discussion
|
||||
line-height 2rem
|
||||
margin .5rem 0 .5rem 2.3rem
|
||||
|
||||
.item .description textarea
|
||||
min-width 20rem
|
||||
min-height 6rem
|
||||
|
||||
.item .hr
|
||||
height .2rem
|
||||
width 6rem
|
||||
|
||||
|
||||
.item .comp
|
||||
width 3rem
|
||||
opacity 0
|
||||
|
||||
.item .comp .a
|
||||
display block
|
||||
font-size .7rem
|
||||
font-weight 500
|
||||
line-height .9rem
|
||||
|
||||
.item:hover .comp
|
||||
opacity 1
|
||||
|
||||
/* global */
|
||||
|
||||
.top
|
||||
vertical-align top
|
||||
|
||||
.ib
|
||||
display inline-block
|
||||
|
||||
.hidden
|
||||
display none
|
||||
|
||||
.a
|
||||
display inline
|
||||
cursor pointer
|
||||
text-decoration underline
|
||||
|
||||
.input
|
||||
outline none
|
||||
display inline-block
|
||||
padding 0 .3rem
|
||||
background-color #f9f9f9
|
||||
border 0
|
||||
font inherit
|
||||
resize none
|
||||
|
||||
.input:focus
|
||||
background-color #e6e6e6
|
||||
|
||||
.caret.left
|
||||
border-left 6px solid #000
|
||||
border-top 6px solid transparent
|
||||
border-right 6px solid transparent
|
||||
border-bottom 6px solid transparent
|
||||
margin-top .4rem
|
28
pub/work/src/js/actions/WorkActions.coffee
Normal file
28
pub/work/src/js/actions/WorkActions.coffee
Normal file
@ -0,0 +1,28 @@
|
||||
Dispatcher = require '../dispatcher/Dispatcher.coffee'
|
||||
|
||||
module.exports =
|
||||
newItem: (index,list) ->
|
||||
Dispatcher.handleViewAction
|
||||
type:'newItem'
|
||||
index:index
|
||||
list:list
|
||||
|
||||
swapItems: (to,from,list) ->
|
||||
Dispatcher.handleViewAction
|
||||
type:'swapItem'
|
||||
from:from
|
||||
list:list
|
||||
to:to
|
||||
|
||||
removeItem: (index,list) ->
|
||||
Dispatcher.handleViewAction
|
||||
type:'removeItem'
|
||||
index:index
|
||||
list:list
|
||||
|
||||
addItem: (index,item,list) ->
|
||||
Dispatcher.handleViewAction
|
||||
type:'addItem'
|
||||
list:list
|
||||
index:index
|
||||
item:item
|
98
pub/work/src/js/components/ItemComponent.coffee
Normal file
98
pub/work/src/js/components/ItemComponent.coffee
Normal file
@ -0,0 +1,98 @@
|
||||
recl = React.createClass
|
||||
[div,textarea] = [React.DOM.div,React.DOM.textarea]
|
||||
|
||||
WorkActions = require '../actions/WorkActions.coffee'
|
||||
|
||||
module.exports = recl
|
||||
_dragStart: (e) ->
|
||||
$t = $(e.target)
|
||||
@dragged = $t.closest('.item')
|
||||
e.dataTransfer.effectAllowed = 'move'
|
||||
e.dataTransfer.setData 'text/html',e.currentTarget
|
||||
@props._dragStart e,@
|
||||
|
||||
_dragEnd: (e) -> @props._dragEnd e,@
|
||||
|
||||
_keyDown: (e) ->
|
||||
@props._keyDown e,@
|
||||
|
||||
kc = e.keyCode
|
||||
|
||||
switch kc
|
||||
# tab - expand
|
||||
when 9
|
||||
if @state.expand is false
|
||||
@setState {expand:true}
|
||||
# esc - collapse
|
||||
when 27
|
||||
@setState {expand:false}
|
||||
|
||||
if (kc is 9 and @state.expand is false) or (kc is 27)
|
||||
e.preventDefault()
|
||||
return
|
||||
|
||||
_focus: (e) -> @props._focus e,@
|
||||
|
||||
formatDate: (d) ->
|
||||
"#{d.getDate()}-#{(d.getMonth()+1)}-#{d.getFullYear()}"
|
||||
|
||||
getInitialState: -> {expand:false}
|
||||
|
||||
render: ->
|
||||
itemClass = 'item'
|
||||
if @state.expand then itemClass += ' expand'
|
||||
|
||||
(div {
|
||||
className:itemClass
|
||||
draggable:true
|
||||
'data-index':@props.index
|
||||
onDragStart:@_dragStart
|
||||
onDragEnd:@_dragEnd
|
||||
'data-index':@props.index
|
||||
}, [
|
||||
(div {className:'audience'},@props.item.audience.join(" "))
|
||||
(div {className:'sort ib top'},@props.index)
|
||||
(div {className:'done ib'},'')
|
||||
(div {className:'title ib top'},[
|
||||
(div {
|
||||
contentEditable:true
|
||||
onFocus:@_focus
|
||||
onKeyDown:@_keyDown
|
||||
className:'input'
|
||||
},@props.item.title)
|
||||
])
|
||||
(div {className:'date ib top'}, [
|
||||
(div {
|
||||
contentEditable:true
|
||||
className:'input'
|
||||
},@formatDate(@props.item['date-created']))
|
||||
])
|
||||
(div {className:'tags ib top'},[
|
||||
(div {
|
||||
contentEditable:true
|
||||
className:'input'
|
||||
},@props.item.tags.join(" "))
|
||||
])
|
||||
(div {
|
||||
className:'expand ib',
|
||||
onClick: (e) =>
|
||||
@setState {expand:!@state.expand}
|
||||
},[
|
||||
(div {className:'caret left'},"")
|
||||
])
|
||||
(div {className:"description"},[
|
||||
(textarea {
|
||||
className:'input'
|
||||
},@props.item.description)
|
||||
])
|
||||
(div {className:"hr"},"")
|
||||
(div {className:"discussion"},[
|
||||
(div {className:"comments"}, @props.item.discussion.map (slug) ->
|
||||
(div {className:'slug'}, slug)
|
||||
),
|
||||
(div {
|
||||
contentEditable:true
|
||||
className:'input comment'
|
||||
},"")
|
||||
])
|
||||
])
|
121
pub/work/src/js/components/ListComponent.coffee
Normal file
121
pub/work/src/js/components/ListComponent.coffee
Normal file
@ -0,0 +1,121 @@
|
||||
recl = React.createClass
|
||||
rece = React.createElement
|
||||
[div,h1,input,textarea] = [React.DOM.div,React.DOM.h1,React.DOM.input,React.DOM.textarea]
|
||||
|
||||
WorkStore = require '../stores/WorkStore.coffee'
|
||||
WorkActions = require '../actions/WorkActions.coffee'
|
||||
ItemComponent = require './ItemComponent.coffee'
|
||||
|
||||
module.exports = recl
|
||||
stateFromStore: -> {
|
||||
list:WorkStore.getList @props.list
|
||||
expand:false
|
||||
}
|
||||
|
||||
getInitialState: -> @stateFromStore()
|
||||
_onChangeStore: -> @setState @stateFromStore()
|
||||
|
||||
alias: ->
|
||||
@$el = $ @getDOMNode()
|
||||
@$items = @$el.find('.items').children()
|
||||
|
||||
_focus: (e,i) -> @setState {selected:Number(i.props.index)}
|
||||
|
||||
_dragStart: (e,i) -> @dragged = i.dragged
|
||||
|
||||
_dragEnd: (e,i) ->
|
||||
from = Number @dragged.attr('data-index')
|
||||
to = Number @over.attr('data-index')
|
||||
if from<to then to--
|
||||
if @drop is 'after' then to++
|
||||
WorkActions.swapItems to,from,@props.list
|
||||
@dragged.removeClass 'hidden'
|
||||
@placeholder.remove()
|
||||
|
||||
_dragOver: (e,i) ->
|
||||
e.preventDefault()
|
||||
$t = $(e.target).closest('.item')
|
||||
if $t.hasClass 'placeholder' then return
|
||||
if $t.length is 0 then return
|
||||
@over = $t
|
||||
if not @dragged.hasClass('hidden') then @dragged.addClass 'hidden'
|
||||
if (e.clientY - $t[0].offsetTop) < ($t[0].offsetHeight / 2)
|
||||
@drop = 'before'
|
||||
@placeholder.insertBefore $t
|
||||
else
|
||||
@drop = 'after'
|
||||
@placeholder.insertAfter $t
|
||||
|
||||
_keyDown: (e) ->
|
||||
kc = e.keyCode
|
||||
|
||||
switch kc
|
||||
# enter - add new
|
||||
when 13
|
||||
if window.getSelection().getRangeAt(0).endOffset is 0
|
||||
ins = @state.selected
|
||||
else
|
||||
ins = @state.selected+1
|
||||
@setState {selected:ins,select:true}
|
||||
WorkActions.newItem ins,@props.list
|
||||
# backspace - remove if at 0
|
||||
when 8
|
||||
if window.getSelection().getRangeAt(0).endOffset is 0 and
|
||||
e.target.innerText.length is 0
|
||||
if @state.selected isnt 0
|
||||
@setState {selected:@state.selected-1,select:"end"}
|
||||
WorkActions.removeItem @state.selected,@props.list
|
||||
e.preventDefault()
|
||||
# up
|
||||
when 38
|
||||
last = @state.selected-1
|
||||
if last<0 then last = @state.list.length-1
|
||||
@$items.eq(last).find('.title .input').focus()
|
||||
@setState {select:"end"}
|
||||
# down
|
||||
when 40
|
||||
next = @state.selected+1
|
||||
if next is @state.list.length then next = 0
|
||||
@$items.eq(next).find('.title .input').focus()
|
||||
@setState {select:"end"}
|
||||
|
||||
# cancel these
|
||||
if (kc is 13) or (kc is 38) or (kc is 40) then e.preventDefault()
|
||||
|
||||
componentDidMount: ->
|
||||
@placeholder = $ "<div class='item placeholder'><div class='sort'>x</div></div>"
|
||||
WorkStore.addChangeListener @_onChangeStore
|
||||
@alias()
|
||||
|
||||
componentDidUpdate: ->
|
||||
@alias()
|
||||
if @state.selected isnt undefined or @state.select
|
||||
$title = @$items.eq(@state.selected).find('.title .input')
|
||||
if @state.selected isnt undefined and @state.select
|
||||
$title.focus()
|
||||
if @state.select is "end"
|
||||
r = window.getSelection().getRangeAt(0)
|
||||
r.setStart $title[0],1
|
||||
r.setEnd $title[0],1
|
||||
s = window.getSelection()
|
||||
s.removeAllRanges()
|
||||
s.addRange r
|
||||
if @state.select
|
||||
@setState {select:false}
|
||||
|
||||
render: ->
|
||||
(div {}, [
|
||||
(div {
|
||||
className:'items'
|
||||
onDragOver:@_dragOver
|
||||
}, [
|
||||
_.map @state.list,(item,index) =>
|
||||
rece(ItemComponent,{
|
||||
item
|
||||
index
|
||||
@_focus
|
||||
@_keyDown
|
||||
@_dragStart
|
||||
@_dragEnd})
|
||||
])
|
||||
])
|
11
pub/work/src/js/components/WorkComponent.coffee
Normal file
11
pub/work/src/js/components/WorkComponent.coffee
Normal file
@ -0,0 +1,11 @@
|
||||
recl = React.createClass
|
||||
rece = React.createElement
|
||||
[div,input,textarea] = [React.DOM.div,React.DOM.input,React.DOM.textarea]
|
||||
|
||||
ListComponent = require './ListComponent.coffee'
|
||||
|
||||
module.exports = recl
|
||||
render: ->
|
||||
(div {}, [
|
||||
(rece(ListComponent,{list:'upcoming'}))
|
||||
])
|
13
pub/work/src/js/dispatcher/dispatcher.coffee
Normal file
13
pub/work/src/js/dispatcher/dispatcher.coffee
Normal file
@ -0,0 +1,13 @@
|
||||
Dispatcher = require('flux').Dispatcher
|
||||
|
||||
module.exports = _.merge new Dispatcher(), {
|
||||
handleServerAction: (action) ->
|
||||
@dispatch
|
||||
source: 'server'
|
||||
action: action
|
||||
|
||||
handleViewAction: (action) ->
|
||||
@dispatch
|
||||
source: 'view'
|
||||
action: action
|
||||
}
|
4
pub/work/src/js/main.coffee
Normal file
4
pub/work/src/js/main.coffee
Normal file
@ -0,0 +1,4 @@
|
||||
WorkComponent = require './components/WorkComponent.coffee'
|
||||
|
||||
$ ->
|
||||
React.render React.createElement(WorkComponent),$('#c')[0]
|
1192
pub/work/src/js/main.js
Normal file
1192
pub/work/src/js/main.js
Normal file
File diff suppressed because it is too large
Load Diff
17
pub/work/src/js/package.json
Normal file
17
pub/work/src/js/package.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "urbit-work",
|
||||
"version": "0.0.0",
|
||||
"repository": {
|
||||
"type":"git",
|
||||
"url":"https://github.com/urbit/urbit"
|
||||
},
|
||||
"description": "urbit work frontend",
|
||||
"main": "main.js",
|
||||
"dependencies": {
|
||||
"coffeeify": "~0.7.0",
|
||||
"flux": "~2.0.1",
|
||||
"lodash": "~2.4.1",
|
||||
"moment-timezone": "~0.2.4",
|
||||
"object-assign": "^1.0.0"
|
||||
}
|
||||
}
|
95
pub/work/src/js/stores/WorkStore.coffee
Normal file
95
pub/work/src/js/stores/WorkStore.coffee
Normal file
@ -0,0 +1,95 @@
|
||||
EventEmitter = require('events').EventEmitter
|
||||
assign = require 'object-assign'
|
||||
Dispatcher = require '../dispatcher/Dispatcher.coffee'
|
||||
|
||||
_upcoming = [
|
||||
id:0
|
||||
sort:0
|
||||
"date-created":new Date('2015-8-18')
|
||||
"date-modifed":new Date('2015-8-18')
|
||||
"date-due":null
|
||||
owner:"~talsur-todres"
|
||||
audience:["doznec/urbit-meta","doznec/tlon"]
|
||||
status:"working"
|
||||
tags:['food','office']
|
||||
title:'get groceries'
|
||||
description:'first go out the door, \n then walk down the block.'
|
||||
discussion:[]
|
||||
,
|
||||
id:1
|
||||
sort:1
|
||||
"date-created":new Date('2015-8-18')
|
||||
"date-modifed":new Date('2015-8-18')
|
||||
"date-due":null
|
||||
owner:"~talsur-todres"
|
||||
audience:["doznec/tlon"]
|
||||
status:"working"
|
||||
tags:['home','office']
|
||||
title:'eat'
|
||||
description:'dont forget about lunch.'
|
||||
discussion:[]
|
||||
,
|
||||
id:2
|
||||
sort:2
|
||||
"date-created":new Date('2015-8-18')
|
||||
"date-modifed":new Date('2015-8-18')
|
||||
"date-due":null
|
||||
owner:"~talsur-todres"
|
||||
audience:["doznec/tlon"]
|
||||
status:"working"
|
||||
tags:['home']
|
||||
title:'sleep'
|
||||
description:'go get some sleep.'
|
||||
discussion:[]
|
||||
]
|
||||
_following = {}
|
||||
_incoming = {}
|
||||
|
||||
lists =
|
||||
'upcoming':_upcoming
|
||||
'following':_following
|
||||
'incoming':_incoming
|
||||
|
||||
WorkStore = assign {},EventEmitter.prototype,{
|
||||
emitChange: -> @emit 'change'
|
||||
addChangeListener: (cb) -> @on 'change', cb
|
||||
removeChangeListener: (cb) -> @removeListener "change", cb
|
||||
|
||||
getList: (key) -> lists[key]
|
||||
|
||||
newItem: ({index,list}) ->
|
||||
list = lists[list]
|
||||
item =
|
||||
id:index
|
||||
sort:index
|
||||
"date-created":new Date()
|
||||
"date-modifed":new Date()
|
||||
"date-due":null
|
||||
owner:"~talsur-todres"
|
||||
status:null
|
||||
tags:[]
|
||||
title:''
|
||||
description:''
|
||||
discussion:[]
|
||||
list.splice index,0,item
|
||||
|
||||
swapItem: ({to,from,list}) ->
|
||||
list = lists[list]
|
||||
list.splice to,0,list.splice(from,1)[0]
|
||||
|
||||
removeItem: ({index,list}) ->
|
||||
list = lists[list]
|
||||
list.splice index,1
|
||||
|
||||
}
|
||||
|
||||
WorkStore.setMaxListeners 100
|
||||
|
||||
WorkStore.dispatchToken = Dispatcher.register (p) ->
|
||||
a = p.action
|
||||
|
||||
if WorkStore[a.type]
|
||||
WorkStore[a.type] a
|
||||
WorkStore.emitChange()
|
||||
|
||||
module.exports = WorkStore
|
8
pub/work/test.work-task
Normal file
8
pub/work/test.work-task
Normal file
@ -0,0 +1,8 @@
|
||||
0v0_~1999.1.1 2~1999.1.2 ~1999.5.20
|
||||
Tagged!
|
||||
Yoooo
|
||||
~fyr.gave
|
||||
Testin
|
||||
~doznec ~2015.1.3
|
||||
how long has
|
||||
this been around?
|
52
sur/work.hoon
Normal file
52
sur/work.hoon
Normal file
@ -0,0 +1,52 @@
|
||||
/- talk
|
||||
|%
|
||||
++ client
|
||||
$: tasks=(map ,@uvH client-task)
|
||||
sort=(list ,@uvH)
|
||||
==
|
||||
++ client-task
|
||||
$: task=task
|
||||
audience=(set station:talk)
|
||||
==
|
||||
++ task
|
||||
$: id=@uvH
|
||||
date-created=@da
|
||||
version=@u
|
||||
date-modified=@da
|
||||
owner=@p
|
||||
status=status
|
||||
tags=(set ,@t)
|
||||
due-date=(unit ,@da)
|
||||
title=@t
|
||||
description=@t
|
||||
discussion=(list comment)
|
||||
==
|
||||
++ comment
|
||||
$: date=@da
|
||||
ship=@p
|
||||
body=@t
|
||||
==
|
||||
++ status ?(%took %gave %left)
|
||||
++ command
|
||||
$% [%new task]
|
||||
[%old id=@uvH dif=update]
|
||||
[%sort p=(list ,@uvH)]
|
||||
==
|
||||
++ update
|
||||
$% $: %set
|
||||
$% [%due-date p=@da]
|
||||
[%title p=@t]
|
||||
[%description p=@t]
|
||||
[%tags p=(set ,@t)]
|
||||
[%done p=(unit ,@da)]
|
||||
[%audience p=(set station:talk)]
|
||||
== ==
|
||||
$: %add
|
||||
$% [%comment [@da @t]]
|
||||
== ==
|
||||
$: %own
|
||||
$% [%announce ~]
|
||||
[%claim ~]
|
||||
== ==
|
||||
==
|
||||
--
|
Loading…
Reference in New Issue
Block a user