Commit 7d1906ab authored by Thomas van Noort's avatar Thomas van Noort

*** empty log message ***


git-svn-id: https://svn.cs.ru.nl/repos/iTask-system/trunk@166 63da3aa8-80fd-4f01-9db8-e6ea747a3da2
parent fac33850
definition module iTasks
// iTasks library for defining interactive multi-user workflow tasks (iTask) for the web.
// Defined on top of the iData library.
// (c) iTask & iData Concept and Implementation by Rinus Plasmeijer, 2006,2007,2008 - MJP
// This library is still under construction - MJP
iTaskVersion :== "0.99 - April 2008 - "
import iDataSettings, iDataButtons, StdBimap
derive gForm Void, Wid, TCl
derive gUpd Void, Wid, TCl
derive gPrint Void, Wid, TCl
derive gParse Void, Wid, TCl
derive gerda Void, Wid
derive read Void, Wid, TCl
derive write Void, Wid, TCl
// iTask types
:: Task a :== *TSt -> *(!a,!*TSt) // an iTask is state stransition
:: LabeledTask a :== !(!TaskLabel,!Task a) // a Task with a label used for labeling buttons, pull down menu, and the like
:: TCl a = TCl !.(Task a) // task closure, container for a task used for higher order tasks (task which deliver a task)
:: *TSt // TSt is abstract task state
:: TaskLabel :== !String // label name
:: UserId :== !Int // a user id of an iTask user must be a unique integer value
// iTask workflow processes types
:: Wid a // reference to a workflow process
:: WorkflowStatus = WflActive // iTask workflow process is still being processed
| WflSuspended // it is (temporally) suspended
| WflFinished // it is finshed
| WflDeleted // it does not exist anymore because it is deleted
instance == WorkflowStatus
// general types
:: HtmlCode :== ![BodyTag] // most programmers will only write bodytags
:: Void = Void // for tasks returning non interesting results, won't show up in editors either
// *********************************************************************************************************************************
// Setting global options for any collection of iTask workflows:
class (<<@) infixl 3 b :: !(Task a) !b -> Task a
class (@>>) infixl 7 b :: !b !(Task a) -> Task a | iData a
instance <<@ Lifespan // default: Session
, StorageFormat // default: PlainString
, Mode // default: Edit
, GarbageCollect // default: Collect
instance @>> SubPage // default: the *whole* page will be updated when a form has been modified
// Lifespan, StorageFormat, Mode are already defined in iTask library
:: GarbageCollect = Collect // garbage collect iTask administration
| NoCollect // no garbage collection
:: SubPage = UseAjax // use Ajax technology to update part of a page, only works if Ajax enabled
| OnClient // use SAPL to update part of a page on the client, only works if Client enabled and Sapl is running...
// *********************************************************************************************************************************
/* Initiate the iTask library with an iData server wrapper such as doHtmlServer in combination with one of the following functions:
singleUserTask :: iTask start function for defining tasks for one, single user
multiUserTask :: iTask start function for multi-users, with option in window to switch between [0..users - 1]
workFlowTask :: iTask start function for a real workflow
- the first arument has to be an itask which is used for login purposes; it should yield
Bool: True, is the user a new one: if so the second argument is spawned as a separate task for that user
UserId: the id of that user
- the second argument is workflow that will spawned as a task
(True if we have new user,user id of the user, has ) :
- the second one is the actual function for that user
a predefined login task is defined in iTaskLogin.dcl
*/
singleUserTask :: ![StartUpOptions] !(Task a) !*HSt -> (!Bool,Html,*HSt) | iData a
multiUserTask :: ![StartUpOptions] !(Task a) !*HSt -> (!Bool,Html,*HSt) | iData a
workFlowTask :: ![StartUpOptions] !(Task ((Bool,UserId),a))
!(UserId a -> LabeledTask b) !*HSt -> (!Bool,Html,*HSt) | iData b
:: StartUpOptions = TraceOn | TraceOff // for single & multiUser: default = TraceOn
| ThreadStorage Lifespan // for Ajax: where to store threadinformation: default = TxtFile
| ShowUsers Int // for multiUserTask, toggle between given maximum number of users, default: ShowUser 5
| VersionCheck | NoVersionCheck // for single & multiUser: default = VersionNoCheck
| TestModeOn | TestModeOff // emties storages when starting from scratch: On for single and multi-user tasks
| MyHeader HtmlCode // wil replace standard iTask information line
// *********************************************************************************************************************************
/* iTask Workflow process management:
spawnWorkflow :: spawn an iTask workflow as a new separate process, Wid is a handle to that process, bool indicates whether it is active or suspended
waitForWorkflow :: wait until the indicated process is finished and obtain the resulting value; returns Nothing when process is deleted
getWorkflowStatus :: get status of workflow
deleteWorkflow :: delete iTask workflow; returns False if workflow does not exist anymore
suspendWorkflow :: suspend iTask workflow, all corresponding tasks will vanish temporally; returns False if workflow does not exist anymore
activateWorkflow :: activate the iTask workflow again; returns False if workflow does not exist anymore
suspendMe :: suspend current workflow process; no effect on start task
deleteMe :: delete current workflow process; no effect on start task
changeWorkflowUser :: transfer the workflow task to the indicated user; returns False if workflow does not exist anymore
*/
spawnWorkflow :: !UserId !Bool !(LabeledTask a) -> Task (Wid a) | iData a
waitForWorkflow :: !(Wid a) -> Task (Maybe a ) | iData a
getWorkflowStatus :: !(Wid a) -> Task WorkflowStatus
activateWorkflow :: !(Wid a) -> Task Bool
suspendWorkflow :: !(Wid a) -> Task Bool
deleteWorkflow :: !(Wid a) -> Task Bool
changeWorkflowUser :: !UserId !(Wid a) -> Task Bool
suspendMe :: (Task Void)
deleteMe :: (Task Void)
// *********************************************************************************************************************************
/* Here follow the iTasks combinators:
Basic editors:
editTask :: create a task editor to edit a value of given type, and add a button with given name to finish the task
editTask :: create a task editor (with submit button) to edit a value of given type, finish only if predicate holds
Standard monadic combinators on iTasks:
(=>>) :: for sequencing: bind
return_V :: lift a value to the iTask domain and return it
Prompting variants:
(?>>) :: prompt as long as task is active but not finished
(!>>) :: prompt when task is activated
(<<?) :: as ?>>, except that prompt is displayed *after* task
(<<!) :: as !>>, except that prompt is displayed *after* task
Assign tasks to user with indicated id:
assignTaskTo :: assign task to indicated user, True for verbose reporting
Repetition and loops:
foreverTask :: infinitely repeating Task
(<!) :: repeat task (as a loop) as long as predicate does not hold; also works for tasks that don't require any user interactions (e.g. database access)
Sequencing Tasks:
seqTasks :: do all iTasks one after another, task completed when all done
Choose the tasks you want to do one forehand:
chooseTask_btn :: choose ONE task by pressing a button, True for horizontal buttons, else vertical
chooseTask_pdm :: as chooseTask_btn, depending on pulldownmenu item selected, Int for initial value
chooseTask_radio:: as chooseTask_btn, depending on radio item selected, Int for initial value, htmlcode for option explanation
chooseTask_cb :: choice N tasks out of N, order of chosen task depending on first arg
(initial setting, effect for all when set, explanation) for each option
Do m Tasks parallel / interleaved and FINISH as soon as SOME Task completes:
orTask2 :: do both iTasks in any order, combined task completed as any subtask is done
andTask2 :: do both iTasks in any order (interleaved), task completed when both done
andTasksCond :: do tasks in any order until pred holds for finished tasks, string used for naming group of task navigation buttons
*/
editTask :: !String !a -> Task a | iData a
editTaskPred :: !a !(a -> (Bool, HtmlCode)) -> Task a | iData a
(=>>) infixl 1 :: !(Task a) !(a -> Task b) -> Task b | iCreateAndPrint b
return_V :: !a -> Task a | iCreateAndPrint a
(?>>) infixr 5 :: !HtmlCode !(Task a) -> Task a | iCreate a
(!>>) infixr 5 :: !HtmlCode !(Task a) -> Task a | iCreate a
(<<?) infixl 5 :: !(Task a) !HtmlCode -> Task a | iCreate a
(<<!) infixl 5 :: !(Task a) !HtmlCode -> Task a | iCreate a
assignTaskTo :: !Bool !UserId !(LabeledTask a) -> Task a | iData a
foreverTask :: !(Task a) -> Task a | iData a
(<!) infixl 6 :: !(Task a) !(a -> .Bool) -> Task a | iCreateAndPrint a
seqTasks :: ![LabeledTask a] -> Task [a] | iCreateAndPrint a
chooseTask_btn :: !HtmlCode !Bool![LabeledTask a] -> Task a | iCreateAndPrint a
chooseTask_pdm :: !HtmlCode !Int ![LabeledTask a] -> Task a | iCreateAndPrint a
chooseTask_radio:: !HtmlCode !Int ![(HtmlCode,LabeledTask a)]
-> Task a | iCreateAndPrint a
:: ChoiceUpdate :== !Bool [Bool] -> [Bool] // changed checkbox + current settings -> new settings
chooseTask_cbox :: !([LabeledTask a] -> Task [a])
!HtmlCode ![((!Bool,!ChoiceUpdate,!HtmlCode),LabeledTask a)]
-> Task [a] | iData a
orTask2 :: !(Task a,Task b) -> Task (EITHER a b)
| iCreateAndPrint a & iCreateAndPrint b
andTask2 :: !(Task a,Task b) -> Task (a,b) | iCreateAndPrint a & iCreateAndPrint b
andTasksCond :: !String !([a] -> Bool) ![LabeledTask a] -> (Task [a]) | iData a
/* Time and Date management:
waitForTimeTask :: Task is done when time has come
waitForDateTask :: Task is done when date has come
*/
waitForTimeTask :: !HtmlTime -> Task HtmlTime
waitForDateTask :: !HtmlDate -> Task HtmlDate
/* Experimental department:
May not work when the tasks are garbage collected !!
-!> :: a task, either finished or interrupted (by completion of the first task) is returned in the closure
if interrupted, the work done so far is returned (!) which can be continued somewhere else
channel :: splits a task in respectively a sender task closure and receiver taskclosure;
when the sender is evaluated, the original task is evaluated as usual;
when the receiver task is evaluated, it will wait upon completeion of the sender and then get's its result;
Important: Notice that a receiver will never finish if you don't activate the corresponding receiver somewhere.
*/
(-!>) infix 4 :: (Task stop) (Task a) -> Task (Maybe stop,TCl a) | iCreateAndPrint stop & iCreateAndPrint a
channel :: String (Task a) -> Task (TCl a,TCl a) | iCreateAndPrint a
/* Exception Handling:
<^> :: Evaluate the task; An exception of type e raised by this task, will be catched by the closest handler.
One can use the function create a proper task value or signal the fact that an exception has occured.
Raise :: Raises an exception of type e which will be catched by the closest parent handler for this type
*/
(<^>) infix 1 :: !(e -> a) !(Task a) -> Task a | iData a & TC e // assigns an exception Handler
Raise :: e -> Task a | iCreate a & TC e // rases an exception
// *********************************************************************************************************************************
/* Support for user defined combinators
mkTask :: for making a user defined combinator, name will appear intrace
newTask :: same, but optimized: after completion only result will remembered
Once :: task will be done only once, the value of the task will be remembered, important for side effecting functions lifted to iData domain
*/
mkTask :: !String !(Task a) -> Task a | iCreateAndPrint a
newTask :: !String !(Task a) -> Task a | iData a
Once :: !String !(Task a) -> Task a | iData a
// *********************************************************************************************************************************
/* Lifting of other domains to the iTask domain
(*>>) :: lift functions of type (TSt -> (a,TSt)) to iTask domain
(@>>) :: lift functions of (TSt -> TSt) to iTask domain
appIData :: lift iData editors to iTask domain
appIData2 :: lift iData editors to iTask domain, and pass iDataTasknumber for naming convenience
appHStOnce :: lift HSt domain to TSt domain, will be executed only once; string used for tracing
appHSt :: lift HSt domain to TSt domain, will be executed on each invocation; string used for tracing
*/
(*=>) infix 4 :: (TSt -> (a,TSt)) (a -> Task b) -> Task b
(*#>) infix 4 :: (TSt -> TSt) (Task a) -> Task a
appIData :: (IDataFun a) -> Task a | iData a
appIData2 :: (String *HSt -> *(Form a,*HSt)) -> Task a | iData a
appHStOnce :: !String (HSt -> (a,HSt)) -> Task a | iData a
appHSt :: !String (HSt -> (a,HSt)) -> Task a | iData a
appWorldOnce :: !String (*World -> *(a,*World)) -> Task a | iData a
appWorld :: !String (*World -> *(a,*World)) -> Task a | iData a
// *********************************************************************************************************************************
/* Operations on Task state
taskId :: give id of user assigned to task
userId :: give id of application user
addHtml :: add html code
*/
taskId :: TSt -> (Int,TSt)
userId :: TSt -> (Int,TSt)
addHtml :: HtmlCode TSt -> TSt
// *********************************************************************************************************************************
This diff is collapsed.
definition module iTasks2
// (c) iTask & iData Concept and Implementation by Rinus Plasmeijer, 2006-2008 - MJP
// *********************************************************************************************************************************
// a collection of handy iTasks combinators defined in terms of the basic iTask combinators defined in module iTasks
// with Thanks to Erik Zuurbier for suggesting: (=>>?), (-&&-?), multiAndTask
// *********************************************************************************************************************************
import iTasks
/* standard monadic combinators on iTasks:
(#>>) :: for sequencing: bind, but no argument passed
return_D :: return the value and show it in iData display format
return_VF :: return the value and show the Html code specified
*/
(#>>) infixl 1 :: !(Task a) !(Task b) -> Task b | iCreateAndPrint b
return_D :: !a -> Task a | gForm {|*|}, iCreateAndPrint a
return_VF :: !HtmlCode !a -> Task a | iCreateAndPrint a
/* Assign tasks to user with indicated id:
(@:) :: will prompt who is waiting for task with give name
(@::) :: as @:, a default task name is chosen as label
(@:>) :: as @:, no prompting
(@::>) :: as @::, no prompting
*/
(@:) infix 3 :: !UserId !(LabeledTask a) -> Task a | iData a
(@::) infix 3 :: !UserId !(Task a) -> Task a | iData a
(@:>) infix 3 :: !UserId !(LabeledTask a) -> Task a | iData a
(@::>) infix 3 :: !UserId !(Task a) -> Task a | iData a
/* Handling recursion and loops:
repeatTask :: repeat Task until predicate is valid
(<|) :: repeat task (recursively) as long as predicate does not hold, and give error message otherwise
*/
repeatTask :: !(a -> Task a) !(a -> Bool) a -> Task a | iData a
(<|) infixl 6 :: !(Task a) !(a -> (Bool, HtmlCode)) -> Task a | iData a
/* Choose out the tasks you want to do one forehand, labels are used to make the choice:
button :: return value when button pressed
buttonTask :: do the iTask when button pressed
chooseTask :: Choose ONE iTask from list, depending on button pressed, button horizontal displayed
chooseTaskV :: as chooseTask, buttons vertical displayed
mchoiceTask :: Checked tasks will be done SEQUENTIALLY
mchoiceTask2 :: as mchoiceTask, boolean used for initial setting of the checks
mchoiceTask3 :: as mchoiceTask2, function can be used to (re)set the checkboxes
mchoiceTask :: Checked tasks can be done in INTERLEAVED
mchoiceTask2 :: as mchoiceTask, boolean used for initial setting of the checks
mchoiceTask3 :: as mchoiceTask2, function can be used to (re)set the checkboxes
*/
button :: !String !a -> Task a | iCreateAndPrint a
buttonTask :: !String !(Task a) -> Task a | iCreateAndPrint a
chooseTask :: !HtmlCode ![LabeledTask a] -> Task a | iCreateAndPrint a
chooseTaskV :: !HtmlCode ![LabeledTask a] -> Task a | iCreateAndPrint a
mchoiceTasks :: !HtmlCode ![LabeledTask a] -> Task [a] | iData a
mchoiceTasks2 :: !HtmlCode ![(!Bool,LabeledTask a)] -> Task [a] | iData a
mchoiceTasks3 :: !HtmlCode ![((!Bool,!ChoiceUpdate,!HtmlCode),LabeledTask a)]
-> Task [a] | iData a
mchoiceAndTasks :: !HtmlCode ![LabeledTask a] -> Task [a] | iData a
mchoiceAndTasks2:: !HtmlCode ![(!Bool,LabeledTask a)] -> Task [a] | iData a
mchoiceAndTasks3 :: !HtmlCode ![((!Bool,!ChoiceUpdate,!HtmlCode),LabeledTask a)]
-> Task [a] | iData a
/* Do m Tasks parallel / interleaved and FINISH as soon as SOME Task completes:
(-||-) :: do both iTasks in any order, combined task completed as soon as any subtask is done
(-&&-) :: do both iTasks in any order (interleaved), task completed when both done
orTasks :: do all iTasks in any order (interleaved), task completed as soon as any subtask is done
andTasks :: do all iTasks in any order (interleaved), task completed when all done
andTasks_mu :: assign task to indicated users, task completed when all done
*/
(-||-) infixr 3 :: !(Task a) !(Task a) -> Task a | iData a
(-&&-) infixr 4 :: !(Task a) !(Task b) -> Task (a,b) | iData a & iData b
orTasks :: ![LabeledTask a] -> (Task a) | iData a
andTasks :: ![LabeledTask a] -> Task [a] | iData a
andTasks_mu :: !String ![(Int,Task a)] -> Task [a] | iData a
/* convenient combinators for tasks that maybe return a result:
(=>>?) :: as bind, but do the second task only if the first one delivers a result
(-&&-?) :: do both tasks in any order, task completed when all done, or one of them delivers nothing
*/
(=>>?) infixl 1 :: !(Task (Maybe a)) !(a -> Task (Maybe b)) -> Task (Maybe b) | iCreateAndPrint a & iCreateAndPrint b
(-&&-?)infixr 4 :: !(Task (Maybe a)) !(Task (Maybe b)) -> Task (Maybe (a,b)) | iData a & iData b
/* Time and Date management:
waitForTimerTask:: Task is done when specified amount of time has passed
*/
waitForTimerTask:: !HtmlTime -> Task HtmlTime
implementation module iTasks2
// (c) iTask & iData Concept and Implementation by Rinus Plasmeijer, 2006-2008 - MJP
// Definition of non-primitive iTask combinators defined in terms of primitive iTask combinators
import StdEnv
import iTasks
import iDataTrivial
derive gForm []
derive gUpd []
derive gUpd Maybe
derive gForm Maybe
derive gPrint Maybe
derive gParse Maybe
// ******************************************************************************************************
// monads for combining iTasks
(#>>) infixl 1 :: !(Task a) !(Task b) -> Task b | iCreateAndPrint b
(#>>) taska taskb
= taska
=>> \_ -> taskb
(=>>?) infixl 1 :: !(Task (Maybe a)) !(a -> Task (Maybe b)) -> Task (Maybe b) | iCreateAndPrint a & iCreateAndPrint b
(=>>?) t1 t2
= t1
=>> \r1 -> case r1 of
Nothing -> return_V Nothing
Just r`1 -> t2 r`1
return_VF :: !HtmlCode !a -> (Task a) | iCreateAndPrint a
return_VF bodytag a = return_V a <<! bodytag
return_D :: !a -> (Task a) | gForm {|*|}, iCreateAndPrint a
return_D a = return_V a <<! [toHtml a ]
// ******************************************************************************************************
// repetition
repeatTask :: !(a -> Task a) !(a -> Bool) a -> Task a | iData a
repeatTask task pred a = dorepeatTask a
where
dorepeatTask a
= newTask "doReapeatTask" dorepeatTask`
where
dorepeatTask` tst
| pred a = (a,tst)
# (na,tst) = task a tst
= dorepeatTask na tst
(<|) infixl 6 :: !(Task a) !(a -> (Bool, HtmlCode)) -> Task a | iData a
(<|) taska pred = mkTask "repeatTest" doTask
where
doTask
= taska
=>> \r -> case pred r of
(True,_) -> return_V r
(False,msg) -> msg ?>> doTask
// ******************************************************************************************************
// Assigning tasks to users, each user has to be identified by an unique number >= 0
(@:) infix 3 :: !UserId !(LabeledTask a) -> Task a | iData a
(@:) nuserId ltask = assignTaskTo True nuserId ltask
(@::) infix 3 :: !UserId !(Task a) -> (Task a) | iData a
(@::) nuserId taska = assignTaskTo True nuserId ("Task for " <+++ nuserId,taska)
(@:>) infix 3 :: !UserId !(LabeledTask a) -> Task a | iData a
(@:>) nuserId ltask = assignTaskTo False nuserId ltask
(@::>) infix 3 :: !UserId !(Task a) -> (Task a) | iData a
(@::>) nuserId taska = assignTaskTo False nuserId ("Task for " <+++ nuserId,taska)
// ******************************************************************************************************
// choose one or more tasks on forehand out of a set
button :: !String !a -> (Task a) | iCreateAndPrint a
button s a = mkTask "button" (chooseTask_btn [] True [(s,return_V a)])
buttonTask :: !String !(Task a) -> (Task a) | iCreateAndPrint a
buttonTask s task = mkTask "buttonTask" (chooseTask_btn [] True [(s,task)])
chooseTask :: !HtmlCode ![LabeledTask a] -> (Task a) | iCreateAndPrint a
chooseTask prompt options = mkTask "chooseTask" (chooseTask_btn prompt True options)
chooseTaskV :: !HtmlCode ![LabeledTask a] -> (Task a) | iCreateAndPrint a
chooseTaskV prompt options = mkTask "chooseTask" (chooseTask_btn prompt False options)
mchoiceTasks :: !HtmlCode ![LabeledTask a] -> (Task [a]) | iData a
mchoiceTasks prompt taskOptions
= chooseTask_cbox seqTasks prompt [((False,\b bs -> bs,[]),labeltask) \\ labeltask <- taskOptions]
mchoiceTasks2 :: !HtmlCode ![(!Bool,LabeledTask a)] -> Task [a] | iData a
mchoiceTasks2 prompt taskOptions
= chooseTask_cbox seqTasks prompt [((set,\b bs -> bs,[]),labeltask) \\ (set,labeltask) <- taskOptions]
mchoiceTasks3 :: !HtmlCode ![((!Bool,!ChoiceUpdate,!HtmlCode),LabeledTask a)] -> Task [a] | iData a
mchoiceTasks3 prompt taskOptions
= chooseTask_cbox seqTasks prompt taskOptions
mchoiceAndTasks :: !HtmlCode ![LabeledTask a] -> (Task [a]) | iData a
mchoiceAndTasks prompt taskOptions
= chooseTask_cbox andTasks prompt [((False,\b bs -> bs,[]),labeltask) \\ labeltask <- taskOptions]
mchoiceAndTasks2 :: !HtmlCode ![(!Bool,LabeledTask a)] -> Task [a] | iData a
mchoiceAndTasks2 prompt taskOptions
= chooseTask_cbox andTasks prompt [((set,\b bs -> bs,[]),labeltask) \\ (set,labeltask) <- taskOptions]
mchoiceAndTasks3 :: !HtmlCode ![((!Bool,!ChoiceUpdate,!HtmlCode),LabeledTask a)] -> Task [a] | iData a
mchoiceAndTasks3 prompt taskOptions
= chooseTask_cbox andTasks prompt taskOptions
// ******************************************************************************************************
// Speculative OR-tasks: task ends as soon as one of its subtasks completes
(-||-) infixr 3 :: !(Task a) !(Task a) -> (Task a) | iData a
(-||-) taska taskb = newTask "-||-" (doOrTask (taska,taskb))
where
doOrTask :: !(Task a,Task a) -> (Task a) | iCreateAndPrint a
doOrTask (taska,taskb)
= orTask2 (taska,taskb)
=>> \at -> case at of
(LEFT a) -> return_V a
(RIGHT b) -> return_V b
(-&&-) infixr 4 :: !(Task a) !(Task b) -> (Task (a,b)) | iData a & iData b
(-&&-) taska taskb = newTask "-&&-" (andTask2 (taska,taskb))
orTasks :: ![LabeledTask a] -> (Task a) | iData a
orTasks [] = return createDefault
orTasks taskCollection = newTask "orTasks" (andTasksCond "or Tasks" (\list -> length list >= 1) taskCollection)
=>> \list -> return (hd list)
andTasks :: ![LabeledTask a] -> (Task [a]) | iData a
andTasks taskCollection = newTask "andTasks" (andTasksCond "and Tasks" (\_ -> False) taskCollection)
(-&&-?) infixr 4 :: !(Task (Maybe a)) !(Task (Maybe b)) -> Task (Maybe (a,b)) | iData a & iData b
(-&&-?) t1 t2
= andTasksCond "Maybe Task" noNothing [("Maybe 1",left),("Maybe 2",right)]
=>> combineResult
where
left = t1 =>> \tres -> return_V (LEFT tres)
right = t2 =>> \tres -> return_V (RIGHT tres)
combineResult [LEFT (Just r1),RIGHT (Just r2)] = return_V (Just (r1,r2))
combineResult _ = return_V Nothing
noNothing [] = False
noNothing [LEFT Nothing:xs] = True
noNothing [RIGHT Nothing:xs] = True
noNothing [x:xs] = noNothing xs
andTasks_mu :: !String ![(Int,Task a)] -> (Task [a]) | iData a
andTasks_mu label tasks = newTask "andTasks_mu" (domu_andTasks tasks)
where
domu_andTasks list = andTasks [(label <+++ " " <+++ i, i @:: task) \\ (i,task) <- list]
// ******************************************************************************************************
// Timer Tasks ending when timed out
waitForTimerTask:: !HtmlTime -> (Task HtmlTime)
waitForTimerTask time = waitForTimerTask`
where
waitForTimerTask`
= appHStOnce "getTimeAndDate" getTimeAndDate
=>> \(ctime,_) -> waitForTimeTask (ctime + time)
......@@ -159,7 +159,7 @@ where
andTasks_mu :: !String ![(Int,Task a)] -> (Task [a]) | iData a
andTasks_mu label tasks = newTask "andTasks_mu" (domu_andTasks tasks)
where
domu_andTasks list = andTasks [(label <+++ " " <+++ i, i @:: task) \\ (i,task) <- list]
domu_andTasks list = andTasks [(label <+++ " " <+++ i, i @::> task) \\ (i,task) <- list]
// ******************************************************************************************************
// Timer Tasks ending when timed out
......
......@@ -67,7 +67,7 @@ mkTaskButtons :: !Bool !String !Int !TaskNr !Options ![String] !*HSt -> (!(!Int,
mkTaskButtons vertical myid userId tasknr info btnnames hst
# btnsId = iTaskId userId tasknr (myid <+++ "genBtns")
# myidx = length btnnames
//| myidx == 1 = ((0,[],[]),hst) // no task button if there is only one task to choose from
| myidx == 1 = ((0,[],[]),hst) // no task button if there is only one task to choose from
# (chosen,hst) = SelectStore (myid,myidx) tasknr info id hst // which choice was made in the past
# (buttons,hst) = SelectButtons Init btnsId info (chosen,btnnames) hst // create buttons
# (chosen,hst) = SelectStore (myid,myidx) tasknr info buttons.value hst // maybe a new button was pressed
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment