diff --git a/Client/app/controller/Controller.js b/Client/app/controller/Controller.js index 75c33a3ab324fa21b7c0694e0897a806307feb93..e1e908d525cf05ec9a6ded0c6004d3808264e5bd 100644 --- a/Client/app/controller/Controller.js +++ b/Client/app/controller/Controller.js @@ -82,12 +82,14 @@ Ext.define('itwc.controller.Controller',{ onAction: function(taskId, actionId) { console.log("Action event", taskId, actionId); var me = this, - params = {commitEvent: Ext.encode([taskId,actionId])}; + params = {actionEvent: Ext.encode([taskId,actionId])}; me.sendMessage(params); //TEMPORARILY DUMB WITHOUT QUEUE AND TRACKING }, //iTasks focus events onFocus: function(taskId) { - console.log("Focus event", taskId); + var me = this, + params = {focusEvent: Ext.encode(taskId)}; + me.sendMessage(params); }, //Send a message to the server sendMessage: function(msg) { diff --git a/Server/API/Core/CoreCombinators.icl b/Server/API/Core/CoreCombinators.icl index c5250e35b0f0ee2327268052cad759586bc17288..84e2782668c8da274c5d615449ec4d51ff851602 100644 --- a/Server/API/Core/CoreCombinators.icl +++ b/Server/API/Core/CoreCombinators.icl @@ -23,7 +23,7 @@ getNextTaskId iworld=:{currentInstance,nextTaskNo} = (TaskId currentInstance nex transform :: ((TaskValue a) -> TaskValue b) !(Task a) -> Task b | iTask a & iTask b transform f (Task evala) = Task eval where - eval eEvent cEvent refresh repOpts tree iworld = case evala eEvent cEvent refresh repOpts tree iworld of + eval event repOpts tree iworld = case evala event repOpts tree iworld of (ValueResult val lastEvent rep tree,iworld) = (ValueResult (f val) lastEvent rep tree, iworld) //TODO: guarantee stability (ExceptionResult e str, iworld) = (ExceptionResult e str, iworld) (DestroyedResult, iworld) = (DestroyedResult, iworld) @@ -31,15 +31,15 @@ where project :: ((TaskValue a) r -> Maybe w) (ReadWriteShared r w) !(Task a) -> Task a | iTask a project projection share (Task evala) = Task eval where - eval eEvent cEvent refresh repOpts (TCDestroy (TCProject taskId encprev treea)) iworld //Cleanup duty simply passed to inner task - = evala eEvent cEvent refresh repOpts (TCDestroy treea) iworld + eval event repOpts (TCDestroy (TCProject taskId encprev treea)) iworld //Cleanup duty simply passed to inner task + = evala event repOpts (TCDestroy treea) iworld - eval eEvent cEvent refresh repOpts state iworld + eval event repOpts state iworld # (taskId,prev,statea) = case state of (TCInit taskId _) = (taskId,NoValue,state) (TCProject taskId encprev statea) = (taskId,fromJust (fromJSON encprev),statea) - # (resa, iworld) = evala eEvent cEvent refresh repOpts statea iworld + # (resa, iworld) = evala event repOpts statea iworld = case resa of ValueResult val ts rep ncxta # result = ValueResult val ts rep (TCProject taskId (toJSON val) ncxta) @@ -65,17 +65,17 @@ where step :: !(Task a) [TaskStep a b] -> Task b | iTask a & iTask b step (Task evala) conts = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId ts) iworld + eval event repOpts (TCInit taskId ts) iworld # (taskIda,iworld) = getNextTaskId iworld - = eval eEvent cEvent refresh repOpts (TCStep taskId (Left (TCInit taskIda ts))) iworld + = eval event repOpts (TCStep taskId (Left (TCInit taskIda ts))) iworld //Eval left-hand side - eval eEvent cEvent refresh repOpts (TCStep taskId (Left treea)) iworld=:{taskTime} - # (resa, iworld) = evala eEvent cEvent refresh {repOpts & appFinalLayout = False} treea iworld - # mbcommit = case cEvent of - (Just (TaskEvent t action)) - | t == taskId && not refresh = Just action - _ = Nothing + eval event repOpts (TCStep taskId (Left treea)) iworld=:{taskTime} + # (resa, iworld) = evala event {repOpts & appFinalLayout = False} treea iworld + # mbcommit = case event of + (ActionEvent t action) + | t == taskId = Just action + _ = Nothing # mbCont = case resa of ValueResult val lastEvent rep ntreea = case searchContValue val mbcommit conts of Nothing = Left (ValueResult NoValue lastEvent (doStepLayout taskId repOpts rep (Just val)) (TCStep taskId (Left ntreea)) ) @@ -89,17 +89,17 @@ where //Cleanup state of left-hand side # iworld = case mbTreeA of Nothing = iworld - Just treea = snd (evala Nothing Nothing refresh {repOpts & appFinalLayout = False} (TCDestroy treea) iworld) //TODO: Check for exceptions during cleanup + Just treea = snd (evala RefreshEvent {repOpts & appFinalLayout = False} (TCDestroy treea) iworld) //TODO: Check for exceptions during cleanup # (taskIdb,iworld) = getNextTaskId iworld - # (resb,iworld) = evalb Nothing Nothing refresh {repOpts & appFinalLayout = False} (TCInit taskIdb taskTime) iworld + # (resb,iworld) = evalb RefreshEvent {repOpts & appFinalLayout = False} (TCInit taskIdb taskTime) iworld = case resb of ValueResult val lastEvent rep nstateb = (ValueResult val lastEvent (doStepLayout taskId repOpts rep Nothing) (TCStep taskId (Right (d_json_a,sel,nstateb))),iworld) ExceptionResult e str = (ExceptionResult e str, iworld) //Eval right-hand side - eval eEvent cEvent refresh repOpts (TCStep taskId (Right (enca,sel,treeb))) iworld + eval event repOpts (TCStep taskId (Right (enca,sel,treeb))) iworld = case restoreTaskB sel enca of Just (Task evalb) - # (resb, iworld) = evalb eEvent cEvent refresh {repOpts & appFinalLayout = False} treeb iworld + # (resb, iworld) = evalb event {repOpts & appFinalLayout = False} treeb iworld = case resb of ValueResult val lastEvent rep ntreeb = (ValueResult val lastEvent (doStepLayout taskId repOpts rep Nothing) (TCStep taskId (Right (enca,sel,ntreeb))), iworld) ExceptionResult e str = (ExceptionResult e str, iworld) @@ -107,19 +107,19 @@ where = (exception "Corrupt task value in step", iworld) //Cleanup - eval eEvent cEvent refresh repOpts (TCDestroy (TCStep taskId (Left treea))) iworld - = case evala eEvent cEvent refresh repOpts (TCDestroy treea) iworld of + eval event repOpts (TCDestroy (TCStep taskId (Left treea))) iworld + = case evala event repOpts (TCDestroy treea) iworld of (DestroyedResult,iworld) = (DestroyedResult,iworld) (ExceptionResult e str,iworld) = (ExceptionResult e str,iworld) (ValueResult _ _ _ _,iworld) = (exception "Destroy failed in step",iworld) - eval eEvent cEvent refresh repOpts (TCDestroy (TCStep taskId (Right(enca,sel,treeb)))) iworld + eval event repOpts (TCDestroy (TCStep taskId (Right(enca,sel,treeb)))) iworld = case restoreTaskB sel enca of - Just (Task evalb) = evalb eEvent cEvent refresh repOpts (TCDestroy treeb) iworld + Just (Task evalb) = evalb event repOpts (TCDestroy treeb) iworld Nothing = (exception "Corrupt task value in step", iworld) //Incorred state - eval eEvent cEvent refresh _ state iworld + eval event _ state iworld = (exception ("Corrupt task state in step:" +++ (toString (toJSON state))), iworld) searchContValue val mbcommit conts = search val mbcommit 0 Nothing conts @@ -180,25 +180,18 @@ parallel :: !d ![(!ParallelTaskType,!ParallelTask a)] -> Task [(!TaskTime,!TaskV parallel desc initTasks = Task eval where //Create initial task list - eval eEvent cEvent refresh repOpts (TCInit taskId ts) iworld=:{IWorld|localLists} + eval event repOpts (TCInit taskId ts) iworld=:{IWorld|localLists} //Append the initial tasks to the list # iworld = foldl append {iworld & localLists = 'Map'.put taskId [] localLists} initTasks //Evaluate the parallel - = eval eEvent cEvent refresh repOpts (TCParallel taskId) iworld + = eval event repOpts (TCParallel taskId) iworld where append iworld t = snd (appendTaskToList taskId t iworld) //Evaluate the task list - eval eEvent cEvent refresh repOpts (TCParallel taskId) iworld=:{taskTime} - //Update the tasktime if an explicit reorder event of tabs/windows is targeted at the parallel - # iworld = case eEvent of - Just (TaskEvent t ("top",JSONString top)) - | t == taskId && not refresh = updateListEntryTime taskId (fromString top) taskTime iworld - = iworld - _ = iworld - + eval event repOpts (TCParallel taskId) iworld=:{taskTime} //Evaluate all parallel tasks in the list - = case evalParTasks taskId eEvent cEvent refresh iworld of + = case evalParTasks taskId event iworld of (Just res=:(ExceptionResult e str),_,iworld) = (res,iworld) (Just res=:(ValueResult _ _ _ _),_,iworld) = (exception "parallel evaluation yielded unexpected result",iworld) (Nothing,entries,iworld) @@ -215,21 +208,21 @@ where # ts = foldr max 0 (map fst values) = (ValueResult (Value values stable) ts (finalizeRep repOpts rep) (TCParallel taskId),{iworld & localLists = 'Map'.put taskId (map fst entries) localLists}) //Cleanup - eval eEvent cEvent refresh repOpts (TCDestroy (TCParallel taskId)) iworld=:{localLists} + eval event repOpts (TCDestroy (TCParallel taskId)) iworld=:{localLists} # entries = fromMaybe [] ('Map'.get taskId localLists) = case foldl destroyParTask (Nothing,iworld) entries of (Nothing,iworld) = (DestroyedResult,{iworld & localLists = 'Map'.del taskId localLists}) //All destroyed (Just (ExceptionResult e str),iworld) = (ExceptionResult e str,{iworld & localLists = 'Map'.del taskId localLists}) //An exception occurred (Just result,iworld) = (fixOverloading result initTasks (exception "Destroy failed in step"),iworld) //Fallback - eval _ _ _ _ _ iworld + eval _ _ _ iworld = (exception "Corrupt task state in parallel", iworld) - evalParTasks :: !TaskId !(Maybe EditEvent) !(Maybe CommitEvent) !RefreshFlag !*IWorld -> (!Maybe (TaskResult [(TaskTime,TaskValue a)]),![(!TaskListEntry,!Maybe TaskRep)],!*IWorld) | iTask a - evalParTasks taskId eEvent cEvent refresh iworld=:{localLists} + evalParTasks :: !TaskId !Event !*IWorld -> (!Maybe (TaskResult [(TaskTime,TaskValue a)]),![(!TaskListEntry,!Maybe TaskRep)],!*IWorld) | iTask a + evalParTasks taskId event iworld=:{localLists} = evalFrom 0 [] (fromMaybe [] ('Map'.get taskId localLists)) iworld where - evalFrom n acc list iworld = case foldl (evalParTask taskId eEvent cEvent refresh) (Nothing,acc,iworld) (drop n list) of + evalFrom n acc list iworld = case foldl (evalParTask taskId event) (Nothing,acc,iworld) (drop n list) of (Just (ExceptionResult e str),acc,iworld) = (Just (ExceptionResult e str),acc,iworld) (Nothing,acc,iworld=:{localLists}) # nlist = fromMaybe [] ('Map'.get taskId localLists) @@ -238,10 +231,10 @@ where //IMPORTANT: This last rule should never match, but it helps to solve overloading solves overloading (Just (ValueResult val ts rep tree),acc,iworld) = (Just (ValueResult (Value [(ts,val)] Unstable) ts rep tree),acc,iworld) - evalParTask :: !TaskId !(Maybe EditEvent) !(Maybe CommitEvent) !RefreshFlag !(!Maybe (TaskResult a),![(!TaskListEntry,!Maybe TaskRep)],!*IWorld) !TaskListEntry -> (!Maybe (TaskResult a),![(!TaskListEntry,!Maybe TaskRep)],!*IWorld) | iTask a + evalParTask :: !TaskId !Event !(!Maybe (TaskResult a),![(!TaskListEntry,!Maybe TaskRep)],!*IWorld) !TaskListEntry -> (!Maybe (TaskResult a),![(!TaskListEntry,!Maybe TaskRep)],!*IWorld) | iTask a //Evaluate embedded tasks - evalParTask taskId eEvent cEvent refresh (Nothing,acc,iworld) {TaskListEntry|entryId,state=EmbeddedState (Task evala :: Task a^) tree, removed=False} - # (result,iworld) = evala eEvent cEvent refresh {TaskRepOpts|useLayout=Nothing,modLayout=Nothing,appFinalLayout=False} tree iworld + evalParTask taskId event (Nothing,acc,iworld) {TaskListEntry|entryId,state=EmbeddedState (Task evala :: Task a^) tree, removed=False} + # (result,iworld) = evala event {TaskRepOpts|useLayout=Nothing,modLayout=Nothing,appFinalLayout=False} tree iworld = case result of ExceptionResult _ _ = (Just result,acc,iworld) @@ -250,7 +243,7 @@ where = (Nothing, acc++[(entry,Just rep)],iworld) //Copy the last stored result of detached tasks - evalParTask taskId eEvent cEvent refresh (Nothing,acc,iworld) {TaskListEntry|entryId,state=DetachedState instanceNo _ _,removed=False} + evalParTask taskId event (Nothing,acc,iworld) {TaskListEntry|entryId,state=DetachedState instanceNo _ _,removed=False} = case loadTaskInstance instanceNo iworld of (Error _, iworld) = (Nothing,acc,iworld) //TODO: remove from parallel if it can't be loaded (now it simply keeps the last known result) (Ok (meta,_,res), iworld) @@ -259,12 +252,12 @@ where = (Nothing,acc++[(entry,Nothing)],iworld) //Do nothing if an exeption occurred or marked as removed - evalParTask taskId eEvent cEvent refresh (result,acc,iworld) entry = (result,acc,iworld) + evalParTask taskId event (result,acc,iworld) entry = (result,acc,iworld) destroyParTask :: (!Maybe (TaskResult a),!*IWorld) !TaskListEntry -> (!Maybe (TaskResult a),!*IWorld) | iTask a //Destroy embedded tasks destroyParTask (_,iworld) {TaskListEntry|entryId,state=EmbeddedState (Task evala :: Task a^) tree} - # (result,iworld) = evala Nothing Nothing False {TaskRepOpts|useLayout=Nothing,modLayout=Nothing,appFinalLayout=False} (TCDestroy tree) iworld + # (result,iworld) = evala RefreshEvent {TaskRepOpts|useLayout=Nothing,modLayout=Nothing,appFinalLayout=False} (TCDestroy tree) iworld = case result of DestroyedResult = (Nothing,iworld) _ = (Just result,iworld) @@ -341,10 +334,6 @@ where = {TaskListEntry| e & state = DetachedState no progress management,result = result, attributes = 'Map'.fromList attributes} update e = e -updateListEntryTime :: !TaskId !TaskId !TaskTime !*IWorld -> *IWorld -updateListEntryTime listId entryId ts iworld - = snd (updateListEntry listId entryId (\e -> {TaskListEntry|e & time = ts}) iworld) - markListEntryRemoved :: !TaskId !TaskId !*IWorld -> *IWorld markListEntryRemoved listId entryId iworld = snd (updateListEntry listId entryId (\e -> {TaskListEntry|e & removed = True}) iworld) @@ -430,12 +419,12 @@ where workOn :: !TaskId -> Task WorkOnStatus workOn (TaskId instanceNo taskNo) = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId ts) iworld=:{currentInstance,currentUser} + eval event repOpts (TCInit taskId ts) iworld=:{currentInstance,currentUser} # iworld = setTaskWorker currentUser instanceNo iworld # iworld = addTaskInstanceObserver currentInstance instanceNo iworld - = eval eEvent cEvent refresh repOpts (TCBasic taskId ts JSONNull False) iworld + = eval event repOpts (TCBasic taskId ts JSONNull False) iworld - eval eEvent cEvent refresh repOpts tree=:(TCBasic taskId ts _ _) iworld=:{currentUser} + eval event repOpts tree=:(TCBasic taskId ts _ _) iworld=:{currentUser} //Load instance # (meta,iworld) = loadTaskMeta instanceNo iworld # (result,iworld) = loadTaskResult instanceNo iworld @@ -453,11 +442,10 @@ where _ = (ValueResult (Value WODeleted Stable) ts (finalizeRep repOpts noRep) tree, iworld) - eval eEvent cEvent refresh repOpts (TCDestroy (TCBasic taskId _ _ _)) iworld + eval event repOpts (TCDestroy (TCBasic taskId _ _ _)) iworld //TODO: Remove this workon from the observers = (DestroyedResult,iworld) - inUseRep worker = TaskRep {UIDef|controls=[(stringDisplay (toString worker +++ " is working on this task"),'Map'.newMap)],actions=[],attributes='Map'.newMap} [] /* @@ -468,32 +456,32 @@ where workAs :: !User !(Task a) -> Task a | iTask a workAs user (Task eval) = Task eval` where - eval` eEvent cEvent refresh repOpts state iworld=:{currentUser} - # (result,iworld) = eval eEvent cEvent refresh repOpts state {iworld & currentUser = user} + eval` event repOpts state iworld=:{currentUser} + # (result,iworld) = eval event repOpts state {iworld & currentUser = user} = (result,{iworld & currentUser = currentUser}) withShared :: !b !((Shared b) -> Task a) -> Task a | iTask a & iTask b withShared initial stask = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId ts) iworld=:{localShares} + eval event repOpts (TCInit taskId ts) iworld=:{localShares} # localShares = 'Map'.put taskId (toJSON initial) localShares # (taskIda,iworld) = getNextTaskId iworld - = eval eEvent cEvent refresh repOpts (TCShared taskId (TCInit taskIda ts)) {iworld & localShares = localShares} + = eval event repOpts (TCShared taskId (TCInit taskIda ts)) {iworld & localShares = localShares} - eval eEvent cEvent refresh repOpts (TCShared taskId treea) iworld + eval event repOpts (TCShared taskId treea) iworld # (Task evala) = stask (localShare taskId) - # (resa,iworld) = evala eEvent cEvent refresh repOpts treea iworld + # (resa,iworld) = evala event repOpts treea iworld = case resa of ValueResult NoValue lastEvent rep ntreea = (ValueResult NoValue lastEvent rep (TCShared taskId ntreea),iworld) ValueResult (Value stable val) lastEvent rep ntreea = (ValueResult (Value stable val) lastEvent rep (TCShared taskId ntreea),iworld) ExceptionResult e str = (ExceptionResult e str,iworld) - eval eEvent cEvent refresh repOpts (TCDestroy (TCShared taskId treea)) iworld //First destroy inner task, then remove shared state + eval event repOpts (TCDestroy (TCShared taskId treea)) iworld //First destroy inner task, then remove shared state # (Task evala) = stask (localShare taskId) - # (resa,iworld=:{localShares}) = evala eEvent cEvent refresh repOpts (TCDestroy treea) iworld + # (resa,iworld=:{localShares}) = evala event repOpts (TCDestroy treea) iworld = (resa,{iworld & localShares = 'Map'.del taskId localShares}) - eval _ _ _ _ _ iworld + eval _ _ _ iworld = (exception "Corrupt task state in withShared", iworld) /* * Tuning of tasks @@ -504,17 +492,17 @@ instance tune SetLayout where tune (SetLayout layout) (Task eval) = Task eval` where - eval` eEvent cEvent refresh repOpts=:{useLayout=Nothing,modLayout} state iworld - = eval eEvent cEvent refresh {TaskRepOpts|repOpts & useLayout = Just ((fromMaybe id modLayout) layout), modLayout = Nothing} state iworld - eval` eEvent cEvent refresh repOpts=:{useLayout=Just _,modLayout} state iworld - = eval eEvent cEvent refresh {TaskRepOpts|repOpts & useLayout = Just layout, modLayout = Nothing} state iworld + eval` event repOpts=:{useLayout=Nothing,modLayout} state iworld + = eval event {TaskRepOpts|repOpts & useLayout = Just ((fromMaybe id modLayout) layout), modLayout = Nothing} state iworld + eval` event repOpts=:{useLayout=Just _,modLayout} state iworld + = eval event {TaskRepOpts|repOpts & useLayout = Just layout, modLayout = Nothing} state iworld instance tune ModifyLayout where tune (ModifyLayout f) (Task eval) = Task eval` where - eval` eEvent cEvent refresh repOpts=:{modLayout=Nothing} state iworld - = eval eEvent cEvent refresh {TaskRepOpts|repOpts & modLayout = Just f} state iworld - eval` eEvent cEvent refresh repOpts=:{modLayout=Just g} state iworld - = eval eEvent cEvent refresh {TaskRepOpts|repOpts & modLayout = Just (g o f)} state iworld + eval` event repOpts=:{modLayout=Nothing} state iworld + = eval event {TaskRepOpts|repOpts & modLayout = Just f} state iworld + eval` event repOpts=:{modLayout=Just g} state iworld + = eval event {TaskRepOpts|repOpts & modLayout = Just (g o f)} state iworld \ No newline at end of file diff --git a/Server/API/Core/CoreTasks.icl b/Server/API/Core/CoreTasks.icl index 09560a13f5719e264641503f37fb43aad3bc9292..5b1cff628816230e7e41ad3755aa1d5a324b6c7b 100644 --- a/Server/API/Core/CoreTasks.icl +++ b/Server/API/Core/CoreTasks.icl @@ -53,36 +53,33 @@ where watch :: !(ReadWriteShared r w) -> Task r | iTask r watch shared = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # (val,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld # res = case val of Ok val = ValueResult (Value val Unstable) ts (finalizeRep repOpts NoRep) (TCInit taskId ts) Error e = exception (SharedException e) = (res,iworld) - eval eEvent cEvent refresh repAs (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repAs (TCDestroy _) iworld = (DestroyedResult,iworld) interactSharedChoice :: !d !(ReadOnlyShared r) (Maybe l) (r (Maybe l) -> t v l) -> Task (Maybe l) | descr d & Choice t & iTask r & iTask l & iTask (t v l) interactSharedChoice desc shared initial_mask toView = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld = case mbr of Error _ = could_not_read_shared_in_interact_exception iworld Ok r # v = toView r initial_mask # (l,v,mask) = (initial_mask,v,defaultMask v) - = eval eEvent cEvent refresh repOpts (TCInteract2 taskId ts (toJSON l) (toJSON r) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract2 taskId=:(TaskId instanceNo _) ts encl encr mask) iworld=:{taskTime} + = eval event repOpts (TCInteract2 taskId ts (toJSON l) (toJSON r) mask) iworld + eval event repOpts (TCInteract2 taskId=:(TaskId instanceNo _) ts encl encr mask) iworld=:{taskTime} //Decode stored values # l = fromJust (fromJSON encl) r = fromJust (fromJSON encr) v = toView r l //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) - = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld //Load next r from shared value # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld | isError mbr = could_not_read_shared_in_interact_exception iworld @@ -96,9 +93,9 @@ where //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract2 taskId nts (toJSON nl) (toJSON nr) nmask), iworld) - eval eEvent cEvent refresh repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) refresh_fun l nr nv valid # nl = if valid (getMbSelection nv) l @@ -109,24 +106,21 @@ interactSharedChoiceNoView :: !d !(ReadOnlyShared r) (Maybe l) (r (Maybe l) -> t -> Task (Maybe l) | descr d & ChoiceNoView t & iTask r & iTask l & iTask (t l) interactSharedChoiceNoView desc shared initial_mask toViewId = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld = case mbr of Error _ = could_not_read_shared_in_interact_exception iworld Ok r # v = toViewId r initial_mask # (l,v,mask) = (initial_mask,v,defaultMask v) - = eval eEvent cEvent refresh repOpts (TCInteract2 taskId ts (toJSON l) (toJSON r) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract2 taskId=:(TaskId instanceNo _) ts encl encr mask) iworld=:{taskTime} + = eval event repOpts (TCInteract2 taskId ts (toJSON l) (toJSON r) mask) iworld + eval event repOpts (TCInteract2 taskId=:(TaskId instanceNo _) ts encl encr mask) iworld=:{taskTime} //Decode stored values # l = fromJust( fromJSON encl) r = fromJust (fromJSON encr) v = toViewId r l //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) - = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld //Load next r from shared value # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld | isError mbr = could_not_read_shared_in_interact_exception iworld @@ -140,9 +134,9 @@ where //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract2 taskId nts (toJSON nl) (toJSON nr) nmask), iworld) - eval eEvent cEvent refresh repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) refresh_fun l nr nv valid # nl = if valid (getMbSelectionNoView nv) l @@ -152,23 +146,21 @@ where interactSharedInformation :: !d !(ReadOnlyShared r) (r -> v) -> Task r | descr d & iTask r & iTask v interactSharedInformation desc shared toView = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld = case mbr of Error _ = could_not_read_shared_in_interact_exception iworld Ok r # v = toView r # (l,v,mask) = (r,v,defaultMask v) - = eval eEvent cEvent refresh repOpts (TCInteract2 taskId ts (toJSON l) (toJSON r) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract2 taskId=:(TaskId instanceNo _) ts encl encr mask) iworld=:{taskTime} + = eval event repOpts (TCInteract2 taskId ts (toJSON l) (toJSON r) mask) iworld + eval event repOpts (TCInteract2 taskId=:(TaskId instanceNo _) ts encl encr mask) iworld=:{taskTime} //Decode stored values # l = fromJust (fromJSON encl) r = fromJust (fromJSON encr) v = toView r //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld //Load next r from shared value # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld | isError mbr = could_not_read_shared_in_interact_exception iworld @@ -180,9 +172,9 @@ where //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract2 taskId nts (toJSON nl) (toJSON nr) nmask), iworld) - eval eEvent cEvent refresh repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) refresh_fun r # v = toView r @@ -191,18 +183,16 @@ where interactNullEnter :: !d !v (v->l) -> Task l | descr d & iTask v interactNullEnter desc initFun fromf = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # v = initFun # mask = Untouched - = eval eEvent cEvent refresh repOpts (TCInteract1 taskId ts (toJSON v) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract1 taskId=:(TaskId instanceNo _) ts encv mask) iworld=:{taskTime} + = eval event repOpts (TCInteract1 taskId ts (toJSON v) mask) iworld + eval event repOpts (TCInteract1 taskId=:(TaskId instanceNo _) ts encv mask) iworld=:{taskTime} //Decode stored value # v = fromJust (fromJSON encv) l = fromf v //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld //Apply refresh function if v changed # changed = nts =!= ts # valid = isValidValue (verifyForm nv nmask) @@ -210,9 +200,9 @@ where //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract1 taskId nts (toJSON nv) nmask), iworld) - eval eEvent cEvent refresh repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) refresh_fun l v m ok | ok @@ -222,19 +212,17 @@ where interactNullUpdate :: !d !(l -> v) (l v -> l) l -> Task l | descr d & iTask l & iTask v interactNullUpdate desc tof fromf m = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # v = tof m l = m mask = defaultMask v - = eval eEvent cEvent refresh repOpts (TCInteract1 taskId ts (toJSON l) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract1 taskId=:(TaskId instanceNo _) ts encl mask) iworld=:{taskTime} + = eval event repOpts (TCInteract1 taskId ts (toJSON l) mask) iworld + eval event repOpts (TCInteract1 taskId=:(TaskId instanceNo _) ts encl mask) iworld=:{taskTime} //Decode stored values # l = fromJust (fromJSON encl) v = tof l //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld //Apply refresh function if v changed # changed = nts =!= ts # valid = isValidValue (verifyForm nv nmask) @@ -242,9 +230,9 @@ where //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract1 taskId nts (toJSON nl) nmask), iworld) - eval eEvent cEvent refresh repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) refresh_fun l v m ok | ok @@ -256,46 +244,42 @@ where interactNullView :: !d (l->v) l -> Task l | descr d & iTask l & iTask v interactNullView desc tof m = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # l = m v = Display (tof l) mask = defaultMask v - = eval eEvent cEvent refresh repOpts (TCInteract1 taskId ts (toJSON l) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract1 taskId=:(TaskId instanceNo _) ts encl mask) iworld=:{taskTime} + = eval event repOpts (TCInteract1 taskId ts (toJSON l) mask) iworld + eval event repOpts (TCInteract1 taskId=:(TaskId instanceNo _) ts encl mask) iworld=:{taskTime} //Decode stored values # l = fromJust (fromJSON encl) v = Display (tof l) //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld # nl = l //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract1 taskId nts (toJSON nl) nmask), iworld) - eval eEvent cEvent refresh repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) interact :: !d !(ReadOnlyShared r) (r -> (l,v,UpdateMask)) (l r v UpdateMask Bool -> (l,v,UpdateMask)) -> Task l | descr d & iTask l & iTask r & iTask v interact desc shared initFun refreshFun = Task eval where - eval eEvent cEvent refresh repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld + eval event repOpts (TCInit taskId=:(TaskId instanceNo _) ts) iworld # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld = case mbr of Error _ = could_not_read_shared_in_interact_exception iworld Ok r # (l,v,mask) = initFun r - = eval eEvent cEvent refresh repOpts (TCInteract taskId ts (toJSON l) (toJSON r) (toJSON v) mask) iworld + = eval event repOpts (TCInteract taskId ts (toJSON l) (toJSON r) (toJSON v) mask) iworld - eval eEvent cEvent refresh repOpts (TCInteract taskId=:(TaskId instanceNo _) ts encl encr encv mask) iworld=:{taskTime} + eval event repOpts (TCInteract taskId=:(TaskId instanceNo _) ts encl encr encv mask) iworld=:{taskTime} //Decode stored values # (l,r,v) = (fromJust (fromJSON encl), fromJust (fromJSON encr), fromJust (fromJSON encv)) //Determine next v by applying edit event if applicable - # (nv,nmask,nts,iworld) = if refresh - (v,mask,ts,iworld) - (matchAndApplyEvent eEvent taskId taskTime v mask ts iworld) + # (nv,nmask,nts,iworld) = matchAndApplyEvent event taskId taskTime v mask ts iworld //Load next r from shared value # (mbr,iworld) = 'SharedDataSource'.readRegister instanceNo shared iworld | isError mbr = could_not_read_shared_in_interact_exception iworld @@ -307,32 +291,25 @@ where //Make visualization # validity = verifyForm nv nmask # (rep,iworld) = visualizeView taskId repOpts nv validity desc iworld - # value = if (isValidValue validity) (Value nl (if (isLucky eEvent) Stable Unstable)) NoValue + # value = if (isValidValue validity) (Value nl Unstable) NoValue = (ValueResult value nts (finalizeRep repOpts rep) (TCInteract taskId nts (toJSON nl) (toJSON nr) (toJSON nv) nmask), iworld) - eval eEvent cEvent refresh repAs (TCDestroy _) iworld = (DestroyedResult,iworld) + eval event repOpts (TCDestroy _) iworld = (DestroyedResult,iworld) -isLucky (Just (LuckyEvent _ _)) = True //HACK -isLucky _ = False - -matchAndApplyEvent eEvent taskId taskTime v mask ts iworld - = applyEvent taskId taskTime v mask ts (matchEvent taskId eEvent) iworld -where - matchEvent taskId1 (Just (LuckyEvent _ e)) = Just e - matchEvent taskId1 (Just (TaskEvent taskId2 e)) | taskId1 == taskId2 = Just e - matchEvent taskId1 _ = Nothing - - applyEvent taskId taskTime v mask ts event iworld = case event of - Nothing = (v,mask,ts,iworld) - Just (dps,encev) - # dp = s2dp dps - | dataPathLevel dp == 0 - = case fromJSON encev of - Nothing = (v,mask,ts,iworld) - Just nv = (nv,defaultMask nv,taskTime,iworld) - | otherwise - # (nv,nmask,iworld) = updateValueAndMask dp encev v mask iworld - = (nv,nmask,taskTime,iworld) +matchAndApplyEvent (EditEvent taskId name value) matchId taskTime v mask ts iworld + | taskId == matchId + # dp = s2dp name + | (dataPathLevel dp == 0) = case fromJSON value of + Nothing = (v,mask,ts,iworld) + Just nv = (nv,defaultMask nv,taskTime,iworld) + | otherwise + # (nv,nmask,iworld) = updateValueAndMask dp value v mask iworld + = (nv,nmask,taskTime,iworld) + | otherwise = (v,mask,ts,iworld) +matchAndApplyEvent (FocusEvent taskId) matchId taskTime v mask ts iworld + = (v,mask, if (taskId == matchId) taskTime ts, iworld) +matchAndApplyEvent _ matchId taskTime v mask ts iworld + = (v,mask,ts,iworld) visualizeView taskId repOpts v validity desc iworld # layout = repLayout repOpts diff --git a/Server/API/Core/IntegrationTasks.icl b/Server/API/Core/IntegrationTasks.icl index 30f749f60bdb424613b8349e266cc0c510282209..23ae7a217efc53fe0e73f9c25c95bce15e8b3a82 100644 --- a/Server/API/Core/IntegrationTasks.icl +++ b/Server/API/Core/IntegrationTasks.icl @@ -42,7 +42,7 @@ callProcess :: !FilePath ![String] -> Task Int callProcess cmd args = Task eval where //Start the external process - eval eEvent cEvent refresh repAs (TCInit taskId ts) iworld=:{build,dataDirectory,sdkDirectory,world} + eval event repAs (TCInit taskId ts) iworld=:{build,dataDirectory,sdkDirectory,world} # outfile = dataDirectory "tmp-" +++ build (toString taskId +++ "-callprocess") # runAsync = sdkDirectory "Tools" "RunAsync" (IF_POSIX_OR_WINDOWS "RunAsync" "RunAsync.exe") # runAsyncArgs = [ "--taskid" @@ -56,13 +56,13 @@ where # nstate = case res of Error e = state taskId ts (Left e) Ok _ = state taskId ts (Right outfile) - = eval eEvent cEvent refresh repAs nstate {IWorld|iworld & world = world} + = eval event repAs nstate {IWorld|iworld & world = world} where state :: TaskId TaskTime (Either OSError FilePath) -> TaskTree state taskId taskTime val = TCBasic taskId taskTime (toJSON val) False //Check for its result - eval eEvent cEvent refresh repAs state=:(TCBasic taskId lastEvent encv stable) iworld=:{world} + eval event repAs state=:(TCBasic taskId lastEvent encv stable) iworld=:{world} | stable = (ValueResult (Value (fromJust (fromJSON encv)) Stable) lastEvent (TaskRep {UIDef|controls=[],actions=[],attributes='Map'.newMap} []) state, iworld) | otherwise @@ -98,7 +98,7 @@ where Nothing = (exception (CallFailed (3,"callProcess: Unknown exception")), {IWorld|iworld & world = world}) //Clean up - eval eEvent cEvent refresh repAs (TCDestroy (TCBasic taskId lastEvent encv stable)) iworld + eval event repAs (TCDestroy (TCBasic taskId lastEvent encv stable)) iworld //TODO: kill runasync for this task and clean up tmp files = (DestroyedResult,iworld) diff --git a/Server/API/Extensions/Admin/WorkflowAdmin.icl b/Server/API/Extensions/Admin/WorkflowAdmin.icl index 1ec3c0dc5a7c1fb5ea3924ef698495ea4fa009bc..7ed1716b5a628be00133e09d12c9a55b427e84ac 100644 --- a/Server/API/Extensions/Admin/WorkflowAdmin.icl +++ b/Server/API/Extensions/Admin/WorkflowAdmin.icl @@ -89,8 +89,8 @@ viewTask externalTaskInterface :: [PublishedTask] externalTaskInterface - = [publish "/external/tasklist" WebApp viewTaskList - ,publish "/external/task" WebApp viewTask + = [publish "/external/tasklist" WebApp (\_ -> viewTaskList) + ,publish "/external/task" WebApp (\_ -> viewTask) ] // MANAGEMENT TASKS diff --git a/Server/Framework/Engine.dcl b/Server/Framework/Engine.dcl index 91b4f865861b3f4dd0ac21d32e062fa87f3041c6..1dcc9f4fee1204cafb8a25081e7853c5879f4fa2 100644 --- a/Server/Framework/Engine.dcl +++ b/Server/Framework/Engine.dcl @@ -21,6 +21,8 @@ URL_PREFIX :== "" , defaultFormat :: ServiceFormat } +:: TaskWrapper = E.a: TaskWrapper (HTTPRequest -> Task a) & iTask a + //* The format in which a task is presented. :: ServiceFormat = WebApp @@ -39,13 +41,14 @@ engine :: publish -> [(!String -> Bool,!HTTPRequest *IWorld -> (!HTTPResponse, ! /** * Wraps a task together with a url to make it publishable by the engine */ -publish :: String ServiceFormat (Task a) -> PublishedTask | iTask a +publish :: String ServiceFormat (HTTPRequest -> Task a) -> PublishedTask | iTask a class Publishable a where publishAll :: !a -> [PublishedTask] instance Publishable (Task a) | iTask a +instance Publishable (HTTPRequest -> Task a) | iTask a instance Publishable [PublishedTask] /** diff --git a/Server/Framework/Engine.icl b/Server/Framework/Engine.icl index 0907dbbb3cefa84036835d0ce7862c350139f024..bee70303a92e3af0c1c7d3e521d8fd91adac76c7 100644 --- a/Server/Framework/Engine.icl +++ b/Server/Framework/Engine.icl @@ -114,13 +114,17 @@ handleStopRequest req iworld = ({newHTTPResponse & rsp_headers = fromList [("X-S path2name path = last (split "/" path) -publish :: String ServiceFormat (Task a) -> PublishedTask | iTask a +publish :: String ServiceFormat (HTTPRequest -> Task a) -> PublishedTask | iTask a publish url format task = {url = url, task = TaskWrapper task, defaultFormat = format} instance Publishable (Task a) | iTask a where - publishAll task = [publish "/" WebApp task] + publishAll task = [publish "/" WebApp (\_ -> task)] +instance Publishable (HTTPRequest -> Task a) | iTask a +where + publishAll task = [publish "/" WebApp task] + instance Publishable [PublishedTask] where publishAll list = list diff --git a/Server/Framework/Task.dcl b/Server/Framework/Task.dcl index 87d484beea05c013a5fcad2cfc4cb73f4084ff2e..0ff39fff9160680f07a06ab2288e9981e02a8b64 100644 --- a/Server/Framework/Task.dcl +++ b/Server/Framework/Task.dcl @@ -22,14 +22,13 @@ derive gGetRecordFields Task derive gPutRecordFields Task // Tasks -:: Task a = Task !((Maybe EditEvent) (Maybe CommitEvent) RefreshFlag TaskRepOpts TaskTree *IWorld -> *(!TaskResult a, !*IWorld)) +:: Task a = Task !(Event TaskRepOpts TaskTree *IWorld -> *(!TaskResult a, !*IWorld)) -:: Event e = TaskEvent !TaskId !e //Event for a task within the process we are looking for - | LuckyEvent !InstanceNo !e //Event for any task who is willing to handle it (I am feeling lucky event) - -:: EditEvent :== Event (!String,!JSONNode) //Datapath and new value -:: CommitEvent :== Event String //Action name -:: RefreshFlag :== Bool //Flag that indicates if events should not be applied +:: Event = EditEvent !TaskId !String !JSONNode //Update something in an interaction: Task id, edit name, value + | ActionEvent !TaskId !String //Progress in a step combinator: Task id, action id + | FocusEvent !TaskId //Update last event time without changing anything: Task id + | RefreshEvent //No event, just recalcalutate the entire task instance + :: TaskResult a = ValueResult !(TaskValue a) !TaskTime !TaskRep !TaskTree //If all goes well, a task computes its current value, an observable representation and a new task state | ExceptionResult !Dynamic !String //If something went wrong, a task produces an exception value diff --git a/Server/Framework/Task.icl b/Server/Framework/Task.icl index 216707a6fd2d7ed13f4bd5c99e52925c2def82ed..8c25937bf12eb022fd69927e6a37d113636ff3fc 100644 --- a/Server/Framework/Task.icl +++ b/Server/Framework/Task.icl @@ -9,16 +9,16 @@ from iTasks import JSONEncode, JSONDecode, dynamicJSONEncode, dynamicJSONDeco mkInstantTask :: (TaskId *IWorld -> (!TaskResult a,!*IWorld)) -> Task a | iTask a mkInstantTask iworldfun = Task (evalOnce iworldfun) where - evalOnce f _ _ _ repOpts (TCInit taskId ts) iworld = case f taskId iworld of + evalOnce f _ repOpts (TCInit taskId ts) iworld = case f taskId iworld of (ValueResult (Value a Stable) _ _ _, iworld) = (ValueResult (Value a Stable) ts (finalizeRep repOpts rep) (TCStable taskId ts (DeferredJSON a)), iworld) (ExceptionResult e s, iworld) = (ExceptionResult e s, iworld) (_,iworld) = (exception "Instant task did not complete instantly", iworld) - evalOnce f _ _ _ repOpts state=:(TCStable taskId ts enc) iworld = case fromJSONOfDeferredJSON enc of + evalOnce f _ repOpts state=:(TCStable taskId ts enc) iworld = case fromJSONOfDeferredJSON enc of Just a = (ValueResult (Value a Stable) ts (finalizeRep repOpts rep) state, iworld) Nothing = (exception "Corrupt task result", iworld) - evalOnce f _ _ _ _ (TCDestroy _) iworld = (DestroyedResult,iworld) + evalOnce f _ _ (TCDestroy _) iworld = (DestroyedResult,iworld) rep = TaskRep {UIDef|attributes= put TYPE_ATTRIBUTE "single" newMap,controls=[],actions=[]} [] diff --git a/Server/Framework/TaskEval.dcl b/Server/Framework/TaskEval.dcl index 6fff2fa174adfd00cce6466f61182b22cd41a0fb..7ce409391bb29fba209a36174b659e59be6cbcce 100644 --- a/Server/Framework/TaskEval.dcl +++ b/Server/Framework/TaskEval.dcl @@ -4,7 +4,7 @@ definition module TaskEval */ from SystemTypes import :: IWorld, :: TaskListItem, :: User, :: TaskId, :: SessionId -from Task import :: Task, :: TaskResult, :: Event, :: EditEvent, :: CommitEvent, :: RefreshFlag, :: TaskRepOpts +from Task import :: Task, :: TaskResult, :: Event, :: TaskRepOpts from Shared import :: Shared import Maybe, JSON_NG, Error @@ -31,25 +31,25 @@ createTaskInstance :: !InstanceNo !(Maybe SessionId) !InstanceNo !(Maybe User) ! * Create a new session task instance and evaluate its immediately * * @param The task to run as session +* @param An event * @param The IWorld state * * @return The result of the targeted main task and the tasknr of the instance or an error * @return The IWorld state */ -createSessionInstance :: !(Task a) !(Maybe EditEvent) !(Maybe CommitEvent) !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) | iTask a +createSessionInstance :: !(Task a) !Event !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) | iTask a /** * Evaluate a session task instance * * @param The session id -* @param Optionally an edit event -* @param Optionally a commit event +* @param An event * @param The IWorld state * * @return The result of the targeted main task or an error * @return The IWorld state */ -evalSessionInstance :: !SessionId !(Maybe EditEvent) !(Maybe CommitEvent) !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) +evalSessionInstance :: !SessionId !Event !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) /** * Create a stored task instance in the task pool (lazily without evaluating it) diff --git a/Server/Framework/TaskEval.icl b/Server/Framework/TaskEval.icl index 356426d790cb72ec4a5426ae29217a753cd5c4f3..ba05aabcd93e04d7b60980e7f8ec0f6ccc40c257 100644 --- a/Server/Framework/TaskEval.icl +++ b/Server/Framework/TaskEval.icl @@ -20,38 +20,38 @@ createTaskInstance instanceNo sessionId parent worker task mmeta pmeta iworld=:{ where toJSONTask (Task eval) = Task eval` where - eval` eEvent cEvent refresh repAs tree iworld = case eval eEvent cEvent refresh repAs tree iworld of + eval` event repOpts tree iworld = case eval event repOpts tree iworld of (ValueResult val ts rep tree,iworld) = (ValueResult (fmap toJSON val) ts rep tree, iworld) (ExceptionResult e str,iworld) = (ExceptionResult e str,iworld) -createSessionInstance :: !(Task a) !(Maybe EditEvent) !(Maybe CommitEvent) !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) | iTask a -createSessionInstance task eEvent cEvent iworld=:{currentDateTime} +createSessionInstance :: !(Task a) !Event !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) | iTask a +createSessionInstance task event iworld=:{currentDateTime} # (sessionId,iworld) = newSessionId iworld # (instanceId,iworld) = newInstanceId iworld # worker = AnonymousUser sessionId # ((meta,reduct,result,_), iworld) = createTaskInstance instanceId (Just sessionId) 0 (Just worker) task noMeta {issuedAt=currentDateTime,issuedBy=worker,status=Unstable,firstEvent=Nothing,latestEvent=Nothing} iworld - # (mbRes,iworld) = evalAndStoreInstance eEvent cEvent False (meta,reduct,result) iworld + # (mbRes,iworld) = evalAndStoreInstance event (meta,reduct,result) iworld # iworld = refreshOutdatedInstances iworld = case loadSessionInstance sessionId iworld of (Ok (meta,reduct,result),iworld) - # (mbRes,iworld) = evalAndStoreInstance eEvent cEvent False (meta,reduct,result) iworld + # (mbRes,iworld) = evalAndStoreInstance RefreshEvent (meta,reduct,result) iworld = case mbRes of Ok result = (Ok (result, instanceId, sessionId), iworld) Error e = (Error e, iworld) (Error e, iworld) = (Error e, iworld) -evalSessionInstance :: !SessionId !(Maybe EditEvent) !(Maybe CommitEvent) !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) -evalSessionInstance sessionId eEvent cEvent iworld +evalSessionInstance :: !SessionId !Event !*IWorld -> (!MaybeErrorString (!TaskResult JSONNode, !InstanceNo, !SessionId), !*IWorld) +evalSessionInstance sessionId event iworld //Set session user # iworld = {iworld & currentUser = AnonymousUser sessionId} //Update current datetime in iworld # iworld = updateCurrentDateTime iworld - //Evaluate the instance at which the targeted or refresh the session instance - # iworld = if (isJust eEvent || isJust cEvent) - (processEvent eEvent cEvent iworld) - (refreshSessionInstance sessionId iworld) + //Evaluate the instance at which the event is targeted or refresh the session instance + # iworld = case event of + RefreshEvent = refreshSessionInstance sessionId iworld + _ = processEvent event iworld //Refresh affected tasks # iworld = refreshOutdatedInstances iworld //Evaluate session instance @@ -59,7 +59,7 @@ evalSessionInstance sessionId eEvent cEvent iworld = case mbInstance of Error e = (Error e, iworld) Ok (meta,reduct,result) - # (mbRes,iworld) = evalAndStoreInstance eEvent cEvent True (meta,reduct,result) iworld + # (mbRes,iworld) = evalAndStoreInstance RefreshEvent (meta,reduct,result) iworld # iworld = remOutdatedInstance meta.TIMeta.instanceNo iworld = case mbRes of Ok result = (Ok (result, meta.TIMeta.instanceNo, sessionId), iworld) @@ -70,23 +70,21 @@ where # (dt,world) = currentDateTimeWorld world = {IWorld|iworld & currentDateTime = dt, world = world} -processEvent :: !(Maybe EditEvent) !(Maybe CommitEvent) !*IWorld -> *IWorld -processEvent Nothing Nothing iworld - = iworld -processEvent eEvent cEvent iworld - = case loadTaskInstance (instanceNo eEvent cEvent) iworld of +processEvent :: !Event !*IWorld -> *IWorld +processEvent RefreshEvent iworld = iworld +processEvent event iworld + = case loadTaskInstance (instanceNo event) iworld of (Error _,iworld) = iworld (Ok (meta,reduct,result),iworld) //Eval the targeted instance first - # (_,iworld) = evalAndStoreInstance eEvent cEvent False (meta,reduct,result) iworld + # (_,iworld) = evalAndStoreInstance event (meta,reduct,result) iworld = iworld where - instanceNo (Just (TaskEvent (TaskId no _) _)) _ = no - instanceNo _ (Just (TaskEvent (TaskId no _) _)) = no - instanceNo (Just (LuckyEvent no _)) _ = no - instanceNo _ (Just (LuckyEvent no _)) = no - instanceNo _ _ = 0 //Should not happen - + instanceNo (EditEvent (TaskId no _) _ _) = no + instanceNo (ActionEvent (TaskId no _) _) = no + instanceNo (FocusEvent (TaskId no _)) = no + instanceNo _ = 0 //Should not happen... + createPersistentInstance :: !(Task a) !ManagementMeta !User !InstanceNo !*IWorld -> (!TaskId, !*IWorld) | iTask a createPersistentInstance task meta issuer parent iworld=:{currentDateTime} # (instanceId,iworld) = newInstanceId iworld @@ -95,10 +93,10 @@ createPersistentInstance task meta issuer parent iworld=:{currentDateTime} = (TaskId instanceId 0, iworld) //Evaluate a single task instance -evalAndStoreInstance :: !(Maybe EditEvent) !(Maybe CommitEvent) !RefreshFlag !(TIMeta,TIReduct,TIResult) !*IWorld -> (!MaybeErrorString (TaskResult JSONNode),!*IWorld) -evalAndStoreInstance _ _ _ inst=:(meta=:{TIMeta|worker=Nothing},_,_) iworld +evalAndStoreInstance :: !Event !(TIMeta,TIReduct,TIResult) !*IWorld -> (!MaybeErrorString (TaskResult JSONNode),!*IWorld) +evalAndStoreInstance _ inst=:(meta=:{TIMeta|worker=Nothing},_,_) iworld = (Error "Can't evalutate a task instance with no worker set", iworld) -evalAndStoreInstance editEvent commitEvent refresh (meta=:{TIMeta|instanceNo,parent,worker=Just worker,progress},reduct=:{TIReduct|task=Task eval,nextTaskNo=curNextTaskNo,nextTaskTime,tree,shares,lists},result=:TIValue val _) iworld=:{currentUser,currentInstance,nextTaskNo,taskTime,localShares,localLists} +evalAndStoreInstance event (meta=:{TIMeta|instanceNo,parent,worker=Just worker,progress},reduct=:{TIReduct|task=Task eval,nextTaskNo=curNextTaskNo,nextTaskTime,tree,shares,lists},result=:TIValue val _) iworld=:{currentUser,currentInstance,nextTaskNo,taskTime,localShares,localLists} //Eval instance # repAs = {TaskRepOpts|useLayout=Nothing,modLayout=Nothing,appFinalLayout=True} //Update current process id & eval stack in iworld @@ -108,7 +106,7 @@ evalAndStoreInstance editEvent commitEvent refresh (meta=:{TIMeta|instanceNo,par # iworld = clearShareRegistrations instanceNo iworld # iworld = remOutdatedInstance instanceNo iworld //Apply task's eval function and take updated nextTaskId from iworld - # (result,iworld) = eval editEvent commitEvent refresh repAs tree iworld + # (result,iworld) = eval event repAs tree iworld # (updNextTaskNo,iworld) = getNextTaskNo iworld # (shares,iworld) = getLocalShares iworld # (lists,iworld) = getLocalLists iworld @@ -146,9 +144,9 @@ where taskrep (ValueResult _ _ rep _) = rep taskrep (ExceptionResult _ _) = TaskRep {UIDef|controls=[],actions=[],attributes='Map'.newMap} [] -evalAndStoreInstance _ _ _ (_,_,TIException e msg) iworld +evalAndStoreInstance _ (_,_,TIException e msg) iworld = (Ok (ExceptionResult e msg), iworld) -evalAndStoreInstance _ _ _ _ iworld +evalAndStoreInstance _ _ iworld = (Ok (exception "Could not unpack instance state"), iworld) //Evaluate tasks marked as outdated in the task pool @@ -167,7 +165,7 @@ refreshInstance instanceNo iworld = case loadTaskInstance instanceNo iworld of (Error _,iworld) = iworld (Ok (meta,reduct,result),iworld) - # (_,iworld) = evalAndStoreInstance Nothing Nothing False (meta,reduct,result) iworld + # (_,iworld) = evalAndStoreInstance RefreshEvent (meta,reduct,result) iworld = iworld refreshSessionInstance :: !SessionId !*IWorld -> *IWorld @@ -175,7 +173,7 @@ refreshSessionInstance sessionId iworld = case loadSessionInstance sessionId iworld of (Error _,iworld) = iworld (Ok (meta,reduct,result),iworld) - # (_,iworld) = evalAndStoreInstance Nothing Nothing False (meta,reduct,result) iworld + # (_,iworld) = evalAndStoreInstance RefreshEvent (meta,reduct,result) iworld = iworld localShare :: !TaskId -> Shared a | iTask a diff --git a/Server/Framework/TaskState.icl b/Server/Framework/TaskState.icl index f6c1ce7e4d68e1b46002cd67b95416c6b7f60fdb..21e261d5d829e7643c50630c2056e76f1194d9d4 100644 --- a/Server/Framework/TaskState.icl +++ b/Server/Framework/TaskState.icl @@ -2,7 +2,7 @@ implementation module TaskState import SystemTypes, UIDefinition from iTasks import JSONEncode, JSONDecode -from Task import :: Event, :: EditEvent, :: TaskTime, :: TaskResult(..), :: TaskRep(..), :: TaskServiceRep, :: TaskPart, :: TaskCompositionType +from Task import :: Event, :: TaskTime, :: TaskResult(..), :: TaskRep(..), :: TaskServiceRep, :: TaskPart, :: TaskCompositionType from GenUpdate import :: UpdateMask import JSON_NG diff --git a/Server/Framework/UIDiff.dcl b/Server/Framework/UIDiff.dcl index 889aab1ee9954ffbb79b7923f98e3fc0bb9407aa..7d11350e2c222b5bc6420a63dfc39533a8861e55 100644 --- a/Server/Framework/UIDiff.dcl +++ b/Server/Framework/UIDiff.dcl @@ -1,7 +1,7 @@ definition module UIDiff import UIDefinition -from Task import :: EditEvent, :: Event +from Task import :: Event :: UIUpdate //Leaf updates @@ -19,6 +19,6 @@ from Task import :: EditEvent, :: Event :: UIPath :== String -diffUIDefinitions :: ![UIControl] ![UIControl] !(Maybe EditEvent) -> [UIUpdate] +diffUIDefinitions :: ![UIControl] ![UIControl] !Event -> [UIUpdate] encodeUIUpdates :: ![UIUpdate] -> JSONNode \ No newline at end of file diff --git a/Server/Framework/UIDiff.icl b/Server/Framework/UIDiff.icl index 3e782a3fa0c87414c3af92c0370ae2503f9eeff1..e6141fe2192db7b59bacc6ff31b4a6ea35f127a2 100644 --- a/Server/Framework/UIDiff.icl +++ b/Server/Framework/UIDiff.icl @@ -2,7 +2,7 @@ implementation module UIDiff import StdBool, StdClass, StdList, StdEnum, StdMisc, StdTuple, sapldebug import Text, Util, UIDefinition -from Task import :: EditEvent(..), :: Event(..) +from Task import :: Event(..) :: DiffPath :== [DiffStep] :: DiffStep = ItemStep !Int | MenuStep @@ -14,10 +14,10 @@ where step (ItemStep i) = toString i step (MenuStep) = "m" -diffUIDefinitions :: ![UIControl] ![UIControl] !(Maybe EditEvent) -> [UIUpdate] +diffUIDefinitions :: ![UIControl] ![UIControl] !Event -> [UIUpdate] diffUIDefinitions old new event = [] //diffEditorDefinitions` [ItemStep 0] event old new -diffEditorDefinitions` :: !DiffPath !(Maybe EditEvent) !UIControl !UIControl -> [UIUpdate] +diffEditorDefinitions` :: !DiffPath !Event !UIControl !UIControl -> [UIUpdate] //diffEditorDefinitions` path event (UIViewString osize oview) (UIViewString nsize nview) = [] //Fallback case, simply replace old by new diffEditorDefinitions` [ItemStep parentIndex:parentPath] event old new = [UIReplace (toString parentPath) parentIndex new] diff --git a/Server/Framework/WebService.dcl b/Server/Framework/WebService.dcl index 789594a837db62578ce5a0ea43e817c63f3feb78..8c0e5194d0042ce7e8b53384ca4f688a9fdf7e23 100644 --- a/Server/Framework/WebService.dcl +++ b/Server/Framework/WebService.dcl @@ -8,4 +8,4 @@ from Engine import :: ServiceFormat from IWorld import :: IWorld import iTaskClass -webService :: !(Task a) !ServiceFormat !HTTPRequest !*IWorld -> (!HTTPResponse, !*IWorld) | iTask a \ No newline at end of file +webService :: !(HTTPRequest -> Task a) !ServiceFormat !HTTPRequest !*IWorld -> (!HTTPResponse, !*IWorld) | iTask a \ No newline at end of file diff --git a/Server/Framework/WebService.icl b/Server/Framework/WebService.icl index 777cc1e648db9199ddd2aa49ff1c8b950364ffe7..08844fc6bc388a8d282af3f45a053c2bc6d8292e 100644 --- a/Server/Framework/WebService.icl +++ b/Server/Framework/WebService.icl @@ -15,7 +15,7 @@ import Engine, IWorld derive JSONEncode ServiceResponsePart -webService :: !(Task a) !ServiceFormat !HTTPRequest !*IWorld -> (!HTTPResponse, !*IWorld) | iTask a +webService :: !(HTTPRequest -> Task a) !ServiceFormat !HTTPRequest !*IWorld -> (!HTTPResponse, !*IWorld) | iTask a webService task defaultFormat req iworld=:{IWorld|timestamp,application} = case format of //Serve start page @@ -26,12 +26,12 @@ webService task defaultFormat req iworld=:{IWorld|timestamp,application} //Load or create session context and edit / evaluate # (mbResult, prevUI, iworld) = case sessionParam of "" - # (mbResult, iworld) = createSessionInstance task Nothing Nothing iworld + # (mbResult, iworld) = createSessionInstance (task req) RefreshEvent iworld = (mbResult, [], iworld) sessionId //Check if there is a previous tui definition and check if it is still current # (prevUI,iworld) = loadPrevUI sessionId guiVersion iworld - # (mbResult, iworld) = evalSessionInstance sessionId editEvent commitEvent iworld + # (mbResult, iworld) = evalSessionInstance sessionId event iworld = (mbResult,prevUI,iworld) # (json, iworld) = case mbResult of Error err @@ -51,7 +51,7 @@ webService task defaultFormat req iworld=:{IWorld|timestamp,application} (_, TaskRep {UIDef|controls} _) = JSONObject [("success",JSONBool True) ,("session",JSONString sessionId) - ,("updates", encodeUIUpdates (diffUIDefinitions prevUI (map fst controls) editEvent)) + ,("updates", encodeUIUpdates (diffUIDefinitions prevUI (map fst controls) event)) ,("timestamp",toJSON timestamp)] _ @@ -67,9 +67,9 @@ webService task defaultFormat req iworld=:{IWorld|timestamp,application} //Serve the task in easily accessable JSON representation JSONService # (mbResult,iworld) = case sessionParam of - "" = createSessionInstance task Nothing Nothing iworld + "" = createSessionInstance (task req) RefreshEvent iworld sessionId - = evalSessionInstance sessionId Nothing Nothing iworld + = evalSessionInstance sessionId RefreshEvent iworld = case mbResult of Ok (ExceptionResult _ err,_,_) = (errorResponse err, iworld) @@ -79,20 +79,12 @@ webService task defaultFormat req iworld=:{IWorld|timestamp,application} = (jsonResponse (serviceBusyResponse rep actions (toList attributes)), iworld) //Serve the task in a minimal JSON representation (only possible for non-parallel instantly completing tasks) JSONPlain - //HACK: REALLY REALLY REALLY UGLY THAT IT IS NECCESARY TO EVAL TWICE - # (mbResult,iworld) = createSessionInstance task Nothing Nothing iworld - # (mbResult,iworld) = case mbResult of - (Ok (_,instanceId,sessionId)) - # (luckyEdit,luckyCommit) = if (req.req_data == "") - (Nothing,Nothing) - (Just (LuckyEvent instanceId ("",fromString req.req_data)), Just (LuckyEvent instanceId "")) - = evalSessionInstance sessionId luckyEdit luckyCommit iworld - (Error e) = (Error e,iworld) + # (mbResult,iworld) = createSessionInstance (task req) RefreshEvent iworld = case mbResult of Ok (ExceptionResult _ err,_,_) = (errorResponse err, iworld) - Ok (ValueResult (Value val Stable) _ _ _,_,_) - = (plainDoneResponse val, iworld) + Ok (ValueResult (Value val _) _ _ _,_,_) + = (jsonResponse val, iworld) _ = (errorResponse "Requested service format not available for this task", iworld) //Error unimplemented type @@ -108,20 +100,23 @@ where formatParam = paramValue "format" req - sessionParam = paramValue "session" req // downloadParam = paramValue "download" req // uploadParam = paramValue "upload" req versionParam = paramValue "version" req - editEventParam = paramValue "editEvent" req - editEvent = case (fromJSON (fromString editEventParam)) of - Just (task,path,value) = Just (TaskEvent (fromString task) (path,value)) - _ = Nothing - commitEventParam = paramValue "commitEvent" req - commitEvent = case (fromJSON (fromString commitEventParam)) of - Just (task,action) = Just (TaskEvent (fromString task) action) - _ = Nothing + editEventParam = paramValue "editEvent" req + actionEventParam = paramValue "actionEvent" req + focusEventParam = paramValue "focusEvent" req + + event = case (fromJSON (fromString editEventParam)) of + Just (taskId,name,value) = EditEvent (fromString taskId) name value + _ = case (fromJSON (fromString actionEventParam)) of + Just (taskId,actionId) = ActionEvent (fromString taskId) actionId + _ = case (fromJSON (fromString focusEventParam)) of + Just taskId = FocusEvent (fromString taskId) + _ = RefreshEvent + guiVersion = toInt versionParam jsonResponse json @@ -141,8 +136,6 @@ where serviceErrorResponse e = JSONObject [("status",JSONString "error"),("error",JSONString e)] - plainDoneResponse val = jsonResponse val - appStartResponse appName = {newHTTPResponse & rsp_data = toString (appStartPage appName)} appStartPage appName = HtmlTag [] [head,body] diff --git a/Server/Framework/iTaskClass.dcl b/Server/Framework/iTaskClass.dcl index 41afb2d765c2b298a76e3c672f898f6e724bc538..98c58480da0bf193f83222bf220c6d76f3023883 100644 --- a/Server/Framework/iTaskClass.dcl +++ b/Server/Framework/iTaskClass.dcl @@ -17,4 +17,3 @@ class iTask a , TC a :: Container a c = Container a & iTask c // container for context restrictions -:: TaskWrapper = E.a: TaskWrapper (Task a) & iTask a \ No newline at end of file