worked it out

This commit is contained in:
Galen Wolfe-Pauly 2015-08-21 17:29:03 -07:00
commit 13f9404abb
10 changed files with 268 additions and 201 deletions

View File

@ -1,4 +1,14 @@
:: not implemented: set audience
:: when adding a station, send a new create. need to eliminate
:: sanity checks to make this work. when removing a station,
:: send a %archive message, which signifies that you'll no longer
:: receive updates to that task.
:: check ++prep for initialize
:: also check if talk can add stations to something other than porch
:: maybe look into storing a "following" set
:: make most updates not rely on knowing about task (all but claim?)
:: should let non-owners suggest that owner cross-post to another
:: station
::
::::
::
@ -24,28 +34,27 @@
::
|_ [bowl client connected=_|]
++ at
|= [claiming=? audience=(set station:talk) task]
=* tax +<+>
|= client-task
=| moves=(list move)
|%
++ abet
^- [(list move) _+>.$]
[(flop moves) +>.$(tasks (~(put by tasks) id +<.$))]
[(flop moves) +>.$(tasks (~(put by tasks) id.tax +<.$))]
::
++ abut
^- [(list move) _+>.$]
[(flop moves) +>.$]
::
++ send
|= action=duty:work-stuff:talk
++ send-audience
|= [to=(set station:talk) action=duty:work-stuff:talk]
^+ +>
%_ +>.$
eny (sham eny action)
moves
:_ ~
:_ moves
^- move
:* ost %poke
/sending/(scot %uv id)/(scot %ud version)
/sending/(scot %uv id.tax)/(scot %ud version.tax)
[our %talk]
%talk-command
^- command:talk
@ -54,36 +63,25 @@
:_ ~
:+ (shaf %task eny)
%- mo ^- (list ,[partner envelope delivery]:talk)
%+ turn (~(tap in audience))
%+ turn (~(tap in to))
|=(sat=station:talk [[%& sat] [*envelope %pending]])
[now *bouquet [%tax action]]
==
==
::
++ claim
%_ .
eny (sham eny %direct)
claiming &
moves
:_ ~
^- move
:* ost %poke
/claiming/(scot %uv id)
[our %talk]
%talk-command
^- command:talk
:- %publish
|- ^- (list thought)
:_ ~
:+ (shaf %task eny)
[[[%& owner (main owner)] [*envelope %pending]] ~ ~]
[now *bouquet [%tax %claim id]]
==
==
++ send
|= action=duty:work-stuff:talk
(send-audience audience action)
::
++ create %+ send %create
tax(date-created now, version 0, date-modified now)
++ send-update |*(* (send %update id +<))
++ claim
(send-audience(claiming &) [[owner.tax (main owner.tax)] ~ ~] %claim id.tax)
::
++ send-archive
|= to=(set station:talk)
(send-audience to %archive id.tax)
::
++ send-create (send %create tax)
++ send-update |*(* (send %update id.tax +<))
++ release |=([vers=@u her=@p] (send-update vers %release her))
++ accept |=(vers=@u (send-update vers %accept ~))
++ process-update
@ -103,9 +101,14 @@
%description (send-update vers %set-description +>.up)
%tags (send-update vers %set-tags +>.up)
%done (send-update vers %set-done +>.up)
%audience ~|(%not-implemented !!)
==
==
++ process-audience
|= to=(set station:talk)
^+ +>
=. +>.$ (send-archive (~(dif in audience) to))
=. +>.$ (send-audience (~(dif in to) audience) %create tax)
+>.$(audience to)
--
::
++ initialize
@ -120,17 +123,19 @@
[(welp mos mof) con]
^- [mos=(list move) con=_+>.$]
?- -.action
%create :: XX should verify ownership
%create
=+ existing-task=(~(get by tasks) id.tax.action)
~? ?& ?=(^ existing-task)
!=(tax.action task.u.existing-task)
?: ?& ?=(^ existing-task)
!=(tax.action tax.u.existing-task)
!archived.u.existing-task
==
:* %new-task-with-old-id
her=her
from=from
new-task=tax.action
existing-task=u.existing-task
==
~& :* %new-task-with-old-id
her=her
from=from
new-task=tax.action
existing-task=u.existing-task
==
[~ +>.$]
?. |(=(her owner.tax.action) =(%released status.tax.action))
~& :* %created-with-bad-owner
her=her
@ -139,17 +144,9 @@
existing-task=existing-task
==
[~ +>.$]
?. =(0 version.tax.action)
~& :* %new-task-version-not-zero
her=her
from=from
new-task=tax.action
existing-task=existing-task
==
[~ +>.$]
=. tasks
%^ ~(put by tasks) id.tax.action |
:_ tax.action
%^ ~(put by tasks) id.tax.action |
:- | :_ tax.action
?~ existing-task from
(~(uni in audience.u.existing-task) from)
=. sort ?^(existing-task sort [id.tax.action sort])
@ -157,14 +154,40 @@
::
%claim
=+ tax=(~(got by tasks) id.action)
?. &(=(our owner.task.tax) =(%announced status.task.tax))
?. &(=(our owner.tax.tax) =(%announced status.tax.tax))
~& :* %bad-claim
her=her
from=from
task=tax
==
[~ +>.$]
abet:(release:(at (~(got by tasks) id.action)) +(version.task.tax) her)
abet:(release:(at (~(got by tasks) id.action)) +(version.tax.tax) her)
::
%archive
=+ tax=(~(get by tasks) id.action)
?~ tax
~& :* %archive-for-nonexistent-task
her=her
from=from
action=action
==
[~ +>.$]
?: !=(her owner.tax.u.tax)
~& :* %archiver-not-owner
her=her
from=from
action=action
tax=tax
==
[~ +>.$]
=. tasks
%+ ~(put by tasks) id.action
:* claiming.u.tax
=(~ (~(dif in audience.u.tax) from))
(~(dif in audience.u.tax) from)
tax.u.tax
==
[~ +>.$]
::
%update
=+ tax=(~(get by tasks) id.action)
@ -175,7 +198,7 @@
action=action
==
[~ +>.$]
?. =(version.action +(version.task.u.tax))
?. =(version.action +(version.tax.u.tax))
~& :* %update-bad-version
her
from=from
@ -183,42 +206,47 @@
tax=tax
==
[~ +>.$]
=. tasks
%^ ~(put by tasks) id.action
?: ?=(%release -.meat.action)
|
claiming.u.tax
:- (~(uni in audience.u.tax) from)
?: ?& ?=(?(%announce %release %accept) -.meat.action)
!=(her owner.task.u.tax)
?: ?& ?=(?(%announce %release %accept) -.meat.action)
!=(her owner.tax.u.tax)
==
~& :* %not-owner
her=her
from=from
action=action
tax=tax
==
~& :* %not-owner
her=her
from=from
action=action
tax=tax
==
task.u.tax
=. version.task.u.tax version.action
=. date-modified.task.u.tax when
?- -.meat.action
%announce task.u.tax(status %announced)
%release task.u.tax(owner her.meat.action, status %released)
%accept task.u.tax(status %accepted)
%set-date-due task.u.tax(date-due wen.meat.action)
%set-tags task.u.tax(tags tag.meat.action)
%set-title task.u.tax(title til.meat.action)
%set-description task.u.tax(description des.meat.action)
%set-done task.u.tax(done ?.(don.meat.action ~ `when))
%add-comment
%= task.u.tax
discussion [[when her com.meat.action] discussion.task.u.tax]
[~ +>.$]
=. tasks
%+ ~(put by tasks) id.action
:* ?: ?=(%release -.meat.action)
|
claiming.u.tax
::
archived.u.tax
::
(~(uni in audience.u.tax) from)
::
=. version.tax.u.tax version.action
=. date-modified.tax.u.tax when
?- -.meat.action
%announce tax.u.tax(status %announced)
%release tax.u.tax(owner her.meat.action, status %released)
%accept tax.u.tax(status %accepted)
%set-date-due tax.u.tax(date-due wen.meat.action)
%set-tags tax.u.tax(tags tag.meat.action)
%set-title tax.u.tax(title til.meat.action)
%set-description tax.u.tax(description des.meat.action)
%set-done tax.u.tax(done ?.(don.meat.action ~ `when))
%add-comment
%= tax.u.tax
discussion [[when her com.meat.action] discussion.tax.u.tax]
==
==
==
?: ?& =([%release our] meat.action)
claiming.u.tax
==
abet:(accept:(at (~(got by tasks) id.action)) +(+(version.task.u.tax)))
abet:(accept:(at (~(got by tasks) id.action)) +(+(version.tax.u.tax)))
[~ +>.$]
==
::
@ -255,10 +283,18 @@
initialize
=^ mof +>.$
?- -.cod
%new abut:create:(at [| - +]:+.cod)
%old =+ (at (~(got by tasks) id.cod))
abet:(process-update:- version.cod dif.cod)
%sort mirror-to-web(sort p.cod)
%sort mirror-to-web(sort p.cod)
%audience
=^ mow +>.$
abet:(process-audience:(at (~(got by tasks) id.cod)) to.cod)
=^ mov +>.$ mirror-to-web
[(welp mow mov) +>.$]
%old
=+ (at (~(got by tasks) id.cod))
abet:(process-update:- version.cod dif.cod)
%new
=. +>.cod +>.cod(date-created now, version 0, date-modified now)
abut:send-create:(at | | +.cod)
==
[(welp mos mof) +>.$]
::

