MyTasks portlet improvements and fixes:

- Inner panel of MyTasks portlet now a separate webscript called 'mytaskspanel' and an ajax request is used to refresh or update the panel after an action occurs.
 - Generated task actions fixed to use ajax refresh rather than full window refresh (fixes issue with MyTasks portlet actions being used in JSF-168 or JSF runtime)
 - Generated task actions fixed to handle default (null) transition ID
Permission checking added to MySpaces portlet actions.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5808 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2007-05-30 09:35:20 +00:00
parent b2a11b9832
commit c05c6a253f
7 changed files with 154 additions and 81 deletions

View File

@@ -33,13 +33,13 @@
<td class="spaceAction docActionViewContent">View Content</td>
</tr>
<tr>
<td class="spaceAction docActionDelete" onclick='event.cancelBubble=true;MySpaces.deleteItem("${node.name}", "${node.nodeRef}");'>Delete</td>
<td class="spaceAction docActionDelete" <#if node.hasPermission("Delete")>onclick='event.cancelBubble=true;MySpaces.deleteItem("${node.name}", "${node.nodeRef}");'</#if>>Delete</td>
<td class="spaceAction docActionMoreActions">More Actions...</td>
</tr>
<#else>
<tr>
<td class="spaceAction spaceActionEditDetails">Edit Details</td>
<td class="spaceAction spaceActionDelete" onclick='event.cancelBubble=true;MySpaces.deleteItem("${node.name}", "${node.nodeRef}");'>Delete</td>
<td class="spaceAction spaceActionDelete" <#if node.hasPermission("Delete")>onclick='event.cancelBubble=true;MySpaces.deleteItem("${node.name}", "${node.nodeRef}");'</#if>>Delete</td>
</tr>
<tr>
<td class="spaceAction spaceActionMoreActions">More Actions...</td>

View File

@@ -54,14 +54,14 @@
<div class="spaceToolbar">
<#-- TODO: permission checks on the actions! -->
<#-- Upload File action -->
<div class="spaceToolbarAction spaceToolbarActionUpload" title="Upload a new document" onclick="MySpaces.upload(this);">Upload</div>
<div class="spaceToolbarAction spaceToolbarActionUpload" title="Upload a new document" <#if home.hasPermission("CreateChildren")>onclick="MySpaces.upload(this);"</#if>>Upload</div>
<div class="spaceUploadPanel">
<#-- Url encode the path value, and encode any single quotes to generate valid string -->
<input class="spaceFormItem" type="submit" value="OK" onclick='MySpaces.uploadOK(this, "${path?url?replace("'","_%_")}");'>
<input class="spaceFormItem" type="button" value="Cancel" onclick="MySpaces.closePopupPanel();">
</div>
<#-- Create Space action -->
<div class="spaceToolbarAction spaceToolbarActionCreateSpace" title="Create a new Space" onclick="MySpaces.createSpace(this);">Create Space</div>
<div class="spaceToolbarAction spaceToolbarActionCreateSpace" title="Create a new Space" <#if home.hasPermission("CreateChildren")>onclick="MySpaces.createSpace(this);"</#if>>Create Space</div>
<div class="spaceCreateSpacePanel">
<table cellspacing="2" cellpadding="2" border="0">
<tr><td class="spaceFormLabel">Name:</td><td><input class="spaceFormItem" type="text" size="32" maxlength="1024" id="space-name"></td></tr>

View File

