Commit 1d9ddb6a authored by Bas Lijnse's avatar Bas Lijnse

Replaced use of WorkTabHandler by TaskService. Also removed old Handler files.

git-svn-id: https://svn.cs.ru.nl/repos/iTask-system/trunk@1124 63da3aa8-80fd-4f01-9db8-e6ea747a3da2
parent 7e4ee009
......@@ -18,8 +18,8 @@ itasks.WorkPanel = Ext.extend(itasks.RemoteDataPanel, {
closable: true,
autoDestroy: true,
iconCls: "icon-task",
url: itasks.config.serverUrl + "/work/tab",
params: {_maintask: this.taskId, _debug: itasks.app.debug ? 1 : 0},
url: itasks.config.servicesUrl + "/json/tasks/" + this.taskId + "/tui",
params: {_session: itasks.app.session},
layout: "border",
items: [{
xtype: "itasks.work-header",
......@@ -94,14 +94,14 @@ itasks.WorkPanel = Ext.extend(itasks.RemoteDataPanel, {
update: function(data) {
//Check if the task is finished or became redundant
if(data.content == "done" || data.content == "redundant") {
if(data.tui == "done" || data.tui == "redundant") {
var ct = this.getComponent(1);
if(ct.items && ct.items.length) {
ct.remove(0);
}
switch(data.content) {
switch(data.tui) {
case "done":
ct.add({
xtype: 'itasks.ttc.finished',
......@@ -135,23 +135,16 @@ itasks.WorkPanel = Ext.extend(itasks.RemoteDataPanel, {
return;
}
//Update properties
this.properties = data.properties;
this.properties = data.task;
//Update header
this.getComponent(0).setContent(this.taskId, data.subject, data.properties);
this.getComponent(0).setContent(this.taskId, data.task.managerProperties.subject, data.task);
//Update title
this.updateTitle(data.subject);
this.updateTitle(data.task.managerProperties.subject);
//Update content
this.updateContent(data.content);
//Update Toolbar
this.updateToolbar(data.properties);
//Reset params, events and states
this.params =
{ _maintask : this.taskId
, _debug: itasks.app.debug ? 1 : 0
}
this.updateContent(data.tui);
},
updateTitle: function(subject) {
this.setTitle(Ext.util.Format.ellipsis(subject.join(" - "),10));
this.setTitle(Ext.util.Format.ellipsis(subject,10));
},
updateContent: function(content) {
var ct = this.getComponent(1);
......@@ -174,6 +167,16 @@ itasks.WorkPanel = Ext.extend(itasks.RemoteDataPanel, {
this.initialized = true;
}
},
sendTaskUpdates: function(target, updates) {
//Build event list
var events = [];
for(var k in updates) {
events[events.length] = [target,k,updates[k].toString()];
}
//Set events and refresh
this.params["events"] = Ext.encode(events);
this.refresh();
},
updateToolbar: function(properties) {
var getUserName = function(name){
if(name.match("(.+)<(.+)>"))
......@@ -189,31 +192,6 @@ itasks.WorkPanel = Ext.extend(itasks.RemoteDataPanel, {
cancelMI.disable();
}
},
sendTaskUpdates: function(target,updates) {
//Add task updates to params
Ext.apply(this.params, updates);
//Set target and state
this.params["_targettask"] = target;
this.refresh();
},
sendPropertyEvent: function(process,name,value) {
//Ugly side-effect event handler
this.getComponent(0).setBusy(true);
Ext.Ajax.request({
url: itasks.config.serverUrl + "/work/property",
method: "GET",
params: {_session : itasks.app.session, process : process, property: name, value: value },
callback: function(el,success,response,options) {
this.getComponent(0).setBusy(false);
this.fireEvent("propertyChanged");
if(name == "user" || name == "progress") //HACK: Fix with proper property events
this.refresh();
},
scope: this
});
},
cancel : function(){
var me = this;
......@@ -266,7 +244,7 @@ itasks.WorkHeaderPanel = Ext.extend(Ext.Panel, {
}
}
var subject = subject.join(" &raquo; ") + (itasks.config.debug ? (" (" + taskid + ")") : "");
var subject = subject + (itasks.config.debug ? (" (" + taskid + ")") : "");
this.body.update( String.format(
'<div class="worktab-header {1}">'+
......@@ -286,46 +264,5 @@ itasks.WorkHeaderPanel = Ext.extend(Ext.Panel, {
}
});
itasks.WorkStatusPanel = Ext.extend(Ext.Panel, {
initComponent: function() {
Ext.apply(this, {
layout: "form",
cls: "worktab-content",
defaultType: "staticfield",
items: [{
xtype: "itasks.progress",
name: "progress",
fieldLabel: "Progress",
format: itasks.util.formatProgress,
listeners: {
"change" : function(ov,nv) {var wt = this.findParentByType(itasks.WorkPanel); wt.sendPropertyEvent(wt.properties.systemProperties.taskId,"progress",nv); }
}
},{
name: "priority",
fieldLabel: "Priority",
format: itasks.util.formatPriority
},{
name: "issuedAt",
fieldLabel: "Issued at",
format: itasks.util.formatDate
},{
name: "firstEvent",
fieldLabel: "First worked on",
format: itasks.util.formatStartDate
},{
name: "latestEvent",
fieldLabel: "Last worked on",
format: itasks.util.formatStartDate
}]
});
itasks.WorkStatusPanel.superclass.initComponent.apply(this,arguments);
},
update: function (p) {
var props = [p.workerProperties.progress,p.managerProperties.priority,p.systemProperties.issuedAt,p.systemProperties.firstEvent,p.systemProperties.latestEvent];
this.items.each(function(cmt,i){ cmt.setValue(props[i]); });
}
});
Ext.reg("itasks.work",itasks.WorkPanel);
Ext.reg("itasks.work-header",itasks.WorkHeaderPanel);
Ext.reg("itasks.work-status",itasks.WorkStatusPanel);
\ No newline at end of file
Ext.reg("itasks.work-header",itasks.WorkHeaderPanel);
\ No newline at end of file
......@@ -15,7 +15,6 @@ import Http, HttpUtil
from HttpServer import :: HTTPServerControl(..), :: HTTPServerOption(..)
import Setup
import WorkTabHandler, PropertyHandler
import RPCHandlers
import ApplicationService, SessionService, WorkflowService, TaskService, UserService, DocumentService
......@@ -39,10 +38,7 @@ where
handlers config
= [
//'old' handlers
((==) (config.serverPath +++ "/work/tab"), handleSessionRequest config flows handleWorkTabRequest)
,((==) (config.serverPath +++ "/work/property"), handleSessionRequest config flows handlePropertyRequest)
,((==) (config.serverPath +++ "/rpc/request"), handleSessionRequest config flows handleRPCListRequest)
((==) (config.serverPath +++ "/rpc/request"), handleSessionRequest config flows handleRPCListRequest)
,((==) (config.serverPath +++ "/rpc/response"), handleSessionRequest config flows handleRPCUpdates)
// Webservices
,(startsWith "/services", serviceDispatch config flows)
......@@ -159,16 +155,14 @@ initTSt request config flows world
# ((err,info),world) = getFileInfo path world
| err <> NoDirError = abort "Cannot get executable info."
# (date,time) = info.pi_fileInfo.lastModified
# datestr = (toString date.Date.year)+++"."+++(addPrefixZero date.Date.month)+++"."+++(addPrefixZero date.Date.day)+++"-"+++(addPrefixZero time.Time.hours)+++"."+++(addPrefixZero time.Time.minutes)+++"."+++(addPrefixZero time.Time.seconds)
# datestr = (toString date.Date.year)+++"."+++(padZero date.Date.month)+++"."+++(padZero date.Date.day)+++"-"+++(padZero time.Time.hours)+++"."+++(padZero time.Time.minutes)+++"."+++(padZero time.Time.seconds)
# ((ok,datapath),world) = pd_StringToPath appName world
# (err,world) = createDirectory datapath world
| err <> NoDirError
&& err <> AlreadyExists = abort "Cannot create data directory"
= mkTSt appName config request flows (createStore (appName +++ "\\" +++ datestr)) world
where
addPrefixZero number
| number < 10 = "0"+++toString number
| otherwise = toString number
padZero number = (if (number < 10) "0" "") +++ toString number
finalizeTSt :: !*TSt -> *World
finalizeTSt tst=:{TSt|iworld={IWorld|world}} = world
......@@ -185,7 +179,4 @@ determineAppName world
# (args,world) = getCommandLine world
= (strip (hd args),world)
where
strip path = let executable = last (split PATH_SEP path) in executable % (0, size executable - 5)
strip path = let executable = last (split PATH_SEP path) in executable % (0, size executable - 5)
\ No newline at end of file
definition module AuthenticationHandler
import Http
import TSt
/**
* Handles the ajax request from the login window. It validates the username and
* password and returns session information to the client.
*/
handleAuthenticationRequest :: !HTTPRequest *TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module AuthenticationHandler
import StdEnv, StdMaybe
import Http
import SessionDB, UserDB
handleAuthenticationRequest :: !HTTPRequest *TSt -> (!HTTPResponse, !*TSt)
handleAuthenticationRequest req tst
# (mbUser, tst) = authenticateUser username password tst
= case mbUser of
Just user
# (session, tst) = createSession user tst
# tst = flushStore tst
= ({http_emptyResponse & rsp_data = encodeSuccess session.sessionId (displayName user)},tst)
Nothing
= ({http_emptyResponse & rsp_data = encodeFailure},tst)
where
username = http_getValue "username" req.arg_post ""
password = http_getValue "password" req.arg_post ""
encodeFailure = "{\"success\": false, \"error\": \"Incorrect username or password\"}"
encodeSuccess sid displayName = "{\"success\": true, \"displayName\": \"" +++ displayName +++ "\", \"sessionId\": \"" +++ sid +++ "\"}"
\ No newline at end of file
definition module DeauthenticationHandler //iTasks.Framework.Handlers.DeauthenticationHandler
/**
* Handles the ajax requests to terminate the current session
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handleDeauthenticationRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module DeauthenticationHandler
import Http, TSt, SessionDB
handleDeauthenticationRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handleDeauthenticationRequest request tst=:{staticInfo}
# (_,tst) = deleteSession staticInfo.currentSession.sessionId tst
= ({http_emptyResponse & rsp_data = "{\"success\" : \"true\"}"}, tst)
definition module NewListHandler //iTasks.Handlers.NewListHandler
/**
* Handles the ajax requests from the 'start new work' panel.
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handleNewListRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module NewListHandler
import StdEnv
import Http, TSt
import JSON, Util, Text
import UserDB, SessionDB
:: NewWorkItem = { id :: !String // The name of the workflow that is started
, iconCls :: !String // An icon name. The actual icon image is defined in the css.
, text :: !String // A label of the workflow that is started
, leaf :: !Bool // Is it a leaf in the tree structure
, singleClickExpand :: !Bool // Single click expand extjs option
}
derive JSONEncode NewWorkItem
handleNewListRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handleNewListRequest request tst
# path = http_getValue "node" request.arg_post "_ROOT_"
# path = if (path == "_ROOT_") "" path
# (session,tst) = getCurrentSession tst
# (workflows,tst) = getWorkflows tst
= ({http_emptyResponse & rsp_data = toString (toJSON (sort (removeDup [ mkNode flow path \\ flow <- workflows
| checkRoles flow session && checkPath flow path
])))}, tst)
where
checkRoles flow session
| isEmpty flow.Workflow.roles = True //The workflow does not have required roles
| otherwise = case session.Session.user of
//The "root" user does not need to have assigned roles
RootUser = True
//User has at least one of the roles needed for the flow
RegisteredUser details = or [isMember role (mb2list details.UserDetails.roles) \\ role <- flow.Workflow.roles]
//Workflow is not allowed
_ = False
checkPath flow path = flow.Workflow.path % (0, (size path - 1)) == path
mkNode flow path
# shortPath = flow.Workflow.path % (size path, size flow.Workflow.path)
# slashPosition = indexOf "/" shortPath
| slashPosition == -1
= {id = flow.Workflow.path, iconCls = "icon-workflow", text = shortPath, leaf = True, singleClickExpand = True}
| otherwise
# text = shortPath % (0, slashPosition - 1)
= {id = path +++ text +++ "/", iconCls = "icon-folder", text = text, leaf = False, singleClickExpand = True}
instance == NewWorkItem
where
(==) {NewWorkItem| id = a} {NewWorkItem| id = b} = a == b
instance < NewWorkItem
where
(<) {NewWorkItem| id = a} {NewWorkItem| id = b} = a < b
\ No newline at end of file
definition module NewStartHandler
/**
* Handles the ajax requests from the 'start new work' panel.
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handleNewStartRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module NewStartHandler
import StdEnv
import Http, TSt, ProcessDB, UserDB, Time
handleNewStartRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handleNewStartRequest request tst
# (mbWorkflow, tst) = getWorkflowByName workflowId tst
= case mbWorkflow of
Nothing
= ({http_emptyResponse & rsp_data = "{\"success\" : false }" }, tst)
Just workflow
# (taskid, tst) = startWorkflow workflow tst
= ({http_emptyResponse & rsp_data = response taskid}, tst)
where
workflowId :: String
workflowId = http_getValue "workflow" request.arg_post ""
response :: String -> String
response taskid = "{\"success\" : true, \"taskid\": \"" +++ taskid +++ "\"}"
startWorkflow :: !Workflow !*TSt -> (!ProcessId,!*TSt)
startWorkflow workflow tst
# (pid,_,_,tst) = createTaskInstance workflow.Workflow.thread True Nothing True True tst
= (pid,tst)
\ No newline at end of file
definition module ProcessTableHandler
/**
* This provides a handler which visualizes all processes in the
* the iTasks process database.
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
/**
* Handles the ajax requests for a ProcessTable tab panel.
*/
handleProcessTableRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module ProcessTableHandler
import StdEnv
import Http, TSt, ProcessDB, Trace
/**
* Handles the ajax requests for a ProcessTable tab panel.
*/
handleProcessTableRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handleProcessTableRequest request tst
# (processes,tst) = getProcesses [Active,Suspended,Finished,Deleted] tst
# content = toString (traceProcesses processes)
= ({http_emptyResponse & rsp_data = content}, tst)
definition module PropertyHandler
/**
* Handles the ajax requests to update properties of main tasks.
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handlePropertyRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module PropertyHandler
import TSt, Types
import StdInt, StdMaybe
import Http, JSON
import ProcessDB, UserDB
/**
* This handler is used to update properties of main tasks.
*/
:: PropertyResponse =
{ success :: Bool
, error :: Maybe String
}
derive JSONEncode PropertyResponse
handlePropertyRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handlePropertyRequest req tst
= case http_getValue "process" req.arg_get "" of
"" = (errorResponse "Invalid process id", tst)
proc = case http_getValue "property" req.arg_get "" of
"priority" = updatePriority proc (http_getValue "value" req.arg_get "") tst
"user" = updateUser proc (http_getValue "value" req.arg_get "") tst
"progress" = updateProgress proc (http_getValue "value" req.arg_get "") tst
_ = (errorResponse "Invalid property", tst)
where
updatePriority proc prio tst
= case parsePrio prio of
(Just prio)
# (_,tst) = updateProcessProperties proc (\p -> {p & managerProperties = {p.managerProperties & priority = prio}}) tst
= (successResponse, tst)
Nothing
= (errorResponse "Unknown priority", tst)
parsePrio "LowPriority" = Just LowPriority
parsePrio "NormalPriority" = Just NormalPriority
parsePrio "HighPriority" = Just HighPriority
parsePrio _ = Nothing
updateUser proc username tst=:{staticInfo}
# (_,tst) = updateProcessProperties proc (\p -> {TaskProperties| p & managerProperties = {ManagerProperties | p.managerProperties & worker = NamedUser username}, workerProperties = {p.workerProperties & progress = TPActive}}) tst
= (successResponse,tst)
updateProgress proc val tst
= case parseProgress val of
(Just val)
# (_,tst) = updateProcessProperties proc (\p -> {p & workerProperties = {p.workerProperties & progress = val}}) tst
= (successResponse, tst)
Nothing
= (errorResponse "Unknown progress value", tst)
parseProgress "TPActive" = Just TPActive
parseProgress "TPStuck" = Just TPStuck
parseProgress "TPWaiting" = Just TPWaiting
parseProgress "TPReject" = Just TPReject
parseProgress _ = Nothing
errorResponse :: String -> HTTPResponse
errorResponse msg =
{ rsp_headers = []
, rsp_data = toString (toJSON {PropertyResponse|success = False, error = Just msg})
}
successResponse :: HTTPResponse
successResponse =
{ rsp_headers = []
, rsp_data = toString (toJSON {PropertyResponse|success = True, error = Nothing})
}
instance fromString Int
where
fromString x = toInt x
......@@ -119,13 +119,13 @@ taskService url html path req tst
Just proc
# task = taskItem proc
//Updates are posted as a list of triplets
# updates = case (fromJSON (fromString updatesParam)) of
Just updates = updates
# events = case (fromJSON (fromString eventsParam)) of
Just events = events
Nothing = []
//The menusChanged parameter is a global flag that is set when any task in the tree has
//changed the menu and thus the menu needs to be replaced
# (tree,tst=:{TSt|menusChanged})
= calculateTaskTree taskId updates tst
= calculateTaskTree taskId events tst
= case tree of
(TTMainTask ti properties menus _ content)
# tui = buildTaskPanel content menus menusChanged session.Session.user
......@@ -224,8 +224,8 @@ where
debugParams = [("_session",sessionParam,True)]
detailsParams = [("_session",sessionParam,True)]
tuiParams = [("_session",sessionParam,True),("updates",updatesParam,False)]
updatesParam = paramValue "updates" req
tuiParams = [("_session",sessionParam,True),("events",eventsParam,False)]
eventsParam = paramValue "events" req
propParams = [("_session",sessionParam,True),("update",updateParam,False)]
updateParam = paramValue "update" req
......
definition module TaskTreeForestHandler
/**
* This module provides a handler that computes and visualizes the complete! task forest
* of all relevant processes for the current user.
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handleTaskForestRequest :: !HTTPRequest *TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module TaskTreeForestHandler
import StdEnv
import Http, TSt, Trace
handleTaskForestRequest :: !HTTPRequest *TSt -> (!HTTPResponse, !*TSt)
handleTaskForestRequest request tst
# (forest, tst) = calculateTaskForest [] tst
= ({http_emptyResponse & rsp_data = traceTaskForest forest}, tst)
\ No newline at end of file
definition module ThreadTableHandler
import Http, TSt
/**
* Handles the ajax requests for a ThreadTable tab panel.
*/
handleThreadTableRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module ThreadTableHandler
import StdEnv
import Http, TSt
import iDataForms, iDataState
/**
* Handles the ajax requests for a ThreadTable tab panel.
*/
handleThreadTableRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handleThreadTableRequest request tst
# threadTable = []
# content = toString (DivTag [IdAttr "itasks-threadtable", ClassAttr "trace"] threadTable) // create tab data record
= ({http_emptyResponse & rsp_data = content}, tst) // create the http response
definition module UserListHandler
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handleUserListRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module UserListHandler
import StdList, StdBool
import Http, TSt
import UserDB
import JSON, Text
:: UserResponse =
{ total :: !Int
, users :: ![UserRecord]
}
:: UserRecord =
{ user :: !String
}
derive JSONEncode UserResponse,UserRecord
handleUserListRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
handleUserListRequest req tst=:{staticInfo}
# (users,tst) = getUsers tst
# filtered = (rootItem staticInfo.currentSession.Session.user) ++
[{UserRecord
|user = toString user
} \\ user =:(RegisteredUser details) <- users
| query == "" || startsWith query details.UserDetails.userName || startsWith query details.UserDetails.displayName
]
= ({http_emptyResponse & rsp_data = toString (toJSON {UserResponse| users = filtered, total = length filtered})}, tst)
where
//Only add Root user entry for root itself
rootItem RootUser = [{UserRecord|user = toString RootUser}]
rootItem _ = []
query = http_getValue "query" req.arg_post ""
\ No newline at end of file
definition module WorkListHandler //iTasks.Handlers.WorkListHandler
/**
* Handles the ajax requests from the current work filter panel.
*/
from TSt import :: TSt
from Http import :: HTTPRequest, :: HTTPResponse
handleWorkListRequest :: !HTTPRequest !*TSt -> (!HTTPResponse, !*TSt)
\ No newline at end of file
implementation module WorkListHandler
import StdEnv
import Http, TSt, UserDB, ProcessDB
import Text, JSON, Time, Util