View File

@ -49,7 +49,11 @@
==
++ id (ci (slat %uv) so)
++ ship (su fed:ag)
++ coma (of new/task old/(ot id/id version/ni dif/uppd ~) sort/(ar id) ~)
++ coma
%- of :~
new/task old/(ot id/id version/ni dif/uppd ~)
sort/(ar id) audience/(ot id/id to/audi ~)
==
++ task
%- ot :~
audience/audi
@ -73,7 +77,6 @@
description/so
tags/(as so)
done/bo
audience/audi
==
==
--

View File

@ -13,7 +13,7 @@
sort/[%a (turn sort |=(a=@uv [%s (scot %uv a)]))]
=< tasks/(jobe (turn (~(tap by tasks)) .))
|= [@ client-task]
=+ task
=+ tax
:- (scot %uv id)
%- jobe :~ id/[%s (scot %uv id)]
tags/[%a (turn (~(tap in tags)) |=(a=cord s/a))]

View File

@ -17,8 +17,8 @@ module.exports =
description: _item.description ? ''
discussion: _item.discussion ? []
audience: _item.audience ?
["~zod/share", window.util.talk.mainStationPath window.urb.ship]
Persistence.put "new":item
[window.util.talk.mainStationPath window.urb.ship]
Persistence.put new:item
Dispatcher.handleViewAction {type:'newItem', index, item}
setItem: ({id,version},key,val) ->
@ -38,35 +38,21 @@ module.exports =
version += 1
Persistence.put old:{id,version,dif:add:comment:val}
setFilter: (key,val) ->
Dispatcher.handleViewAction
type:'setFilter'
key:key
val:val
setSort: (key,val) ->
Dispatcher.handleViewAction
type:'setSort'
key:key
val:val
swapItems: (to,from) ->
Dispatcher.handleViewAction
type:'swapItem'
from:from
to:to
removeItem: ({id,version},index) ->
Persistence.put old:{id,version,dif:set:done:true}
Dispatcher.handleViewAction
type:'removeItem'
index:index
setFilter: (key,val) -> Dispatcher.handleViewAction {type:'setFilter', key,val}
setSort: (key,val) -> Dispatcher.handleViewAction {type:'setSort',key,val}
moveItem: (list,to,from) ->
sort = _.clone list
sort.splice to, 0, sort.splice(from,1)[0]
Persistence.put {sort}
Dispatcher.handleViewAction {list:sort,to,from,type:'moveItems'}
addItem: (index,item) ->
Dispatcher.handleViewAction
type:'addItem'
index:index
item:item
Dispatcher.handleViewAction {type:'addItem',index,item}
removeItem: ({id,version},index) ->
Persistence.put old:{id,version,dif:set:done:true}
Dispatcher.handleViewAction {type:'removeItem',index}
listenList: (type)->
Persistence.subscribe type, (err,d)->

