Merged BRANCHES/DEV/ADMIN51 to HEAD (5.1)

108655: Fixes for Unlock action to handle cancel checkout case
   108608: Unlock action
   108588: Admin Console actions; Delete Node, Delete Property, Take Ownership, Revert Permissions.
   108583: Branch for admin console changes

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@109513 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2015-08-04 10:28:34 +00:00
parent 8cde3e29eb
commit abeb7991bc
4 changed files with 237 additions and 16 deletions

View File

@@ -40,13 +40,13 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<div class="column-full"> <div class="column-full">
<@section label=msg("nodebrowser.store") /> <@section label=msg("nodebrowser.store") />
<@options name="nodebrowser-store" style="display:inline" valueStyle="display:inline" onchange="AdminConsole_execute('root')" value="${args.store!'workspace://SpacesStore'}"> <@options name="nodebrowser-store" style="display:inline" valueStyle="display:inline" onchange="AdminConsole_action('root')" value="${args.store!'workspace://SpacesStore'}">
<#list stores as s> <#list stores as s>
<@option label=s value=s /> <@option label=s value=s />
</#list> </#list>
</@options> </@options>
<@button label=msg("nodebrowser.root") onclick="AdminConsole_execute('root')" /> <@button label=msg("nodebrowser.root") onclick="AdminConsole_action('root')" />
<#if action??><@button label=msg("nodebrowser.refresh") onclick="AdminConsole_execute('${action?html}')" class="input" style="position:absolute;top:60px;left:1042px" /></#if> <#if action??><@button label=msg("nodebrowser.refresh") onclick="AdminConsole_action('${action?html}')" class="input" style="position:absolute;top:60px;left:1042px" /></#if>
<@section label=msg("nodebrowser.query") /> <@section label=msg("nodebrowser.query") />
<@options name="nodebrowser-search" style="display:inline" valueStyle="display:inline" value="${args.searcher!''}"> <@options name="nodebrowser-search" style="display:inline" valueStyle="display:inline" value="${args.searcher!''}">
@@ -61,7 +61,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<@option label="db-cmis" value="db-cmis" /> <@option label="db-cmis" value="db-cmis" />
</@options> </@options>
<@text id="query" name="nodebrowser-query" label="" value="${query!''}" style="display:inline" valueStyle="display:inline" controlStyle="width:50em" /> <@text id="query" name="nodebrowser-query" label="" value="${query!''}" style="display:inline" valueStyle="display:inline" controlStyle="width:50em" />
<@button label=msg("nodebrowser.execute") onclick="AdminConsole_execute('search')" /> <@button label=msg("nodebrowser.execute") onclick="AdminConsole_action('search')" />
<@tsection label=msg("nodebrowser.search-settings")> <@tsection label=msg("nodebrowser.search-settings")>
<div class="column-left"> <div class="column-left">
<@text name="nodebrowser-query-maxresults" label=msg("nodebrowser.maxresults") value="${args.maxResults!''}" /> <@text name="nodebrowser-query-maxresults" label=msg("nodebrowser.maxresults") value="${args.maxResults!''}" />
@@ -74,6 +74,8 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<!-- hidden values set by button and key events to provide action ID to the Form POST --> <!-- hidden values set by button and key events to provide action ID to the Form POST -->
<@hidden name="nodebrowser-action" id="action" /> <@hidden name="nodebrowser-action" id="action" />
<@hidden name="nodebrowser-action-value" id="action-value" value="${actionValue!''}" /> <@hidden name="nodebrowser-action-value" id="action-value" value="${actionValue!''}" />
<@hidden name="nodebrowser-execute" id="execute" />
<@hidden name="nodebrowser-execute-value" id="execute-value" />
</div> </div>
<#if result??> <#if result??>
@@ -101,6 +103,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<th>${msg("nodebrowser.type")}</th> <th>${msg("nodebrowser.type")}</th>
<th>${msg("nodebrowser.value")}</th> <th>${msg("nodebrowser.value")}</th>
<th>${msg("nodebrowser.residual")}</th> <th>${msg("nodebrowser.residual")}</th>
<th>${msg("nodebrowser.actions")}</th>
</tr> </tr>
<#list result.properties as p> <#list result.properties as p>
<tr> <tr>
@@ -108,6 +111,9 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<td><#if p.typeName??>${p.typeName.prefixedName}<#else>${none}</#if></td> <td><#if p.typeName??>${p.typeName.prefixedName}<#else>${none}</#if></td>
<td><#if (p.values?size > 1)><span style="color:red">${collection} (${p.values?size?c})</span><br></#if><#list p.values as v><#if v.content><a target="new" href="<@contentUrl result.info.nodeRef p.name.prefixedName/>"></#if><@propValue v/><#if v.content></a></#if><#if v_has_next><br></#if></#list></td> <td><#if (p.values?size > 1)><span style="color:red">${collection} (${p.values?size?c})</span><br></#if><#list p.values as v><#if v.content><a target="new" href="<@contentUrl result.info.nodeRef p.name.prefixedName/>"></#if><@propValue v/><#if v.content></a></#if><#if v_has_next><br></#if></#list></td>
<td>${p.residual?string}</td> <td>${p.residual?string}</td>
<td>
<b><a href="#" onclick="AdminConsole_confirmExecute('${result.info.nodeRef}|${p.name}','delete-property');return false;" title="${msg("nodebrowser.delete-property.tip")}">${msg("nodebrowser.delete")}</a></b>
</td>
</tr> </tr>
</#list> </#list>
</table> </table>
@@ -136,6 +142,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<th>${msg("nodebrowser.primary")}</th> <th>${msg("nodebrowser.primary")}</th>
<th>${msg("nodebrowser.association-type")}</th> <th>${msg("nodebrowser.association-type")}</th>
<th>${msg("nodebrowser.index")}</th> <th>${msg("nodebrowser.index")}</th>
<th>${msg("nodebrowser.actions")}</th>
</tr> </tr>
<#list result.children as n> <#list result.children as n>
<tr> <tr>
@@ -144,6 +151,16 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
<td>${n.primary?string}</td> <td>${n.primary?string}</td>
<td>${n.typeQName}</td> <td>${n.typeQName}</td>
<td>${n_index}</td> <td>${n_index}</td>
<#assign isarchive=(args.store!"")?starts_with("archive://")>
<td>
<b><a href="#" onclick="AdminConsole_execute('${n.childRef}','delete');return false;" title="${msg("nodebrowser.delete.tip")}">${msg("nodebrowser.delete")}</a></b>
<#if isarchive>| <b><a href="#" onclick="AdminConsole_execute('${n.childRef}','restore');return false;" title="${msg("nodebrowser.restore.tip")}">${msg("nodebrowser.restore")}</a></b>
<#else>| <b><a href="#" onclick="AdminConsole_confirmExecute('${n.childRef}','fdelete');return false;" title="${msg("nodebrowser.force-delete.tip")}">${msg("nodebrowser.force-delete")}</a></b>
| <b><a href="#" onclick="AdminConsole_execute('${n.childRef}','take-ownership');return false;" title="${msg("nodebrowser.take-ownership.tip")}">${msg("nodebrowser.take-ownership")}</a></b>
| <b><a href="#" onclick="AdminConsole_execute('${n.childRef}','delete-permissions');return false;" title="${msg("nodebrowser.delete-permissions.tip")}">${msg("nodebrowser.delete-permissions")}</a></b>
<#if n.childLocked>| <b><a href="#" onclick="AdminConsole_execute('${n.childRef}','unlock');return false;" title="${msg("nodebrowser.unlock.tip")}">${msg("nodebrowser.unlock")}</a></b></#if>
</#if>
</td>
</tr> </tr>
</#list> </#list>
</table> </table>
@@ -250,16 +267,16 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
Admin.addEventListener(window, 'load', function() { Admin.addEventListener(window, 'load', function() {
// bind Enter key press to call the Execute search button event handler // bind Enter key press to call the Execute search button event handler
Admin.addEventListener(el("query"), 'keypress', function(e) { Admin.addEventListener(el("query"), 'keypress', function(e) {
if (e.keyCode === 13) AdminConsole_execute('search'); if (e.keyCode === 13) AdminConsole_action('search');
return true; return true;
}); });
<#if args.nodeRef??> <#if args.nodeRef??>
AdminConsole_execute('search'); AdminConsole_action('search');
</#if> </#if>
}); });
function AdminConsole_execute(action) function AdminConsole_action(action)
{ {
el("action").value = action; el("action").value = action;
el("${FORM_ID}").submit(); el("${FORM_ID}").submit();
@@ -269,13 +286,28 @@ function AdminConsole_execute(action)
function AdminConsole_childClick(ref) function AdminConsole_childClick(ref)
{ {
el("action-value").value = ref; el("action-value").value = ref;
AdminConsole_execute("children"); AdminConsole_action("children");
} }
function AdminConsole_parentClick(ref) function AdminConsole_parentClick(ref)
{ {
el("action-value").value = ref; el("action-value").value = ref;
AdminConsole_execute("parent"); AdminConsole_action("parent");
}
function AdminConsole_execute(value, execute)
{
el("execute-value").value = value;
el("execute").value = execute;
AdminConsole_action('${(action!"")?html}');
}
function AdminConsole_confirmExecute(value, execute)
{
if (confirm("${msg("nodebrowser.confirm")}"))
{
AdminConsole_execute(value, execute);
}
} }
//]]></script> //]]></script>

View File

@@ -40,4 +40,25 @@ nodebrowser.permission=Permission
nodebrowser.authority=Authority nodebrowser.authority=Authority
nodebrowser.access=Access nodebrowser.access=Access
nodebrowser.inherits=Inherits nodebrowser.inherits=Inherits
nodebrowser.owner=Owner nodebrowser.owner=Owner
nodebrowser.actions=Actions
nodebrowser.delete=Delete
nodebrowser.delete.tip=Delete the node and any children.
nodebrowser.force-delete=Force Delete
nodebrowser.force-delete.tip=Delete the node and any children. The node will not be archived. Rules will not be run.
nodebrowser.restore=Restore
nodebrowser.restore.tip=Restore the node and any children to its original location.
nodebrowser.delete-property.tip=Delete the property from this node.
nodebrowser.take-ownership=Take Ownership
nodebrowser.take-ownership.tip=Take owner permission of the node.
nodebrowser.delete-permissions=Revert Permissions
nodebrowser.delete-permissions.tip=Delete all permissions that have been explicitly assigned to this node and restore permission inheritance.
nodebrowser.unlock=Unlock
nodebrowser.unlock.tip=Remove any locks held by this node. Cancels the checkout for any associated working copy and the working copy is removed. Note that all modifications made to the working copy will be lost.
nodebrowser.confirm=Are you sure?
nodebrowser.message.delete=Successfully deleted node.
nodebrowser.message.restore=Successfully restored node.
nodebrowser.message.take-ownership=Successfully took ownership.
nodebrowser.message.delete-permissions=Successfully removed permissions.
nodebrowser.message.delete-property=Successfully deleted property.
nodebrowser.message.unlock=Successfully unlocked node.

View File

@@ -1807,12 +1807,15 @@
<bean id="webscript.org.alfresco.repository.admin.support-tools.admin-nodebrowser.post" <bean id="webscript.org.alfresco.repository.admin.support-tools.admin-nodebrowser.post"
class="org.alfresco.repo.web.scripts.admin.NodeBrowserPost" class="org.alfresco.repo.web.scripts.admin.NodeBrowserPost"
parent="webscript"> parent="webscript">
<property name="nodeService" ref="NodeService"/> <property name="nodeService" ref="NodeService" />
<property name="dictionaryService" ref="DictionaryService"/> <property name="dictionaryService" ref="DictionaryService" />
<property name="searchService" ref="SearchService"/> <property name="searchService" ref="SearchService" />
<property name="namespaceService" ref="NamespaceService"/> <property name="namespaceService" ref="NamespaceService" />
<property name="permissionService" ref="PermissionService"/> <property name="permissionService" ref="PermissionService" />
<property name="ownableService" ref="OwnableService" /> <property name="ownableService" ref="OwnableService" />
<property name="transactionService" ref="transactionService" />
<property name="lockService" ref="LockService" />
<property name="checkOutCheckInService" ref="CheckoutCheckinService" />
</bean> </bean>
<!-- Repository Admin Console script extensions --> <!-- Repository Admin Console script extensions -->

View File

@@ -32,9 +32,13 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -85,6 +89,8 @@ public class NodeBrowserPost extends DeclarativeWebScript implements Serializabl
transient private NamespaceService namespaceService; transient private NamespaceService namespaceService;
transient private PermissionService permissionService; transient private PermissionService permissionService;
transient private OwnableService ownableService; transient private OwnableService ownableService;
transient private LockService lockService;
transient private CheckOutCheckInService cociService;
/** /**
* @param transactionService transaction service * @param transactionService transaction service
@@ -173,6 +179,26 @@ public class NodeBrowserPost extends DeclarativeWebScript implements Serializabl
{ {
return ownableService; return ownableService;
} }
public void setLockService(LockService lockService)
{
this.lockService = lockService;
}
protected LockService getLockService()
{
return this.lockService;
}
public void setCheckOutCheckInService(CheckOutCheckInService cociService)
{
this.cociService = cociService;
}
protected CheckOutCheckInService getCheckOutCheckInService()
{
return this.cociService;
}
/** /**
* Gets the list of repository stores * Gets the list of repository stores
@@ -425,8 +451,141 @@ public class NodeBrowserPost extends DeclarativeWebScript implements Serializabl
long timeStart = System.currentTimeMillis(); long timeStart = System.currentTimeMillis();
String actionValue = req.getParameter("nodebrowser-action-value"); String actionValue = req.getParameter("nodebrowser-action-value");
String action = req.getParameter("nodebrowser-action"); String action = req.getParameter("nodebrowser-action");
final String execute = req.getParameter("nodebrowser-execute");
final String executeValue = req.getParameter("nodebrowser-execute-value");
String message = null;
try try
{ {
// 'execute' is an action that performs an operation on a node e.g. delete
// the 'executeValue' param provides context
// this is done before the view action to ensure node state is correct
if (execute != null)
{
switch (execute)
{
case "delete":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
// delete the node using the standard NodeService
nodeService.deleteNode(new NodeRef(executeValue));
return null;
}
}, false, true);
message = "nodebrowser.message.delete";
break;
}
case "fdelete":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
// delete the node - but ensure that it is not archived
NodeRef ref = new NodeRef(executeValue);
nodeService.addAspect(ref, ContentModel.ASPECT_TEMPORARY, null);
nodeService.deleteNode(ref);
return null;
}
}, false, true);
message = "nodebrowser.message.delete";
break;
}
case "restore":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
nodeService.restoreNode(new NodeRef(executeValue), null, null, null);
return null;
}
}, false, true);
message = "nodebrowser.message.restore";
break;
}
case "take-ownership":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
ownableService.takeOwnership(new NodeRef(executeValue));
return null;
}
}, false, true);
message = "nodebrowser.message.take-ownership";
break;
}
case "delete-permissions":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
NodeRef ref = new NodeRef(executeValue);
permissionService.deletePermissions(ref);
permissionService.setInheritParentPermissions(ref, true);
return null;
}
}, false, true);
message = "nodebrowser.message.delete-permissions";
break;
}
case "delete-property":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
// argument value contains "NodeRef|QName" packed string
String[] parts = executeValue.split("\\|");
nodeService.removeProperty(new NodeRef(parts[0]), QName.createQName(parts[1]));
return null;
}
}, false, true);
message = "nodebrowser.message.delete-property";
break;
}
case "unlock":
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
NodeRef ref = new NodeRef(executeValue);
if (cociService.isCheckedOut(ref))
{
NodeRef wcRef = cociService.getWorkingCopy(ref);
if (wcRef != null)
{
cociService.cancelCheckout(wcRef);
}
}
else
{
lockService.unlock(ref);
}
return null;
}
}, false, true);
message = "nodebrowser.message.unlock";
break;
}
}
}
// 'action' is a view action that request an update of the admin console view state e.g. 'search' or 'children'
// the 'actionValue' param provides context as may other parameters such as 'query'
switch (action) switch (action)
{ {
// on Execute btn press and query present, perform search // on Execute btn press and query present, perform search
@@ -580,13 +739,14 @@ public class NodeBrowserPost extends DeclarativeWebScript implements Serializabl
returnParams.put("skipCount", skipCount); returnParams.put("skipCount", skipCount);
returnParams.put("in", Long.toString(System.currentTimeMillis()-timeStart)); returnParams.put("in", Long.toString(System.currentTimeMillis()-timeStart));
returnParams.put("e", error); returnParams.put("e", error);
returnParams.put("m", message);
// redirect as all admin console pages do (follow standard pattern) // redirect as all admin console pages do (follow standard pattern)
// The logic to generate the navigation section and server meta-data is all tied into alfresco-common.lib.js // The logic to generate the navigation section and server meta-data is all tied into alfresco-common.lib.js
// which is great for writing JS based JMX surfaced pages, but not so great for Java backed WebScripts. // which is great for writing JS based JMX surfaced pages, but not so great for Java backed WebScripts.
status.setCode(301); status.setCode(301);
status.setRedirect(true); status.setRedirect(true);
status.setLocation(buildUrl(req, returnParams, action)); status.setLocation(buildUrl(req, returnParams, execute != null && execute.length() != 0 ? execute : action));
return null; return null;
} }
@@ -884,6 +1044,11 @@ public class NodeBrowserPost extends DeclarativeWebScript implements Serializabl
{ {
return ref.isPrimary(); return ref.isPrimary();
} }
public boolean isChildLocked()
{
return lockService != null && lockService.getLockType(ref.getChildRef()) != null;
}
} }
/** /**