mirror of
https://github.com/ilyakooo0/urbit.git
synced 2025-01-07 07:30:23 +03:00
work
This commit is contained in:
parent
9081b3a278
commit
743b0a632e
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
|
Loading…
Reference in New Issue
Block a user