@@ -34,71 +34,11 @@
<td width=4 class="paperEdgeRight"><td>
</tr>
<tr><td bgcolor="#F9F3B0">&nbsp;</td><td>
<div id="taskPanelOverlay"></div>
<div id="taskPanel">
<#assign weekms=1000*60*60*24*7>
<#assign count=0>
<#list workflow.assignedTasks?sort_by('startDate') as t>
<#-- TODO: is it better to use a js script to pre-filter the list? -->
<#assign hasDue=t.properties["bpm:dueDate"]?exists>
<#if hasDue>
<#assign due=t.properties["bpm:dueDate"]>
</#if>
<#if (filter=0) ||
(filter=3 && !hasDue) ||
(filter=1 && hasDue && (dateCompare(date?date, due?date, 0, "==") == 1)) ||
(filter=2 && hasDue && (dateCompare(due?date, date?date) == 1 && dateCompare(date?date, due?date, weekms) == 1)) ||
(filter=4 && hasDue && (dateCompare(date?date, due?date) == 1))>
<#assign count=count+1>
<div class="taskRow" id="${t.id}">
<div class="taskTitle">
<div class="taskIndicator">
<#if hasDue>
<#-- items due today? -->
<#if (filter=0 || filter=1) && (dateCompare(date?date, due?date, 0, "==") == 1)>
<img src="${url.context}/images/icons/task_today.gif"></div><div class="taskItem taskItemToday">
<#-- items overdue? -->
<#elseif (filter=0 || filter=4) && (dateCompare(date?date, due?date) == 1)>
<img src="${url.context}/images/icons/task_overdue.gif"></div><div class="taskItem taskItemOverdue">
<#else>
</div><div class="taskItem">
</#if>
<#else>
</div><div class="taskItem">
</#if>
${t.description?html} (${t.type?html})
<#if hasDue>
(Due: ${due?date})
</#if>
<span class="taskInfo" onclick="event.cancelBubble=true; TaskInfoMgr.toggle('${t.id}',this);">
<img src="${url.context}/images/icons/popup.gif" class="popupImage" width="16" height="16" />
</span>
</div>
</div>
<div class="taskDetail">
<div style="float:left">
<table cellpadding='2' cellspacing='0' style="margin-left:32px;margin-top:16px">
<tr><td class="taskMetaprop">Status:</td><td class="taskMetadata">${t.properties["bpm:status"]}</td>
<tr><td class="taskMetaprop">Priority:</td><td class="taskMetadata">${t.properties["bpm:priority"]}</td>
<tr><td class="taskMetaprop">Start Date:</td><td class="taskMetadata">${t.startDate?date}</td></tr>
<tr><td class="taskMetaprop">Type:</td><td class="taskMetadata">${t.type?html}</td></tr>
<tr><td class="taskMetaprop">Complete:</td><td class="taskMetadata">${t.properties["bpm:percentComplete"]}%</td>
</table>
</div>
<div class="taskResourceHeader">${t.name?html}:</div>
<div class="taskResources"></div>
<div>
<table class="taskActions" style="padding-left:16px">
<tr>
<#list t.transitions as wt>
<td><a class="taskAction" href="#" onclick="MyTasks.transitionTask('/command/task/end/${t.id}/${wt.id}', '${scripturl("?f=${filter}")}', 'Workflow action \'${wt.label?html}\' completed.');">${wt.label?html}</a></td>
</#list>
</tr>
</table>
</div>
</div>
</div>
</#if>
</#list>
<#-- populated via an AJAX call to 'mytaskspanel' webscript -->
<#-- resolved filter required as argument -->
<script>MyTasks.Filter="${filter}";</script>
</div>
</td>
<td width=4 class="paperEdgeRight"><td>
@@ -107,7 +47,8 @@
<td bgcolor="#F9F3B0">&nbsp;</td>
<td>
<div id="taskFooter">
Showing ${count} <#if filter=4>overdue</#if> task(s)<#if filter=1> due today</#if><#if filter=2> due next week</#if><#if filter=3> with no due date set</#if>.
<#-- the count value is retrieved and set dynamically from the AJAX webscript output above -->
Showing <span id="taskCount">0</span> <#if filter=4>overdue</#if> task(s)<#if filter=1> due today</#if><#if filter=2> due next week</#if><#if filter=3> with no due date set</#if>.
</div>
</td>
<td class="paperEdgeRight"><td>
@@ -119,9 +60,6 @@
</tr>
</table>
<#-- display status message if provided -->
<#if args.m?exists><script>window.addEvent('load', MyTasks.displayMessage("${args.m}"));</script></#if>
<STYLE type="text/css">
a.taskfilterLink:link, a.taskfilterLink:visited
{
@@ -163,6 +101,20 @@ a.taskfilterLinkSelected:link, a.taskfilterLinkSelected:visited
overflow: auto;
border-top: 1px solid #EBE398;
border-left: 1px solid #F6DEA0;
visibility: hidden;
}
#taskPanelOverlay
{
background-image: url(${url.context}/images/icons/ajax_anim.gif);
background-position: center;
background-repeat: no-repeat;
position: absolute;
border-top: 1px solid #EBE398;
border-left: 1px solid #F6DEA0;
height: 300px;
width: 716px;
overflow: hidden;
}
.taskRow