View File

@ -5,6 +5,9 @@ WorkActions = require '../actions/WorkActions.coffee'
module.exports = recl
onDragStart: (e) ->
unless @props.draggable
e.preventDefault()
return
$t = $(e.target)
@dragged = $t.closest('.item')
e.dataTransfer.effectAllowed = 'move'

View File

@ -11,8 +11,9 @@ FilterComponent = require './FilterComponent.coffee'
SortComponent = require './SortComponent.coffee'
module.exports = recl
stateFromStore: -> {
stateFromStore: -> window.canSort = WorkStore.canSort(); {
list:WorkStore.getList()
canSort:WorkStore.canSort()
listening:WorkStore.getListening()
sorts:WorkStore.getSorts()
filters:WorkStore.getFilters()
@ -31,11 +32,11 @@ module.exports = recl
_dragStart: (e,i) -> @dragged = i.dragged
_dragEnd: (e,i) ->
from = Number @dragged.closest('item-wrap').attr('data-index')
to = Number @over.closest('item-wrap').attr('data-index')
from = Number @dragged.closest('.item-wrap').attr('data-index')
to = Number @over.closest('.item-wrap').attr('data-index')
if from<to then to--
if @drop is 'after' then to++
WorkActions.swapItems to,from
WorkActions.moveItem (id for {id} in @state.list), to, from
@dragged.removeClass 'hidden'
@placeholder.remove()
@ -139,13 +140,14 @@ module.exports = recl
className:'items'
onDragOver:@_dragOver
}, _.map @state.list,(item,index) =>
div {className:'item-wrap','data-index':index},
(div {className:'item-wrap',key:item.id,'data-index':index},
rece(ItemComponent,{
item
@_focus
@_keyDown
draggable:@state.canSort
@_dragStart
@_dragEnd
})
@_dragEnd})
)
)
])

