implementation module InternaliTasksCommon // ********************************************************************************************************************************* // iTask & iData Concept and Implementation: (c) 2006,2007,2008 - Rinus Plasmeijer // ********************************************************************************************************************************* // import StdList, StdArray, StdFunc import iDataHandler, iDataFormData, iDataTrivial import iTasksSettings import iTasksHandler, InternaliTasksThreadHandling showTaskNr :: !TaskNr -> String showTaskNr [] = "" showTaskNr [i] = toString i showTaskNr [i:is] = showTaskNr is <+++ "." <+++ toString i iTaskId :: !Int !TaskNr !String -> String iTaskId userid tasknr postfix # postfix = { c \\ c <-: postfix | not (isMember c ['\\\"/:*?<>|"']) } // throw away characters not allowed in a file name | postfix == "" | userid < 0 = "iLog_" <+++ (showTaskNr tasknr) | otherwise = "iTask_" <+++ (showTaskNr tasknr) | userid < 0 = "iLog_" <+++ (showTaskNr tasknr) <+++ "-" <+++ postfix | otherwise = "iTask_" <+++ (showTaskNr tasknr) <+++ "-" <+++ postfix // MJP:info removed to allow dynamic realloc of users: <+++ "+" <+++ userid deleteAllSubTasks :: ![TaskNr] TSt -> TSt deleteAllSubTasks [] tst = tst deleteAllSubTasks [tx:txs] tst=:{hst,userId} # hst = deleteIData (iTaskId userId (tl tx) "") hst = deleteAllSubTasks txs {tst & hst = hst} // ****************************************************************************************************** // Task creation and printing // ****************************************************************************************************** incTaskNr tst = {tst & tasknr = incNr tst.tasknr} incNr :: !TaskNr -> TaskNr incNr [] = [0] incNr [i:is] = [i+1:is] // mkTask is an important wrapper function which should be wrapped around any task // It takes care of // - deciding whether the task should be called (activated) or not // - adding of trace information // - generating task numbers in a systematic way // It is very important that the numbering of the tasks is done systematically // Every task should have a unique number // Every sequential task should increase the task number // If a task j is a subtask of task i, than it will get number i.j in reverse order mkTask :: !String !(Task a) -> (Task a) | iCreateAndPrint a mkTask taskname mytask = mkTaskNoInc taskname mytask o incTaskNr mkTaskNoInc :: !String !(Task a) -> (Task a) | iCreateAndPrint a // common second part of task wrappers mkTaskNoInc taskname mytask = mkTaskNoInc` where mkTaskNoInc` tst=:{activated,tasknr,userId,options} | not activated = (createDefault,tst) // not active, don't call task, return default value # (val,tst=:{activated,trace}) = mytask tst // active, so perform task and get its result # tst = {tst & tasknr = tasknr, options = options, userId = userId} | isNothing trace || taskname == "" = (val,tst) // no trace, just return value = (val,{tst & trace = Just (InsertTrace activated tasknr userId options taskname (printToString val%(0,30)) (fromJust trace))}) // adjust trace, don't print to long values mkParSubTask :: !String !Int (Task a) -> (Task a) | iCreateAndPrint a // two shifts are needed mkParSubTask name i task = mkParSubTask` where mkParSubTask` tst=:{tasknr, options} # (v,tst) = mkTaskNoInc (name <+++ "." <+++ i) mysubtask {tst & tasknr = [i:tasknr],activated = True} // shift task = (v,{tst & tasknr = tasknr, options = options}) where mysubtask tst=:{tasknr} = task {tst & tasknr = [-1:tasknr], activated = True} // shift once again! // ****************************************************************************************************** // Trace Printing... // ****************************************************************************************************** InsertTrace :: !Bool !TaskNr !Int !Options String !String ![Trace] -> [Trace] InsertTrace finished idx who options taskname val trace = InsertTrace` ridx who val trace where InsertTrace` :: !TaskNr !Int !String ![Trace] -> [Trace] InsertTrace` [i] who str traces | i < 0 = abort ("negative task numbers:" <+++ showTaskNr idx <+++ "," <+++ who <+++ "," <+++ taskname) # (Trace _ itraces) = select i traces = updateAt` i (Trace (Just (finished,(who,show,options,taskname,str))) itraces) traces InsertTrace` [i:is] who str traces | i < 0 = abort ("negative task numbers:" <+++ showTaskNr idx <+++ "," <+++ who <+++ "," <+++ taskname) # (Trace ni itraces) = select i traces # nistraces = InsertTrace` is who str itraces = updateAt` i (Trace ni nistraces) traces select :: !Int ![Trace] -> Trace select i list | i < length list = list!!i = Trace Nothing [] show = idx //showTaskNr idx ridx = reverse idx updateAt`:: !Int !Trace ![Trace] -> [Trace] updateAt` n x list | n < 0 = abort "negative numbers not allowed" = updateAt` n x list where updateAt`:: !Int !Trace ![Trace] -> [Trace] updateAt` 0 x [] = [x] updateAt` 0 x [y:ys] = [x:ys] updateAt` n x [] = [Trace Nothing [] : updateAt` (n-1) x []] updateAt` n x [y:ys] = [y : updateAt` (n-1) x ys] printTrace2 :: !(Maybe ![Trace]) -> BodyTag printTrace2 Nothing = EmptyBody printTrace2 (Just a) = BodyTag [showLabel "Task Tree Forest:", Br, STable emptyBackground (print False a),Hr []] where print _ [] = [] print b trace = [pr b x ++ [STable emptyBackground (print (isDone x||b) xs)]\\ (Trace x xs) <- trace] pr _ Nothing = [] pr dprev (Just (dtask,(w,i,op,tn,s))) | dprev && (not dtask) = pr False Nothing // subtask not important anymore (assume no milestone tasks) | not dtask && tn%(0,4) == "Ajax " = showTask cellattr1b White Navy Aqua Silver (w,i,op,tn,s) | not dtask && tn%(0,6) == "Server " = showTask cellattr1b White Navy Aqua Silver (w,i,op,tn,s) | not dtask && tn%(0,6) == "Client " = showTask cellattr1b White Navy Aqua Silver (w,i,op,tn,s) | not dtask = showTask cellattr1b White Navy Maroon Silver (w,i,op,tn,s) = showTask cellattr1a White Yellow Red White (w,i,op,tn,s) showTask2 attr1 c1 c2 c3 c4 (w,i,op,tn,s) = [Table doneBackground [ Tr [] [Td attr1 [font c1 (toString (last (reverse i)))], Td cellattr2 [font c2 tn]] , Tr [] [Td attr1 [font c3 (toString w)], Td cellattr2 [font c4 s]] ] ,Br] showTask att c1 c2 c3 c4 (w,i,op,tn,s) = [STable doneBackground [ [font c1 (toString w),font c2 ("T" <+++ showTaskNr i)] , [showStorage op.tasklife, font c3 tn] , [EmptyBody, font c4 s] ] ] isDone Nothing = False isDone (Just (b,(w,i,op,tn,s))) = b showStorage Temp = font Silver "Tmp" showStorage Client = font Aqua "Cli" showStorage Page = font Navy "Pag" showStorage Session = font Navy "Ssn" showStorage TxtFileRO = font Red "TxF0" showStorage TxtFile = font Red "TxF" showStorage DataFile = font Red "DaF" showStorage Database = font Red "DaB" doneBackground = [ Tbl_CellPadding (Pixels 1), Tbl_CellSpacing (Pixels 0), cellwidth , Tbl_Rules Rul_None, Tbl_Frame Frm_Border ] doneBackground2 = [ Tbl_CellPadding (Pixels 0), Tbl_CellSpacing (Pixels 0), cellwidth ] emptyBackground = [Tbl_CellPadding (Pixels 0), Tbl_CellSpacing (Pixels 0)] cellattr1a = [Td_Bgcolor (`Colorname Green), Td_Width (Pixels 10), Td_VAlign Alo_Absmiddle] cellattr1b = [Td_Bgcolor (`Colorname Silver), Td_Width (Pixels 10), Td_VAlign Alo_Absmiddle] cellattr2 = [Td_VAlign Alo_Top] cellwidth = Tbl_Width (Pixels 130) font color message = Font [Fnt_Color (`Colorname color), Fnt_Size -1] [B [] message] // ****************************************************************************************************** // iTask Storage Utilities // ****************************************************************************************************** cFormId :: !Options !String !a -> FormId a cFormId {tasklife,taskstorage,taskmode} s d = {sFormId s d & lifespan = tasklife, storage = taskstorage, mode = taskmode} sessionFormId :: !Options !String !a -> FormId a sessionFormId options s d = cFormId options s d <@ if (options.tasklife == Client) Client Session pageFormId :: !Options !String !a -> FormId a pageFormId options s d = cFormId options s d <@ if (options.tasklife == Client) Client Page storageFormId :: !Options !String !a -> FormId a storageFormId options s d = cFormId options s d <@ NoForm