View File

@@ -0,0 +1,7 @@
<webscript>
<shortname>My Tasks Panel</shortname>
<description>Generate the Generate the inner panel for the My Tasks portlet page</description>
<url format="html" template="/mytaskspanel?f={filter?}"/>
<authentication>user</authentication>
<transaction>required</transaction>
</webscript>

View File

@@ -0,0 +1,67 @@
<#assign weekms=1000*60*60*24*7>
<#assign count=0>
<#list workflow.assignedTasks?sort_by('startDate') as t>
<#-- TODO: is it better to use a js script to pre-filter the list? -->
<#assign hasDue=t.properties["bpm:dueDate"]?exists>
<#if hasDue>
<#assign due=t.properties["bpm:dueDate"]>
</#if>
<#-- filters: 0=all, 1=today, 2=next week, 3=no due date, 4=overdue -->
<#if (args.f="0") ||
(args.f="3" && !hasDue) ||
(args.f="1" && hasDue && (dateCompare(date?date, due?date, 0, "==") == 1)) ||
(args.f="2" && hasDue && (dateCompare(due?date, date?date) == 1 && dateCompare(date?date, due?date, weekms) == 1)) ||
(args.f="4" && hasDue && (dateCompare(date?date, due?date) == 1))>
<#assign count=count+1>
<div class="taskRow" id="${t.id}">
<div class="taskTitle">
<div class="taskIndicator">
<#if hasDue>
<#-- items due today? -->
<#if (args.f="0" || args.f="1") && (dateCompare(date?date, due?date, 0, "==") == 1)>
<img src="${url.context}/images/icons/task_today.gif"></div><div class="taskItem taskItemToday">
<#-- items overdue? -->
<#elseif (args.f="0" || args.f="4") && (dateCompare(date?date, due?date) == 1)>
<img src="${url.context}/images/icons/task_overdue.gif"></div><div class="taskItem taskItemOverdue">
<#else>
</div><div class="taskItem">
</#if>
<#else>
</div><div class="taskItem">
</#if>
${t.description?html} (${t.type?html})
<#if hasDue>
(Due: ${due?date})
</#if>
<span class="taskInfo" onclick="event.cancelBubble=true; TaskInfoMgr.toggle('${t.id}',this);">
<img src="${url.context}/images/icons/popup.gif" class="popupImage" width="16" height="16" />
</span>
</div>
</div>
<div class="taskDetail">
<div style="float:left">
<table cellpadding='2' cellspacing='0' style="margin-left:32px;margin-top:16px">
<tr><td class="taskMetaprop">Status:</td><td class="taskMetadata">${t.properties["bpm:status"]}</td>
<tr><td class="taskMetaprop">Priority:</td><td class="taskMetadata">${t.properties["bpm:priority"]}</td>
<tr><td class="taskMetaprop">Start Date:</td><td class="taskMetadata">${t.startDate?date}</td></tr>
<tr><td class="taskMetaprop">Type:</td><td class="taskMetadata">${t.type?html}</td></tr>
<tr><td class="taskMetaprop">Complete:</td><td class="taskMetadata">${t.properties["bpm:percentComplete"]}%</td>
</table>
</div>
<div class="taskResourceHeader">${t.name?html}:</div>
<div class="taskResources"></div>
<div>
<table class="taskActions" style="padding-left:16px">
<tr>
<#list t.transitions as wt>
<td><a class="taskAction" href="#" onclick="event.cancelBubble=true; MyTasks.transitionTask('/command/task/end/${t.id}<#if wt.id?exists>/${wt.id}</#if>', 'Workflow action \'${wt.label?html}\' completed.');">${wt.label?html}</a></td>
</#list>
</tr>
</table>
</div>
</div>
</div>
</#if>
</#list>
<#-- hidden div with the count value for the page -->
<div id="taskCountValue" style="display:none">${count}</div>