View File

@ -24,7 +24,7 @@ module.exports = {
title: (ref4 = _item.title) != null ? ref4 : '',
description: (ref5 = _item.description) != null ? ref5 : '',
discussion: (ref6 = _item.discussion) != null ? ref6 : [],
audience: (ref7 = _item.audience) != null ? ref7 : ["~zod/share", window.util.talk.mainStationPath(window.urb.ship)]
audience: (ref7 = _item.audience) != null ? ref7 : [window.util.talk.mainStationPath(window.urb.ship)]
};
Persistence.put({
"new": item
@ -98,11 +98,25 @@ module.exports = {
val: val
});
},
swapItems: function(to, from) {
moveItem: function(list, to, from) {
var sort;
sort = _.clone(list);
sort.splice(to, 0, sort.splice(from, 1)[0]);
Persistence.put({
sort: sort
});
return Dispatcher.handleViewAction({
type: 'swapItem',
list: sort,
to: to,
from: from,
to: to
type: 'moveItems'
});
},
addItem: function(index, item) {
return Dispatcher.handleViewAction({
type: 'addItem',
index: index,
item: item
});
},
removeItem: function(arg, index) {
@ -124,13 +138,6 @@ module.exports = {
index: index
});
},
addItem: function(index, item) {
return Dispatcher.handleViewAction({
type: 'addItem',
index: index,
item: item
});
},
listenList: function(type) {
return Persistence.subscribe(type, function(err, d) {
var ref, sort, tasks;
@ -267,6 +274,10 @@ WorkActions = require('../actions/WorkActions.coffee');
module.exports = recl({
onDragStart: function(e) {
var $t;
if (!this.props.draggable) {
e.preventDefault();
return;
}
$t = $(e.target);
this.dragged = $t.closest('.item');
e.dataTransfer.effectAllowed = 'move';
@ -602,8 +613,10 @@ SortComponent = require('./SortComponent.coffee');
module.exports = recl({
stateFromStore: function() {
window.canSort = WorkStore.canSort();
return {
list: WorkStore.getList(),
canSort: WorkStore.canSort(),
listening: WorkStore.getListening(),
sorts: WorkStore.getSorts(),
filters: WorkStore.getFilters(),
@ -629,16 +642,25 @@ module.exports = recl({
return this.dragged = i.dragged;
},
_dragEnd: function(e, i) {
var from, to;
from = Number(this.dragged.closest('item-wrap').attr('data-index'));
to = Number(this.over.closest('item-wrap').attr('data-index'));
var from, id, to;
from = Number(this.dragged.closest('.item-wrap').attr('data-index'));
to = Number(this.over.closest('.item-wrap').attr('data-index'));
if (from < to) {
to--;
}
if (this.drop === 'after') {
to++;
}
WorkActions.swapItems(to, from);
WorkActions.moveItem((function() {
var j, len, ref1, results;
ref1 = this.state.list;
results = [];
for (j = 0, len = ref1.length; j < len; j++) {
id = ref1[j].id;
results.push(id);
}
return results;
}).call(this), to, from);
this.dragged.removeClass('hidden');
return this.placeholder.remove();
},
@ -778,11 +800,13 @@ module.exports = recl({
return function(item, index) {
return div({
className: 'item-wrap',
key: item.id,
'data-index': index
}, rece(ItemComponent, {
item: item,
_focus: _this._focus,
_keyDown: _this._keyDown,
draggable: _this.state.canSort,
_dragStart: _this._dragStart,
_dragEnd: _this._dragEnd
}));
@ -1311,7 +1335,7 @@ module.exports = {
},{}],15:[function(require,module,exports){
var Dispatcher, EventEmitter, WorkStore, _filters, _list, _listening, _sorts, assign;
var Dispatcher, EventEmitter, WorkStore, _filters, _list, _listening, _sorts, _tasks, assign;
EventEmitter = require('events').EventEmitter;
@ -1319,8 +1343,8 @@ assign = require('object-assign');
Dispatcher = require('../dispatcher/Dispatcher.coffee');
_list = [
{
_tasks = {
"0v0": {
id: "0v0",
version: 0,
sort: 0,
@ -1340,7 +1364,8 @@ _list = [
body: "Seems like a great idea."
}
]
}, {
},
"0v1": {
id: "0v1",
version: 0,
sort: 1,
@ -1354,7 +1379,8 @@ _list = [
title: 'eat',
description: 'dont forget about lunch.',
discussion: []
}, {
},
"0v2": {
id: "0v2",
version: 0,
sort: 2,
@ -1369,7 +1395,9 @@ _list = [
description: 'go get some sleep.',
discussion: []
}
];
};
_list = ["0v0", "0v1", "0v2"];
_listening = [];
@ -1399,33 +1427,25 @@ WorkStore = assign({}, EventEmitter.prototype, {
return this.removeListener("change", cb);
},
getData: function(arg) {
var _tasks, got, i, id, j, len, sort, tasks;
var sort, tasks;
sort = arg.sort, tasks = arg.tasks;
_tasks = _.clone(tasks);
for (i = j = 0, len = _list.length; j < len; i = ++j) {
id = _list[i].id;
if (!(got = _tasks[id])) {
continue;
}
delete _tasks[id];
_list[i] = this.itemFromData(got, i);
}
return sort.map((function(_this) {
return function(k, index) {
if (_tasks[k]) {
return _this.newItem({
item: _tasks[k],
index: index
});
return function(id, index) {
if (!_tasks[id]) {
_list.splice(index, 0, id);
}
if (tasks[id]) {
return _tasks[id] = _this.itemFromData(tasks[id], index);
}
};
})(this));
},
getList: function(key) {
var _k, _v, add, c, k, list, v;
var _k, _v, add, c, i, id, k, len, list, task, v;
list = [];
for (k in _list) {
v = _list[k];
for (i = 0, len = _list.length; i < len; i++) {
id = _list[i];
task = _tasks[id];
add = true;
for (_k in _filters) {
_v = _filters[_k];
@ -1454,7 +1474,7 @@ WorkStore = assign({}, EventEmitter.prototype, {
}
}
if (add === true) {
list.push(v);
list.push(task);
}
}
if (_.uniq(_.values(_sorts)).length > 0) {
@ -1494,6 +1514,18 @@ WorkStore = assign({}, EventEmitter.prototype, {
}
return _sorts[key] = val;
},
canSort: function() {
var k, v;
for (k in _sorts) {
v = _sorts[k];
if (k === "sort" && v === 1) {
return true;
} else if (v !== 0) {
return false;
}
}
return true;
},
itemFromData: function(item, index) {
var _item;
if (index == null) {
@ -1521,15 +1553,11 @@ WorkStore = assign({}, EventEmitter.prototype, {
});
return _item;
},
newItem: function(arg) {
var index, item;
item = arg.item, index = arg.index;
return _list.splice(index, 0, this.itemFromData(item, index));
},
swapItem: function(arg) {
var from, to;
to = arg.to, from = arg.from;
return _list.splice(to, 0, _list.splice(from, 1)[0]);
moveItems: function(arg) {
var from, list, to;
list = arg.list, to = arg.to, from = arg.from;
_tasks[_list[from]].sort = _tasks[_list[to]].sort;
return _list = list;
},
removeItem: function(arg) {
var index;

View File

@ -2,7 +2,8 @@ EventEmitter = require('events').EventEmitter
assign = require 'object-assign'
Dispatcher = require '../dispatcher/Dispatcher.coffee'
_list = [
_tasks =
"0v0":
id:"0v0"
version:0
sort:0
@ -22,7 +23,8 @@ _list = [
body:"Seems like a great idea."
}
]
,
"0v1":
id:"0v1"
version:0
sort:1
@ -36,7 +38,8 @@ _list = [
title:'eat'
description:'dont forget about lunch.'
discussion:[]
,
"0v2":
id:"0v2"
version:0
sort:2
@ -50,7 +53,8 @@ _list = [
title:'sleep'
description:'go get some sleep.'
discussion:[]
]
_list = ["0v0","0v1","0v2"]
_listening = []
_filters =
done:null
@ -70,17 +74,16 @@ WorkStore = assign {},EventEmitter.prototype,{
removeChangeListener: (cb) -> @removeListener "change", cb
getData: ({sort,tasks})->
_tasks = _.clone tasks
for {id},i in _list when got = _tasks[id]
delete _tasks[id]
_list[i] = @itemFromData got,i
sort.map (k,index)=>
if _tasks[k]
@newItem {item:_tasks[k],index}
sort.map (id,index)=>
unless _tasks[id]
_list.splice index, 0, id
if tasks[id] # XX client-side defaults
_tasks[id] = @itemFromData tasks[id], index
getList: (key) ->
list = []
for k,v of _list
for id in _list
task = _tasks[id]
add = true
for _k,_v of _filters
if _v is null then continue
@ -94,7 +97,7 @@ WorkStore = assign {},EventEmitter.prototype,{
else
if c isnt _v then add = false
if add is true
list.push v
list.push task
if _.uniq(_.values(_sorts)).length > 0
for k,v of _sorts
if v isnt 0
@ -104,18 +107,21 @@ WorkStore = assign {},EventEmitter.prototype,{
list
getListening: -> _listening
getFilters: -> _filters
setFilter: ({key,val}) -> _filters[key] = val
getSorts: -> _sorts
setSort: ({key,val}) ->
for k,v of _sorts
_sorts[k] = 0
_sorts[key] = val
canSort: ->
for k,v of _sorts
if k is "sort" and v is 1
return true
else if v isnt 0
return false
true
itemFromData: (item,index=0)->
_item = _.extend {sort:index}, item
@ -126,10 +132,11 @@ WorkStore = assign {},EventEmitter.prototype,{
_item.discussion = item.discussion.map ({ship,body,date}) ->
{ship,body,date: new Date date}
_item
newItem: ({item,index}) -> _list.splice index,0,@itemFromData item,index
swapItem: ({to,from}) -> _list.splice to,0,_list.splice(from,1)[0]
removeItem: ({index}) -> _list.splice index,1
moveItems: ({list,to,from}) ->
_tasks[_list[from]].sort = _tasks[_list[to]].sort
_list = list
removeItem: ({index}) -> _list.splice index,1
}

View File

@ -83,6 +83,7 @@
++ duty ::
$% [%create tax=task] :: create new task
[%claim id=@uvH] :: claim task
[%archive id=@uvH] :: archive task
$: %update :: operate on task
id=@uvH :: which task
version=@u :: version

View File

@ -6,8 +6,9 @@
==
++ client-task
$: claiming=_|
archived=_|
audience=(set station:talk)
task=task
tax=task
==
++ task
$: id=@uvH
@ -33,6 +34,7 @@
$% [%new audience=(set station:talk) task]
[%old id=@uvH version=@u dif=update]
[%sort p=(list ,@uvH)]
[%audience id=@uvH to=(set station:talk)]
==
++ update
$% $: %set
@ -41,7 +43,6 @@
[%description p=@t]
[%tags p=(set ,@t)]
[%done p=?]
[%audience p=(set station:talk)]
== ==
$: %add
$% [%comment @t]