View File

@@ -19,7 +19,7 @@ var MySpaces = {
// is responsible for rendering just the contents of the main panel div
YAHOO.util.Connect.asyncRequest(
"GET",
getContextPath() + '/service/myspacespanel?p='+MySpaces.Path+'&f='+MySpaces.Filter+'&h='+MySpaces.Home, //+'&_='+(Math.random())
getContextPath() + '/service/myspacespanel?p='+MySpaces.Path+'&f='+MySpaces.Filter+'&h='+MySpaces.Home,
{
success: function(response)
{
@@ -32,7 +32,7 @@ var MySpaces = {
},
failure: function(response)
{
$('spacePanel').setHTML("Sorry, list data currently unavailable.");
$('spacePanel').setHTML("Sorry, data currently unavailable.");
}
}
);

View File

@@ -1,15 +1,44 @@
var MyTasks = {
ANIM_LENGTH: 300,
DETAIL_PANEL_HEIGHT: 132,
Filter: null,
start: function()
{
if ($('taskPanel'))
{
MyTasks.parseTaskPanels();
// fire off the ajax request to populate the task panel - the 'mytaskspanel' webscript
// is responsible for rendering just the contents of the main panel div
YAHOO.util.Connect.asyncRequest(
"GET",
getContextPath() + '/service/mytaskspanel?f='+MyTasks.Filter,
{
success: function(response)
{
// push the response into the task panel div
$('taskPanel').setHTML(response.responseText);
// extract the count value from a hidden div and display it
$('taskCount').setHTML($('taskCountValue').innerHTML);
// wire up all the events and animations
MyTasks.init();
},
failure: function(response)
{
$('taskPanel').setHTML("Sorry, data currently unavailable.");
}
}
);
}
},
init: function()
{
MyTasks.parseTaskPanels();
// hide the ajax wait panel and show the main task panel
$('taskPanelOverlay').setStyle('visibility', 'hidden');
$('taskPanel').setStyle('visibility', 'visible');
},
parseTaskPanels: function()
{
var tasks = $$('#taskPanel .taskRow');
@@ -237,21 +266,20 @@ var MyTasks = {
});
},
transitionTask: function(tUrl, rUrl, successMessage)
transitionTask: function(commandUrl, successMessage)
{
YAHOO.util.Connect.asyncRequest(
"GET",
getContextPath() + tUrl,
getContextPath() + commandUrl,
{
success: function(response)
{
window.location.href = rUrl + "&_rand=" + Math.floor(Math.random()*99999) +
"&" + "m=" + successMessage;
MyTasks.displayMessage(successMessage);
MyTasks.refreshList();
},
failure: function(e)
{
alert(e.status + " : ERROR failed to transition task.");
window.location.href = rUrl + "&_rand=" + Math.floor(Math.random()*99999);
}
}
);
@@ -260,7 +288,26 @@ var MyTasks = {
displayMessage: function(message)
{
var footer = $('taskFooter');
footer.innerHTML = message + ' ' + footer.innerHTML
if (footer.oldMessage == undefined)
{
footer.oldMessage = footer.innerHTML;
}
footer.innerHTML = message + ' ' + footer.oldMessage;
},
/**
* Refresh the main data list contents within the taskPanel container
*/
refreshList: function()
{
// empty the main panel div and restart by reloading the panel contents
var taskPanel = $('taskPanel');
taskPanel.setStyle('visibility', 'hidden');
// show the ajax wait panel
$('taskPanelOverlay').setStyle('visibility', 'visible');
taskPanel.empty();
taskPanel.removeEvents('mouseleave');
MyTasks.start();
}
};