From cc6af1a45cb3cbb3dbe25d2aef8b631453b5df5a Mon Sep 17 00:00:00 2001 From: Britt Park Date: Sat, 2 Sep 2006 18:19:00 +0000 Subject: [PATCH] Merge from HEAD to WCM-DEV2. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3659 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 79 ++- config/alfresco/templates/checkedout_docs.ftl | 25 + config/alfresco/templates/doc_info.ftl | 31 +- config/alfresco/templates/example.ftl | 47 -- .../alfresco/templates/image_thumbnails.ftl | 12 + config/alfresco/templates/my_docs.ftl | 12 +- config/alfresco/templates/my_images.ftl | 12 + .../alfresco/templates/templates_readme.txt | 10 + .../web-client-application-context.xml | 1 + config/alfresco/web-client-config-actions.xml | 8 +- config/alfresco/web-client-config-dialogs.xml | 26 +- .../web-client-config-forum-actions.xml | 2 +- .../alfresco/web-client-config-properties.xml | 75 ++ config/alfresco/web-client-config-wizards.xml | 26 + .../web-client-config-workflow-actions.xml | 114 +++ config/alfresco/web-client-config.xml | 36 +- .../web/app/AlfrescoNavigationHandler.java | 124 +++- .../web/app/AlfrescoVariableResolver.java | 143 ++++ .../web/app/portlet/AlfrescoFacesPortlet.java | 16 +- .../alfresco/web/app/servlet/BaseServlet.java | 10 +- .../web/bean/CheckinCheckoutBean.java | 107 ++- .../java/org/alfresco/web/bean/LoginBean.java | 15 +- .../org/alfresco/web/bean/NavigationBean.java | 37 +- .../web/bean/UserPreferencesBean.java | 66 ++ .../bean/actions/handlers/ScriptHandler.java | 8 +- .../web/bean/clipboard/ClipboardBean.java | 38 +- .../web/bean/content/CreateContentWizard.java | 103 +-- .../content/ViewContentPropertiesDialog.java | 75 ++ .../web/bean/dashboard/DashboardWizard.java | 8 + .../bean/dashboard/GettingStartedBean.java | 70 ++ .../web/bean/dialog/BaseDialogBean.java | 15 + .../web/bean/dialog/DialogManager.java | 121 ++-- .../alfresco/web/bean/dialog/DialogState.java | 53 ++ .../alfresco/web/bean/dialog/IDialogBean.java | 23 + .../generator/HeaderSeparatorGenerator.java | 1 - .../generator/HtmlSeparatorGenerator.java | 79 +++ .../generator/LabelSeparatorGenerator.java | 85 +++ .../bean/generator/SeparatorGenerator.java | 43 +- .../web/bean/repository/TransientNode.java | 66 +- .../web/bean/users/EmailSpaceUsersDialog.java | 250 ++++--- .../web/bean/wizard/WizardManager.java | 194 +++-- .../alfresco/web/bean/wizard/WizardState.java | 113 +++ .../web/bean/workflow/ManageTaskDialog.java | 667 ++++++++++++++++++ .../bean/workflow/ManageWorkItemDialog.java | 476 ------------- .../web/bean/workflow/ReassignTaskDialog.java | 199 ++++++ .../bean/workflow/StartWorkflowWizard.java | 248 ++++++- .../workflow/ViewCompletedTaskDialog.java | 48 ++ .../web/bean/workflow/WorkflowBean.java | 47 +- .../web/config/ClientConfigElement.java | 2 +- .../web/config/DashboardsConfigElement.java | 16 + .../web/config/DashboardsElementReader.java | 8 + .../ui/repo/component/UIContentSelector.java | 401 +++++++++++ .../ui/repo/component/UIWorkflowSummary.java | 163 +++++ .../web/ui/repo/tag/ContentSelectorTag.java | 113 +++ .../web/ui/repo/tag/WorkflowSummaryTag.java | 77 ++ .../property/BaseAssociationEditorTag.java | 11 + source/web/WEB-INF/faces-config-app.xml | 2 +- source/web/WEB-INF/faces-config-beans.xml | 263 +++++-- .../web/WEB-INF/faces-config-navigation.xml | 46 +- source/web/WEB-INF/faces-config-repo.xml | 9 + source/web/WEB-INF/repo.tld | 120 +++- source/web/WEB-INF/web.xml | 77 +- source/web/css/main.css | 11 + source/web/images/filetypes/tif.gif | Bin 0 -> 129 bytes source/web/images/filetypes/tiff.gif | Bin 0 -> 129 bytes source/web/images/filetypes32/tif.gif | Bin 0 -> 407 bytes source/web/images/filetypes32/tiff.gif | Bin 0 -> 407 bytes .../images/icons/completed_workflow_task.gif | Bin 0 -> 606 bytes .../icons/completed_workflow_task_large.gif | Bin 0 -> 1633 bytes .../images/icons/gettingstarted_browse.gif | Bin 0 -> 1418 bytes .../icons/gettingstarted_demonstration.gif | Bin 0 -> 4544 bytes .../icons/gettingstarted_featuretour.gif | Bin 0 -> 4544 bytes .../icons/gettingstarted_onlinehelp.gif | Bin 0 -> 1024 bytes .../icons/manage_workflow_task_large.gif | Bin 0 -> 1592 bytes source/web/images/icons/reassign_task.gif | Bin 0 -> 1032 bytes .../icons/reassign_workflow_task_large.gif | Bin 0 -> 1648 bytes source/web/images/icons/workflow_task.gif | Bin 0 -> 595 bytes .../web/images/icons/workflow_task_large.gif | Bin 0 -> 1540 bytes source/web/index.jsp | 70 +- source/web/jsp/admin/admin-console.jsp | 6 + .../jsp/content/view-content-properties.jsp | 24 + source/web/jsp/dashboards/container-light.jsp | 54 ++ source/web/jsp/dashboards/container.jsp | 2 +- .../dashboards/dashlets/checkedout-docs.jsp | 20 + .../dashboards/dashlets/getting-started.jsp | 102 ++- .../web/jsp/dashboards/dashlets/my-docs.jsp | 4 +- .../web/jsp/dashboards/dashlets/my-images.jsp | 20 + source/web/jsp/dialog/about.jsp | 4 +- source/web/jsp/dialog/checkout-file.jsp | 2 +- source/web/jsp/dialog/edit-html-inline.jsp | 2 +- source/web/jsp/dialog/edit-text-inline.jsp | 2 +- source/web/jsp/dialog/undocheckout-file.jsp | 2 +- source/web/jsp/users/email-space-users.jsp | 17 +- source/web/jsp/users/user-console.jsp | 19 +- .../web/jsp/workflow/manage-task-dialog.jsp | 132 ++++ .../web/jsp/workflow/reassign-task-dialog.jsp | 40 ++ .../workflow-options.jsp | 84 +++ .../jsp/workflow/tasks-completed-dashlet.jsp | 72 ++ .../web/jsp/workflow/tasks-todo-dashlet.jsp | 80 +++ .../workflow/view-completed-task-dialog.jsp | 98 +++ 100 files changed, 4941 insertions(+), 1298 deletions(-) create mode 100644 config/alfresco/templates/checkedout_docs.ftl delete mode 100644 config/alfresco/templates/example.ftl create mode 100644 config/alfresco/templates/image_thumbnails.ftl create mode 100644 config/alfresco/templates/my_images.ftl create mode 100644 config/alfresco/templates/templates_readme.txt create mode 100644 config/alfresco/web-client-config-workflow-actions.xml create mode 100644 source/java/org/alfresco/web/app/AlfrescoVariableResolver.java create mode 100644 source/java/org/alfresco/web/bean/UserPreferencesBean.java create mode 100644 source/java/org/alfresco/web/bean/content/ViewContentPropertiesDialog.java create mode 100644 source/java/org/alfresco/web/bean/dashboard/GettingStartedBean.java create mode 100644 source/java/org/alfresco/web/bean/dialog/DialogState.java create mode 100644 source/java/org/alfresco/web/bean/generator/HtmlSeparatorGenerator.java create mode 100644 source/java/org/alfresco/web/bean/generator/LabelSeparatorGenerator.java create mode 100644 source/java/org/alfresco/web/bean/wizard/WizardState.java create mode 100644 source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java delete mode 100644 source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java create mode 100644 source/java/org/alfresco/web/bean/workflow/ReassignTaskDialog.java create mode 100644 source/java/org/alfresco/web/bean/workflow/ViewCompletedTaskDialog.java create mode 100644 source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java create mode 100644 source/java/org/alfresco/web/ui/repo/component/UIWorkflowSummary.java create mode 100644 source/java/org/alfresco/web/ui/repo/tag/ContentSelectorTag.java create mode 100644 source/java/org/alfresco/web/ui/repo/tag/WorkflowSummaryTag.java create mode 100644 source/web/images/filetypes/tif.gif create mode 100644 source/web/images/filetypes/tiff.gif create mode 100644 source/web/images/filetypes32/tif.gif create mode 100644 source/web/images/filetypes32/tiff.gif create mode 100644 source/web/images/icons/completed_workflow_task.gif create mode 100644 source/web/images/icons/completed_workflow_task_large.gif create mode 100644 source/web/images/icons/gettingstarted_browse.gif create mode 100644 source/web/images/icons/gettingstarted_demonstration.gif create mode 100644 source/web/images/icons/gettingstarted_featuretour.gif create mode 100644 source/web/images/icons/gettingstarted_onlinehelp.gif create mode 100644 source/web/images/icons/manage_workflow_task_large.gif create mode 100644 source/web/images/icons/reassign_task.gif create mode 100644 source/web/images/icons/reassign_workflow_task_large.gif create mode 100644 source/web/images/icons/workflow_task.gif create mode 100644 source/web/images/icons/workflow_task_large.gif create mode 100644 source/web/jsp/content/view-content-properties.jsp create mode 100644 source/web/jsp/dashboards/container-light.jsp create mode 100644 source/web/jsp/dashboards/dashlets/checkedout-docs.jsp create mode 100644 source/web/jsp/dashboards/dashlets/my-images.jsp create mode 100644 source/web/jsp/workflow/manage-task-dialog.jsp create mode 100644 source/web/jsp/workflow/reassign-task-dialog.jsp create mode 100644 source/web/jsp/workflow/tasks-completed-dashlet.jsp create mode 100644 source/web/jsp/workflow/tasks-todo-dashlet.jsp create mode 100644 source/web/jsp/workflow/view-completed-task-dialog.jsp diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 55f375ace1..6266c85a09 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -28,6 +28,7 @@ modify_user_roles_description=Modify the permissions granted to a user for acces modify_content_user_roles_description=Modify the permissions granted to a user for accessing your content. advancedsearch_description=Perform a more detailed search of the repository. edit_content_description=Modify the content properties then click OK. +view_content_description=View the content properties. editcategory_description=Set the category for the document then click OK. editcategory_space_description=Set the category for the space then click OK. editworkflow_description=Modify the simple workflow properties then click OK. @@ -232,7 +233,6 @@ remove_user=Remove User create_space=Create Space add_content=Add Content create_content=Create Content -create_xml_content_type=Create XML Content Type add_multiple_files=Add Multiple Files import_directory=Import Directory advanced_space_wizard=Advanced Space Wizard @@ -514,6 +514,7 @@ preview_of=Preview of modify_props_of=Modify Properties of modify_space_properties=Modify Space Properties modify_content_properties=Modify Content Properties +view_content_properties=View Content Properties preview=Preview in Template custom_view=Custom View view_links=Links @@ -586,13 +587,6 @@ checkout_warn=Note: You will lose any changes already made to this document. local_copy_location=Local copy location locate_content_upload=Locate and upload your document to the repository. -# Edit Workflow messages -modify_workflow_props=Modify Properties of Simple Workflow -name_approve_step=Name for approve step -name_reject_step=Name for reject step -select_reject_step=Do you want to provide a reject step? -choose_copy_move_location=Choose whether you want to move or copy the content and also the location. - # System Information and admin page messages system_info=System Information current_user=Current User @@ -630,7 +624,6 @@ modify_props_when_wizard_closes=Modify all properties when this wizard closes. modify_props_help_text=Rules applied to this content may require you to enter additional information. content_finish_instruction=To add the content to this space click Finish. To review or change your selections click Back. create_content_title=Create Content Wizard -create_xml_content_type_title=Create XML Content Type Wizard create_content_desc=This wizard helps you to create a new document in a space. create_content_step1_title=Step One - Specify name and select type create_content_step1_desc=Specify the name and select the type of content you wish to create. @@ -641,15 +634,6 @@ select_type=Select Type content=Content text_content=Plain Text Content html_content=HTML Content -xml_content=XML Content -create_xml_content_type_desc=Create XML Content Type -create_xml_content_type_step1_title=Upload an XML Schema -create_xml_content_type_step1_desc=Upload an XML Schema -create_xml_content_type_step2_title=Edit the XML Schema -create_xml_content_type_step2_desc=This is the generated XForm based on the schema provided. -edit_xml_schema=Edit XML Schema -template_type=Template Type -configure_presentation_templates=Configure Presentation Templates # Rule and Action Wizard messages run_action_title=Run Action Wizard @@ -912,6 +896,27 @@ layout_three_column_desc=This layout displays components across three columns of # My Alfresco Dashlet components messages dashlet_gettingstarted_label=Getting Started dashlet_gettingstarted_desc=Displays helpful information for getting started with the Alfresco web-client +dashlet_mydocuments=My Documents +dashlet_mydocuments_desc=Displays a list of the documents in my home space +dashlet_checkedoutdocs=My Checked Out Documents +dashlet_checkedoutdocs_desc=Displays a list of the documents checked out to me +dashlet_myimages=My Images +dashlet_myimages_desc=Displays a 3 column thumbnail list of the images in my home space +gettingstarted_commontasks=Common Tasks +gettingstarted_browse=Browse items in your home space +gettingstarted_browse_desc=From the toolbar click My Home to display a list of items in the space. +gettingstarted_createspace=Create a space in your home space +gettingstarted_createspace_desc=Navigate to your home space. In the space info area, from the menu under Create, click Create Space and enter information about the space. +gettingstarted_addcontent=Add content to your home space +gettingstarted_addcontent_desc=Navigate to your home space. In the space info area, click Add Content and enter information about the content to be uploaded. +gettingstarted_createcontent=Create content in your home space +gettingstarted_createcontent_desc=Navigate to your home space. In the space info area, click Create Content under Create and enter information about the content to be created. +gettingstarted_demonstration=Demonstration +gettingstarted_demonstration_desc=Watch a demonstration of how Alfresco can be used to create a marketing launch. +gettingstarted_featuretour=Feature Tour +gettingstarted_featuretour_desc=Take a tour of some of the key features in Alfresco. +gettingstarted_onlinehelp=Online Help +gettingstarted_onlinehelp_desc=Click the help icon to display Alfresco Help topics. # User Console and Settings messages title_user_console=User Options @@ -927,6 +932,7 @@ old_password=Old Password new_password=New Password edit_user_details=Edit User Details edit_user_details_description=Use this view to change your user details and email address +start_location=Start Location # Delete Space Dialog messages select_delete_operation=What do you want to delete? @@ -940,6 +946,11 @@ email_space_users=Email Space users email_space_users_desc=Send an email to the users and groups assigned to this space. # Workflow messages +modify_workflow_props=Modify Properties of Simple Workflow +name_approve_step=Name for approve step +name_reject_step=Name for reject step +select_reject_step=Do you want to provide a reject step? +choose_copy_move_location=Choose whether you want to move or copy the content and also the location. start_workflow=Start Workflow start_workflow_wizard=Start New Workflow Wizard start_workflow_desc=This wizard helps you start a workflow for an item in the repository. @@ -954,19 +965,21 @@ start_workflow_finish_instruction=To start the workflow press Finish. To review start_workflow_no_metadata=There is no metadata to collect for this particular workflow. users_and_roles=Users and their Roles resources=Resources -manage_workitem=Manage WorkItem -manage_workitem_title=Manage WorkItem -manage_workitem_desc=This dialog allows the work item to be managed -workitem_properties=Work Item Properties +manage_task=Manage Task +manage_task_title=Manage Task +manage_task_desc=This dialog allows the task to be managed. +view_completed_task_title=View Completed Task +view_completed_task_desc=This dialog allows the completed task details to be viewed. +task_properties=Task Properties id=Id status=Status completed=Completed source=Source priority=Priority -my_workitems_todo_title=My Work Items To Do -my_workitems_todo_desc=List of your workflow items still to complete -my_workitems_completed_title=My Completed Work Items -my_workitems_completed_desc=List of your completed workflow items +my_tasks_todo_title=My Tasks To Do +my_tasks_todo_desc=List of your tasks still to complete +my_tasks_completed_title=My Completed Tasks +my_tasks_completed_desc=List of your completed tasks due_date=Due Date completed_on=Completed on outcome=Outcome @@ -975,10 +988,16 @@ cancel_workflow=Cancel Workflow cancel_workflow_info=To cancel this workflow, click OK. cancel_workflow_confirm=Are you sure you want to cancel the \"{0}\" workflow? error_cancel_workflow=Unable to cancel the workflow due to system error: -reassign_workitem_title=Reassign Work Item -reassign_workitem_desc=This dialog allows you to reassign a work item. -reassign_select_user=Select the user to assign the work item to, then press OK. -error_reassign_workitem=Unable to reassign the work item due to system error: +reassign_task_title=Reassign Task +reassign_task_desc=This dialog allows you to reassign a task. +reassign_select_user=Select the user to assign the task to, then press OK. +error_reassign_task=Unable to reassign the task due to system error: +part_of_workflow=Part of Workflow +initiated_by=Initiated by +start_date=Start date +add_resource=Add Resource +view_properties=View Content Properties +edit_properties=Edit Content Properties # Admin Console messages title_admin_console=Administration Console diff --git a/config/alfresco/templates/checkedout_docs.ftl b/config/alfresco/templates/checkedout_docs.ftl new file mode 100644 index 0000000000..bd620ce7e5 --- /dev/null +++ b/config/alfresco/templates/checkedout_docs.ftl @@ -0,0 +1,25 @@ +<#-- Table of the documents checked out to the current user --> +<#-- Shows the Icon and link to the content for the doc, also the size in KB and modified date --> +<#assign query="@cm\\:lockOwner:${person.properties.userName}"> +<#assign rowcount=0> + + + + + + + + + <#list userhome.childrenByLuceneSearch[query] as child> + <#if child.isDocument> + <#if rowcount % 2 = 0><#else> + + + + + + + <#assign rowcount=rowcount+1> + + +
NameSizeModified DateLocation
${child.properties.name}${(child.size / 1000)?string("0.##")} KB${child.properties.modified?datetime}${child.displayPath}
diff --git a/config/alfresco/templates/doc_info.ftl b/config/alfresco/templates/doc_info.ftl index 00af7cc5b0..2821edeeee 100644 --- a/config/alfresco/templates/doc_info.ftl +++ b/config/alfresco/templates/doc_info.ftl @@ -1,18 +1,47 @@ <#-- Shows some general info about the current document, including NodeRef and aspects applied --> -

General document info

<#if document?exists>

Current Document Info:

Name: ${document.name}
Ref: ${document.nodeRef}
Type: ${document.type}
+ DBID: ${document.properties["sys:node-dbid"]}
Content URL: /alfresco${document.url}
Locked: <#if document.isLocked>Yes<#else>No
+ <#if hasAspect(document, "cm:countable") == 1 && document.properties['cm:counter']?exists> + Counter: ${document.properties['cm:counter']}
+ Aspects: <#list document.aspects as aspect>
${aspect}
+ Properties: + + <#-- Get a list of all the property names for the document --> + <#assign props = document.properties?keys> + <#list props as t> + <#-- If the property exists --> + <#if document.properties[t]?exists> + <#-- If it is a date, format it accordingly --> + <#if document.properties[t]?is_date> + + + <#-- If it is a boolean, format it accordingly --> + <#elseif document.properties[t]?is_boolean> + + + <#-- If it is a collection, enumerate it --> + <#elseif document.properties[t]?is_enumerable> + + + <#-- Otherwise treat it as a string --> + <#else> + + + + +
${t} = ${document.properties[t]?datetime}
${t} = ${document.properties[t]?string("yes", "no")}
${t} = <#list document.properties[t] as i>${i}
${t} = ${document.properties[t]}
<#else> No document found! diff --git a/config/alfresco/templates/example.ftl b/config/alfresco/templates/example.ftl deleted file mode 100644 index 28628aa543..0000000000 --- a/config/alfresco/templates/example.ftl +++ /dev/null @@ -1,47 +0,0 @@ -

=====Example Template Start=====

- -Company Home Space: ${companyhome.properties.name} -
-My Home Space: ${userhome.properties.name} -
-Company Home children count: ${companyhome.children?size} -
-Company Home first child node name: ${companyhome.children[0].properties.name} -
-Current Document Name: ${document.name} -
-Current Space Name: ${space.name} - -

List of child spaces in my Home Space:

- -<#list userhome.children as child> - <#if child.isContainer> - - - - - - - -
${child.properties.name} (${child.children?size})Path: ${child.displayPath}
- -

List of docs in my Home Space (text only content shown inline, JPG images shown as thumbnails):

- -<#list userhome.children as child> - <#if child.isDocument> - - <#if child.mimetype = "text/plain"> - - <#elseif child.mimetype = "image/jpeg"> - - - - -
${child.properties.name}
${child.content}
- -

Assoc example:

-<#if userhome.children[0].assocs["cm:contains"]?exists> - ${userhome.children[0].assocs["cm:contains"][0].name} - - -

=====Example Template End=====

diff --git a/config/alfresco/templates/image_thumbnails.ftl b/config/alfresco/templates/image_thumbnails.ftl new file mode 100644 index 0000000000..9d18535ff3 --- /dev/null +++ b/config/alfresco/templates/image_thumbnails.ftl @@ -0,0 +1,12 @@ +<#-- 3 column list of image "thumbnails" in the current space --> +<#assign colcount=0> + +<#list space.children as child> + <#if child.isDocument && (child.mimetype = "image/png" || child.mimetype = "image/jpeg" || child.mimetype = "image/gif")> + <#if colcount % 3 = 0> + + <#if colcount % 3 = 2> + <#assign colcount=colcount+1> + + +
${child.properties.name}
diff --git a/config/alfresco/templates/my_docs.ftl b/config/alfresco/templates/my_docs.ftl index 1a31125b52..229d3fa850 100644 --- a/config/alfresco/templates/my_docs.ftl +++ b/config/alfresco/templates/my_docs.ftl @@ -1,20 +1,24 @@ <#-- Table of the documents in my Home Space --> <#-- Shows the Icon and link to the content for the doc, also the size in KB and lock status --> +<#assign rowcount=0> - + - + + <#list userhome.children as child> <#if child.isDocument> - + <#if rowcount % 2 = 0><#else> - + + + <#assign rowcount=rowcount+1>
Name SizeLockedModified DateLocked By
${child.properties.name} ${(child.size / 1000)?string("0.##")} KB <#if child.isLocked>Yes${child.properties.modified?datetime} <#if child.isLocked>${child.properties.lockOwner}
diff --git a/config/alfresco/templates/my_images.ftl b/config/alfresco/templates/my_images.ftl new file mode 100644 index 0000000000..36ec65b7bd --- /dev/null +++ b/config/alfresco/templates/my_images.ftl @@ -0,0 +1,12 @@ +<#-- 3 column list of image "thumbnails" in the users home --> +<#assign colcount=0> + +<#list userhome.children as child> + <#if child.isDocument && (child.mimetype = "image/png" || child.mimetype = "image/jpeg" || child.mimetype = "image/gif")> + <#if colcount % 3 = 0> + + <#if colcount % 3 = 2> + <#assign colcount=colcount+1> + + +
${child.properties.name}
diff --git a/config/alfresco/templates/templates_readme.txt b/config/alfresco/templates/templates_readme.txt new file mode 100644 index 0000000000..a821dab33f --- /dev/null +++ b/config/alfresco/templates/templates_readme.txt @@ -0,0 +1,10 @@ +Many example FreeMarker templates are present in this directory. + +Most are the same as the ones available in a default installation of Alfresco in the folders: +/Company Home/Data Dictionary/Presentation Templates +/Company Home/Data Dictionary/Email Templates + +More up-to-date files and obscure examples that are not appropriate for an installation may be found here. + +http://wiki.alfresco.com/wiki/Template_Guide +http://www.freemarker.org/docs/index.html diff --git a/config/alfresco/web-client-application-context.xml b/config/alfresco/web-client-application-context.xml index 818bf38e94..4c625d66cf 100644 --- a/config/alfresco/web-client-application-context.xml +++ b/config/alfresco/web-client-application-context.xml @@ -14,6 +14,7 @@ classpath:alfresco/web-client-config-actions.xml classpath:alfresco/web-client-config-workflow.xml classpath:alfresco/web-client-config-forum-actions.xml + classpath:alfresco/web-client-config-workflow-actions.xml classpath:alfresco/extension/web-client-config-custom.xml diff --git a/config/alfresco/web-client-config-actions.xml b/config/alfresco/web-client-config-actions.xml index 37b7a158e3..4a2eb195db 100644 --- a/config/alfresco/web-client-config-actions.xml +++ b/config/alfresco/web-client-config-actions.xml @@ -88,7 +88,7 @@ checkin /images/icons/CheckIn_icon.gif #{CheckinCheckoutBean.setupContentAction} - checkinFile + dialog:checkinFile #{actionContext.id} @@ -100,7 +100,7 @@ checkout /images/icons/CheckOut_icon.gif #{CheckinCheckoutBean.setupContentAction} - checkoutFile + dialog:checkoutFile #{actionContext.id} @@ -112,7 +112,7 @@ undocheckout /images/icons/undo_checkout.gif #{CheckinCheckoutBean.setupContentAction} - undoCheckoutFile + dialog:undoCheckoutFile #{actionContext.id} @@ -200,7 +200,7 @@ update /images/icons/update.gif #{CheckinCheckoutBean.setupContentAction} - updateFile + dialog:updateFile #{actionContext.id} diff --git a/config/alfresco/web-client-config-dialogs.xml b/config/alfresco/web-client-config-dialogs.xml index 2768dd5126..b159613f6f 100644 --- a/config/alfresco/web-client-config-dialogs.xml +++ b/config/alfresco/web-client-config-dialogs.xml @@ -23,6 +23,12 @@ icon="/images/icons/delete_large.gif" title-id="delete_space" description-id="delete_space_info" /> + + + - + + + + + + + + + + + diff --git a/config/alfresco/web-client-config-forum-actions.xml b/config/alfresco/web-client-config-forum-actions.xml index d50e31ff8d..7416ddd145 100644 --- a/config/alfresco/web-client-config-forum-actions.xml +++ b/config/alfresco/web-client-config-forum-actions.xml @@ -11,7 +11,7 @@ checkin /images/icons/CheckIn_icon.gif #{CheckinCheckoutBean.setupContentAction} - checkinFile + dialog:checkinFile #{actionContext.id} diff --git a/config/alfresco/web-client-config-properties.xml b/config/alfresco/web-client-config-properties.xml index 00cd3f2ffb..c3176fbaff 100644 --- a/config/alfresco/web-client-config-properties.xml +++ b/config/alfresco/web-client-config-properties.xml @@ -172,7 +172,9 @@ + + @@ -207,4 +209,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/web-client-config-wizards.xml b/config/alfresco/web-client-config-wizards.xml index 6e94a43353..995a4cf39a 100644 --- a/config/alfresco/web-client-config-wizards.xml +++ b/config/alfresco/web-client-config-wizards.xml @@ -221,6 +221,32 @@ + + + + + + + + + + + + + diff --git a/config/alfresco/web-client-config-workflow-actions.xml b/config/alfresco/web-client-config-workflow-actions.xml new file mode 100644 index 0000000000..56516bb451 --- /dev/null +++ b/config/alfresco/web-client-config-workflow-actions.xml @@ -0,0 +1,114 @@ + + + + + + start_workflow + /images/icons/new_workflow.gif + wizard:startWorkflow + #{WizardManager.setupParameters} + + #{actionContext.id} + + + + + reassign + /images/icons/reassign_task.gif + dialog:reassignTask + #{DialogManager.setupParameters} + + #{actionContext.id} + + + + + cancel_workflow + /images/icons/cancel_workflow.gif + dialog:cancelWorkflow + #{DialogManager.setupParameters} + + #{actionContext.workflowInstanceId} + #{actionContext.workflowInstanceName} + + + + + add_resource + /images/icons/add_item.gif + #{Container.bean.prepareForAdd} + + + + remove + /images/icons/remove_item.gif + #{Container.bean.removePackageItem} + + #{actionContext.id} + + + + + view_properties + /images/icons/View_details.gif + dialog:viewContentProperties + #{BrowseBean.setupContentAction} + + #{actionContext.id} + + + + + edit_properties + /images/icons/Change_details.gif + dialog:editContentProperties + #{BrowseBean.setupContentAction} + + #{actionContext.id} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index d10ba6ab65..c15afbdb1d 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -53,8 +53,8 @@ Consumer - - userhome + + myalfresco http://www.alfresco.org/help/webclient @@ -170,7 +170,7 @@ - + @@ -186,26 +186,26 @@ + - - - - - - - - + + + + + + false diff --git a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java index 9a0fabb997..c201aa5ec1 100644 --- a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java +++ b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java @@ -29,8 +29,10 @@ import org.alfresco.config.ConfigService; import org.alfresco.web.app.servlet.ExternalAccessServlet; import org.alfresco.web.bean.NavigationBean; import org.alfresco.web.bean.dialog.DialogManager; +import org.alfresco.web.bean.dialog.DialogState; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.wizard.WizardManager; +import org.alfresco.web.bean.wizard.WizardState; import org.alfresco.web.config.DialogsConfigElement; import org.alfresco.web.config.NavigationConfigElement; import org.alfresco.web.config.NavigationElementReader; @@ -47,9 +49,9 @@ import org.apache.commons.logging.LogFactory; public class AlfrescoNavigationHandler extends NavigationHandler { public final static String OUTCOME_SEPARATOR = ":"; - public final static String DIALOG_PREXIX = "dialog" + OUTCOME_SEPARATOR; + public final static String DIALOG_PREFIX = "dialog" + OUTCOME_SEPARATOR; public final static String WIZARD_PREFIX = "wizard" + OUTCOME_SEPARATOR; - public final static String CLOSE_DIALOG_OUTCOME = DIALOG_PREXIX + "close"; + public final static String CLOSE_DIALOG_OUTCOME = DIALOG_PREFIX + "close"; public final static String CLOSE_WIZARD_OUTCOME = WIZARD_PREFIX + "close"; protected final static String CONFIG_NAV_BEAN = "NavigationBean"; @@ -135,7 +137,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler { boolean dialog = false; - if (outcome != null && outcome.startsWith(DIALOG_PREXIX)) + if (outcome != null && outcome.startsWith(DIALOG_PREFIX)) { dialog = true; } @@ -589,16 +591,51 @@ public class AlfrescoNavigationHandler extends NavigationHandler // or any overridden outcome that may be present if (getViewStack(context).empty() == false) { - String newViewId = (String)getViewStack(context).pop(); - // is there an overidden outcome? String overriddenOutcome = getOutcomeOverride(outcome); if (overriddenOutcome == null) { // there isn't an overidden outcome so go back to the previous view if (logger.isDebugEnabled()) - logger.debug("Closing " + closingItem + ", going back to view id: " + newViewId); - + logger.debug("Closing " + closingItem + ", going back to previous page"); + + // if the top of the stack is not a dialog or wizard just get the + // view id and navigate back to it. + + // if the top of the stack is a dialog or wizard retrieve the state + // and setup the appropriate manager with that state, then get the + // appropriate container page and navigate to it. + + Object topOfStack = getViewStack(context).pop(); + + if (logger.isDebugEnabled()) + logger.debug("Popped item from the top of the view stack: " + topOfStack); + + String newViewId = null; + + if (topOfStack instanceof String) + { + newViewId = (String)topOfStack; + } + else if (topOfStack instanceof DialogState) + { + // restore the dialog state and get the dialog container viewId + Application.getDialogManager().restoreState((DialogState)topOfStack); + newViewId = getDialogContainer(context); + } + else if (topOfStack instanceof WizardState) + { + // restore the wizard state and get the wizard container viewId + Application.getWizardManager().restoreState((WizardState)topOfStack); + newViewId = getWizardContainer(context); + } + else + { + if (logger.isWarnEnabled()) + logger.warn("Invalid object found on view stack: " + topOfStack); + } + + // go to the appropraite page goToView(context, newViewId); } else @@ -656,33 +693,66 @@ public class AlfrescoNavigationHandler extends NavigationHandler * * @param context FacesContext */ + @SuppressWarnings("unchecked") protected void addCurrentViewToStack(FacesContext context) { - // if we are opening a wizard or dialog push the current view - // id on to the stack, but only if it is different than the - // current view at the top (you can't launch a dialog from - // the same page 2 times in a row!) + // if the current viewId is either the dialog or wizard container page + // we need to save the state of the current dialog or wizard to the stack - // TODO: This wouldn't happen if we could be sure a dialog is - // ALWAYS exited properly, look into a way of ensuring - // dialogs get closed if a user navigates away from the page, - // would a PhaseListener help in any way?? + // If the current view is a normal page and it is not the same as the + // view currently at the top of the stack (you can't launch a dialog from + // the same page 2 times in a row so it must mean the user navigated away + // from the first dialog) just add the viewId to the stack + // work out what to add to the stack String viewId = context.getViewRoot().getViewId(); - - if (getViewStack(context).empty() || - viewId.equals(getViewStack(context).peek()) == false) + String dialogContainer = getDialogContainer(context); + String wizardContainer = getWizardContainer(context); + Object objectForStack = null; + if (viewId.equals(dialogContainer)) { - getViewStack(context).push(viewId); - - if (logger.isDebugEnabled()) - logger.debug("Pushed current view to stack: " + viewId); + DialogManager dlgMgr = Application.getDialogManager(); + objectForStack = dlgMgr.getState(); + } + else if (viewId.equals(wizardContainer)) + { + WizardManager wizMgr = Application.getWizardManager(); + objectForStack = wizMgr.getState(); } else { - if (getViewStack(context).empty() == false && logger.isDebugEnabled()) + objectForStack = viewId; + } + + // if the stack is currently empty add the item + Stack stack = getViewStack(context); + if (stack.empty()) + { + stack.push(objectForStack); + + if (logger.isDebugEnabled()) + logger.debug("Pushed item to view stack: " + objectForStack); + } + else + { + // if the item to go on to the stack and the top of + // stack are both Strings and equals to each other + // don't add anything to the stack to stop it + // growing unecessarily + Object topOfStack = stack.peek(); + if (objectForStack instanceof String && + topOfStack instanceof String && + topOfStack.equals(objectForStack)) { - logger.debug("current view is already top the view stack!"); + if (logger.isDebugEnabled()) + logger.debug("current view is already top of the view stack!"); + } + else + { + stack.push(objectForStack); + + if (logger.isDebugEnabled()) + logger.debug("Pushed item to view stack: " + objectForStack); } } } @@ -725,13 +795,13 @@ public class AlfrescoNavigationHandler extends NavigationHandler * the users session, will never be null */ @SuppressWarnings("unchecked") - private Stack getViewStack(FacesContext context) + private Stack getViewStack(FacesContext context) { - Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK); + Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK); if (viewStack == null) { - viewStack = new Stack(); + viewStack = new Stack(); context.getExternalContext().getSessionMap().put(VIEW_STACK, viewStack); } diff --git a/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java b/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java new file mode 100644 index 0000000000..fa506da653 --- /dev/null +++ b/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java @@ -0,0 +1,143 @@ +package org.alfresco.web.app; + +import javax.faces.context.FacesContext; +import javax.faces.el.EvaluationException; +import javax.faces.el.VariableResolver; + +import org.alfresco.config.Config; +import org.alfresco.config.ConfigService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.web.jsf.DelegatingVariableResolver; + +/** + * JSF VariableResolver that first delegates to the Spring JSF variable + * resolver. The sole purpose of this variable resolver is to look out + * for the Container variable. If this variable is encountered + * the current viewId is examined. If the current viewId matches the + * configured dialog or wizard container the appropriate manager object is + * returned i.e. DialogManager or WizardManager. + * + *

Configure this resolver in your faces-config.xml file as follows: + * + *

+ * <application>
+ *   ...
+ *   <variable-resolver>org.alfresco.web.app.AlfrescoVariableResolver</variable-resolver>
+ * </application>
+ * + * @see org.alfresco.web.bean.dialog.DialogManager + * @see org.alfresco.web.bean.wizard.WizardManager + * @author gavinc + */ +public class AlfrescoVariableResolver extends DelegatingVariableResolver +{ + protected String dialogContainer = null; + protected String wizardContainer = null; + + private static final String CONTAINER = "Container"; + + private static final Log logger = LogFactory.getLog(AlfrescoVariableResolver.class); + + /** + * Creates a new VariableResolver. + * + * @param originalVariableResolver The original variable resolver + */ + public AlfrescoVariableResolver(VariableResolver originalVariableResolver) + { + super(originalVariableResolver); + } + + /** + * Resolves the variable with the given name. + *

+ * This implementation will first delegate to the Spring variable resolver. + * If the variable is not found by the Spring resolver and the variable name + * is Container the current viewId is examined. + * If the current viewId matches the configured dialog or wizard container + * the appropriate manager object is returned i.e. DialogManager or WizardManager. + * + * @param context FacesContext + * @param name The name of the variable to resolve + */ + public Object resolveVariable(FacesContext context, String name) + throws EvaluationException + { + Object variable = super.resolveVariable(context, name); + + if (variable == null) + { + // if the variable was not resolved see if the name is "Container" + if (name.equals(CONTAINER)) + { + // get the current view id and the configured dialog and wizard + // container pages + String viewId = context.getViewRoot().getViewId(); + String dialogContainer = getDialogContainer(context); + String wizardContainer = getWizardContainer(context); + + // see if we are currently in a wizard or a dialog + if (viewId.equals(dialogContainer)) + { + variable = Application.getDialogManager(); + } + else if (viewId.equals(wizardContainer)) + { + variable = Application.getWizardManager(); + } + + if (variable != null && logger.isDebugEnabled()) + { + logger.debug("Resolved 'Container' variable to: " + variable); + } + } + } + + return variable; + } + + /** + * Retrieves the configured dialog container page + * + * @param context FacesContext + * @return The container page + */ + protected String getDialogContainer(FacesContext context) + { + if (this.dialogContainer == null) + { + ConfigService configSvc = Application.getConfigService(context); + Config globalConfig = configSvc.getGlobalConfig(); + + if (globalConfig != null) + { + this.dialogContainer = globalConfig.getConfigElement("dialog-container").getValue(); + } + } + + return this.dialogContainer; + } + + /** + * Retrieves the configured wizard container page + * + * @param context FacesContext + * @return The container page + */ + protected String getWizardContainer(FacesContext context) + { + if (this.wizardContainer == null) + { + ConfigService configSvc = Application.getConfigService(context); + Config globalConfig = configSvc.getGlobalConfig(); + + if (globalConfig != null) + { + this.wizardContainer = globalConfig.getConfigElement("wizard-container").getValue(); + } + } + + return this.wizardContainer; + } +} diff --git a/source/java/org/alfresco/web/app/portlet/AlfrescoFacesPortlet.java b/source/java/org/alfresco/web/app/portlet/AlfrescoFacesPortlet.java index afc5984f07..2130a849dd 100644 --- a/source/java/org/alfresco/web/app/portlet/AlfrescoFacesPortlet.java +++ b/source/java/org/alfresco/web/app/portlet/AlfrescoFacesPortlet.java @@ -33,6 +33,7 @@ import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.UnavailableException; +import org.alfresco.config.ConfigService; import org.alfresco.i18n.I18NUtil; import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.service.cmr.security.AuthenticationService; @@ -43,7 +44,9 @@ import org.alfresco.web.app.servlet.AuthenticationStatus; import org.alfresco.web.bean.ErrorBean; import org.alfresco.web.bean.FileUploadBean; import org.alfresco.web.bean.LoginBean; +import org.alfresco.web.bean.NavigationBean; import org.alfresco.web.bean.repository.User; +import org.alfresco.web.config.ClientConfigElement; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.portlet.PortletFileUpload; @@ -259,7 +262,18 @@ public class AlfrescoFacesPortlet extends MyFacesGenericPortlet // perform the forward to the page processed by the Faces servlet response.setContentType("text/html"); request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true"); - nonFacesRequest(request, response, "/jsp/browse/browse.jsp"); + + // get the start location as configured by the web-client config + ConfigService configService = (ConfigService)ctx.getBean("webClientConfigService"); + ClientConfigElement configElement = (ClientConfigElement)configService.getGlobalConfig().getConfigElement("client"); + if (NavigationBean.LOCATION_MYALFRESCO.equals(configElement.getInitialLocation())) + { + nonFacesRequest(request, response, "/jsp/dashboards/container.jsp"); + } + else + { + nonFacesRequest(request, response, "/jsp/browse/browse.jsp"); + } } else { diff --git a/source/java/org/alfresco/web/app/servlet/BaseServlet.java b/source/java/org/alfresco/web/app/servlet/BaseServlet.java index 90b4c7c687..42dde0bf53 100644 --- a/source/java/org/alfresco/web/app/servlet/BaseServlet.java +++ b/source/java/org/alfresco/web/app/servlet/BaseServlet.java @@ -77,7 +77,6 @@ public abstract class BaseServlet extends HttpServlet validRedirectJSPs.add("/jsp/forums/forums.jsp"); validRedirectJSPs.add("/jsp/users/users.jsp"); validRedirectJSPs.add("/jsp/trashcan/trash-list.jsp"); - validRedirectJSPs.add("/jsp/dashboards/container.jsp"); } private static Log logger = LogFactory.getLog(BaseServlet.class); @@ -156,10 +155,15 @@ public abstract class BaseServlet extends HttpServlet throws IOException { // authentication failed - so end servlet execution and redirect to login page - // also save the full requested URL so the login page knows where to redirect too later res.sendRedirect(req.getContextPath() + FACES_SERVLET + Application.getLoginPage(sc)); + + // save the full requested URL so the login page knows where to redirect too later String uri = req.getRequestURI(); - String url = uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""); + String url = uri; + if (req.getQueryString() != null && req.getQueryString().length() != 0) + { + url += "?" + req.getQueryString(); + } if (uri.indexOf(req.getContextPath() + FACES_SERVLET) != -1) { // if we find a JSF servlet reference in the URI then we need to check if the rest of the diff --git a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java index b130c3d788..3359683f70 100644 --- a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java +++ b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java @@ -40,13 +40,12 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.VersionType; +import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.app.servlet.DownloadContentServlet; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.templating.OutputUtil; -import org.alfresco.web.templating.TemplatingService; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIActionLink; import org.apache.commons.logging.Log; @@ -376,8 +375,8 @@ public class CheckinCheckoutBean */ private Node setupContentDocument(String id) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Setup for action, setting current document to: " + id); + if (logger.isDebugEnabled()) + logger.debug("Setup for action, setting current document to: " + id); Node node = null; @@ -427,14 +426,14 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); tx.begin(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Trying to checkout content node Id: " + node.getId()); + if (logger.isDebugEnabled()) + logger.debug("Trying to checkout content node Id: " + node.getId()); // checkout the node content to create a working copy - if (LOGGER.isDebugEnabled()) + if (logger.isDebugEnabled()) { - LOGGER.debug("Checkout copy location: " + getCopyLocation()); - LOGGER.debug("Selected Space Id: " + this.selectedSpaceId); + logger.debug("Checkout copy location: " + getCopyLocation()); + logger.debug("Selected Space Id: " + this.selectedSpaceId); } NodeRef workingCopyRef; if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null) @@ -478,7 +477,7 @@ public class CheckinCheckoutBean } else { - LOGGER.warn("WARNING: checkoutFile called without a current Document!"); + logger.warn("WARNING: checkoutFile called without a current Document!"); } return outcome; @@ -494,16 +493,22 @@ public class CheckinCheckoutBean Node node = getWorkingDocument(); if (node != null) { + // reset the underlying node + if (this.browseBean.getDocument() != null) + { + this.browseBean.getDocument().reset(); + } + // clean up and clear action context clearUpload(); setDocument(null); setWorkingDocument(null); - - outcome = "browse"; + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } else { - LOGGER.warn("WARNING: checkoutFileOK called without a current WorkingDocument!"); + logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!"); } return outcome; @@ -524,11 +529,11 @@ public class CheckinCheckoutBean setDocument(null); setWorkingDocument(null); - outcome = "browse"; + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } else { - LOGGER.warn("WARNING: editFileOK called without a current Document!"); + logger.warn("WARNING: editFileOK called without a current Document!"); } return outcome; @@ -567,17 +572,12 @@ public class CheckinCheckoutBean MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype)) { // make content available to the editing screen - String contentString = reader.getContentString(); - setDocumentContent(contentString); - setEditorOutput(contentString); - - // navigate to appropriate screen - FacesContext fc = FacesContext.getCurrentInstance(); - this.navigator.setupDispatchContext(node); - String s = (MimetypeMap.MIMETYPE_XML.equals(mimetype) - ? "editXmlInline" - : "editTextInline"); - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, s); + setEditorOutput(reader.getContentString()); + + // navigate to appropriate screen + FacesContext fc = FacesContext.getCurrentInstance(); + this.navigator.setupDispatchContext(node); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editTextInline"); } else { @@ -588,7 +588,7 @@ public class CheckinCheckoutBean // navigate to appropriate screen FacesContext fc = FacesContext.getCurrentInstance(); this.navigator.setupDispatchContext(node); - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editHtmlInline"); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editHtmlInline"); } } } @@ -598,7 +598,7 @@ public class CheckinCheckoutBean // normal downloadable document FacesContext fc = FacesContext.getCurrentInstance(); this.navigator.setupDispatchContext(node); - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editFile"); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editFile"); } } } @@ -620,31 +620,23 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); tx.begin(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Trying to update content node Id: " + node.getId()); + if (logger.isDebugEnabled()) + logger.debug("Trying to update content node Id: " + node.getId()); // get an updating writer that we can use to modify the content on the current node ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); writer.putContent(this.editorOutput); - + // commit the transaction tx.commit(); - - if (nodeService.getProperty(node.getNodeRef(), - TemplatingService.TT_QNAME) != null) - { - OutputUtil.regenerate(node.getNodeRef(), - this.contentService, - this.nodeService); - } // clean up and clear action context clearUpload(); setDocument(null); setDocumentContent(null); setEditorOutput(null); - - outcome = "browse"; + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } catch (Throwable err) { @@ -656,7 +648,7 @@ public class CheckinCheckoutBean } else { - LOGGER.warn("WARNING: editInlineOK called without a current Document!"); + logger.warn("WARNING: editInlineOK called without a current Document!"); } return outcome; @@ -679,7 +671,7 @@ public class CheckinCheckoutBean clearUpload(); - outcome = "browse"; + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } catch (Throwable err) { @@ -689,7 +681,7 @@ public class CheckinCheckoutBean } else { - LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!"); + logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); } return outcome; @@ -726,10 +718,10 @@ public class CheckinCheckoutBean { throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!"); } - + clearUpload(); - outcome = "browse"; + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; } catch (Throwable err) { @@ -738,7 +730,7 @@ public class CheckinCheckoutBean } else { - LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!"); + logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); } return outcome; @@ -763,8 +755,8 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(context); tx.begin(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Trying to checkin content node Id: " + node.getId()); + if (logger.isDebugEnabled()) + logger.debug("Trying to checkin content node Id: " + node.getId()); // we can either checkin the content from the current working copy node // which would have been previously updated by the user @@ -816,7 +808,8 @@ public class CheckinCheckoutBean setDocument(null); clearUpload(); - outcome = "browse"; + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; } catch (Throwable err) { @@ -828,7 +821,7 @@ public class CheckinCheckoutBean } else { - LOGGER.warn("WARNING: checkinFileOK called without a current Document!"); + logger.warn("WARNING: checkinFileOK called without a current Document!"); } return outcome; @@ -853,8 +846,8 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(context); tx.begin(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Trying to update content node Id: " + node.getId()); + if (logger.isDebugEnabled()) + logger.debug("Trying to update content node Id: " + node.getId()); // get an updating writer that we can use to modify the content on the current node ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); @@ -872,7 +865,7 @@ public class CheckinCheckoutBean setDocument(null); clearUpload(); - outcome = "browse"; + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } catch (Throwable err) { @@ -884,7 +877,7 @@ public class CheckinCheckoutBean } else { - LOGGER.warn("WARNING: updateFileOK called without a current Document!"); + logger.warn("WARNING: updateFileOK called without a current Document!"); } return outcome; @@ -898,7 +891,7 @@ public class CheckinCheckoutBean // reset the state clearUpload(); - return "browse"; + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } /** @@ -929,7 +922,7 @@ public class CheckinCheckoutBean // ------------------------------------------------------------------------------ // Private data - private static final Log LOGGER = LogFactory.getLog(CheckinCheckoutBean.class); + private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class); /** I18N messages */ private static final String MSG_ERROR_CHECKIN = "error_checkin"; diff --git a/source/java/org/alfresco/web/bean/LoginBean.java b/source/java/org/alfresco/web/bean/LoginBean.java index 17274e42b9..406f26b039 100644 --- a/source/java/org/alfresco/web/bean/LoginBean.java +++ b/source/java/org/alfresco/web/bean/LoginBean.java @@ -91,13 +91,21 @@ public class LoginBean } /** - * @param navigator The NavigationBean to set. + * @param navigator The NavigationBean to set. */ public void setNavigator(NavigationBean navigator) { this.navigator = navigator; } + /** + * @param preferences The UserPreferencesBean to set + */ + public void setUserPreferencesBean(UserPreferencesBean preferences) + { + this.preferences = preferences; + } + /** * @return true if the default Alfresco authentication process is being used, else false * if an external authorisation mechanism is present. @@ -329,7 +337,7 @@ public class LoginBean else { // special case to handle jump to My Alfresco page initially - String location = Application.getClientConfig(FacesContext.getCurrentInstance()).getInitialLocation(); + String location = this.preferences.getStartLocation(); if (NavigationBean.LOCATION_MYALFRESCO.equals(location)) { return "myalfresco"; @@ -451,4 +459,7 @@ public class LoginBean /** The NavigationBean bean reference */ protected NavigationBean navigator; + + /** The user preferences bean reference */ + protected UserPreferencesBean preferences; } diff --git a/source/java/org/alfresco/web/bean/NavigationBean.java b/source/java/org/alfresco/web/bean/NavigationBean.java index d426a07732..8f13f9e018 100644 --- a/source/java/org/alfresco/web/bean/NavigationBean.java +++ b/source/java/org/alfresco/web/bean/NavigationBean.java @@ -126,6 +126,14 @@ public class NavigationBean this.contentDiskDriver = contentDiskDriver; } + /** + * @param preferences The UserPreferencesBean to set + */ + public void setUserPreferencesBean(UserPreferencesBean preferences) + { + this.preferences = preferences; + } + /** * @return the User object representing the current instance for this user */ @@ -252,6 +260,15 @@ public class NavigationBean } else if (LOCATION_MYALFRESCO.equals(location)) { + // make sure we set a current node ID as some screens expect this + if (getCurrentNodeId() == null) + { + String homeSpaceId = Application.getCurrentUser(context).getHomeSpaceId(); + NodeRef homeSpaceRef = new NodeRef(Repository.getStoreRef(), homeSpaceId); + setCurrentNodeId(homeSpaceRef.getId()); + } + + // create a breadcrumb handler for this special case location (not a node) List elements = new ArrayList(1); elements.add(new IBreadcrumbHandler() { @@ -507,13 +524,8 @@ public class NavigationBean { if (this.location == null) { - // get the initial location from the client config - String initialLocation = clientConfig.getInitialLocation(); - if (initialLocation == null || initialLocation.length() == 0) - { - initialLocation = LOCATION_HOME; - } - processToolbarLocation(initialLocation, false); + // get the initial location from the user preferences + processToolbarLocation(this.preferences.getStartLocation(), false); } return this.location; @@ -798,10 +810,10 @@ public class NavigationBean private static Logger s_logger = Logger.getLogger(NavigationBean.class); /** constant values used by the toolbar location modelist control */ - static final String LOCATION_COMPANY = "companyhome"; - static final String LOCATION_HOME = "userhome"; - static final String LOCATION_GUEST = "guesthome"; - static final String LOCATION_MYALFRESCO = "myalfresco"; + public static final String LOCATION_COMPANY = "companyhome"; + public static final String LOCATION_HOME = "userhome"; + public static final String LOCATION_GUEST = "guesthome"; + public static final String LOCATION_MYALFRESCO = "myalfresco"; private static final String MSG_MYALFRESCO = "my_alfresco"; @@ -828,6 +840,9 @@ public class NavigationBean /** Client configuration object */ protected ClientConfigElement clientConfig = null; + /** The user preferences bean reference */ + protected UserPreferencesBean preferences; + /** Cached path to our CIFS server and top level node DIR */ private String cifsServerPath; diff --git a/source/java/org/alfresco/web/bean/UserPreferencesBean.java b/source/java/org/alfresco/web/bean/UserPreferencesBean.java new file mode 100644 index 0000000000..692e3dd7e3 --- /dev/null +++ b/source/java/org/alfresco/web/bean/UserPreferencesBean.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.bean; + +import java.util.ResourceBundle; + +import javax.faces.context.FacesContext; +import javax.faces.model.SelectItem; + +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.PreferencesService; + +/** + * Simple bean backing the user preferences settings. + * + * @author Kevin Roast + */ +public class UserPreferencesBean +{ + private static final String PREF_STARTLOCATION = "start-location"; + private static final String MSG_MYALFRESCO = "my_alfresco"; + private static final String MSG_MYHOME = "my_home"; + private static final String MSG_COMPANYHOME = "company_home"; + private static final String MSG_GUESTHOME = "guest_home"; + + + public String getStartLocation() + { + String location = (String)PreferencesService.getPreferences().getValue(PREF_STARTLOCATION); + if (location == null) + { + // default to value from client config + location = Application.getClientConfig(FacesContext.getCurrentInstance()).getInitialLocation(); + } + return location; + } + + public void setStartLocation(String location) + { + PreferencesService.getPreferences().setValue(PREF_STARTLOCATION, location); + } + + public SelectItem[] getStartLocations() + { + ResourceBundle msg = Application.getBundle(FacesContext.getCurrentInstance()); + return new SelectItem[] { + new SelectItem(NavigationBean.LOCATION_MYALFRESCO, msg.getString(MSG_MYALFRESCO)), + new SelectItem(NavigationBean.LOCATION_HOME, msg.getString(MSG_MYHOME)), + new SelectItem(NavigationBean.LOCATION_COMPANY, msg.getString(MSG_COMPANYHOME)), + new SelectItem(NavigationBean.LOCATION_GUEST, msg.getString(MSG_GUESTHOME))}; + } +} diff --git a/source/java/org/alfresco/web/bean/actions/handlers/ScriptHandler.java b/source/java/org/alfresco/web/bean/actions/handlers/ScriptHandler.java index 41321fba6e..ef73b9bd9b 100644 --- a/source/java/org/alfresco/web/bean/actions/handlers/ScriptHandler.java +++ b/source/java/org/alfresco/web/bean/actions/handlers/ScriptHandler.java @@ -6,7 +6,7 @@ import java.util.Map; import javax.faces.context.FacesContext; -import org.alfresco.repo.action.executer.ScriptActionExecutor; +import org.alfresco.repo.action.executer.ScriptActionExecuter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.web.app.Application; import org.alfresco.web.app.servlet.FacesHelper; @@ -25,7 +25,7 @@ public class ScriptHandler extends BaseActionHandler public String getJSPPath() { - return getJSPPath(ScriptActionExecutor.NAME); + return getJSPPath(ScriptActionExecuter.NAME); } public void prepareForSave(Map actionProps, @@ -34,13 +34,13 @@ public class ScriptHandler extends BaseActionHandler // add the selected script noderef to the action properties String id = (String)actionProps.get(PROP_SCRIPT); NodeRef scriptRef = new NodeRef(Repository.getStoreRef(), id); - repoProps.put(ScriptActionExecutor.PARAM_SCRIPTREF, scriptRef); + repoProps.put(ScriptActionExecuter.PARAM_SCRIPTREF, scriptRef); } public void prepareForEdit(Map actionProps, Map repoProps) { - NodeRef scriptRef = (NodeRef)repoProps.get(ScriptActionExecutor.PARAM_SCRIPTREF); + NodeRef scriptRef = (NodeRef)repoProps.get(ScriptActionExecuter.PARAM_SCRIPTREF); actionProps.put(PROP_SCRIPT, scriptRef.getId()); } diff --git a/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java b/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java index 89c9b0c81f..a707d316c7 100644 --- a/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java +++ b/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java @@ -34,8 +34,6 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.model.FileExistsException; import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.InvalidNodeRefException; @@ -182,12 +180,8 @@ public class ClipboardBean */ private void performPasteItems(int index, int action) { - UserTransaction tx = null; try { - tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); - tx.begin(); - if (index == -1) { // paste all @@ -219,16 +213,11 @@ public class ClipboardBean } } - // commit the transaction - tx.commit(); - // refresh UI on success UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans(); } catch (Throwable err) { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} Utils.addErrorMessage(Application.getMessage( FacesContext.getCurrentInstance(), MSG_ERROR_PASTE) + err.getMessage(), err); } @@ -241,7 +230,7 @@ public class ClipboardBean * @param action the clipboard action to perform (see UIClipboardShelfItem) */ private void performClipboardOperation(ClipboardItem item, int action) - throws FileExistsException, FileNotFoundException + throws Throwable { NodeRef destRef = new NodeRef(Repository.getStoreRef(), this.navigator.getCurrentNodeId()); @@ -267,8 +256,12 @@ public class ClipboardBean boolean operationComplete = false; while (operationComplete == false) { + UserTransaction tx = null; try { + // attempt each copy/paste in its own transaction + tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); + tx.begin(); if (item.Mode == ClipboardStatus.COPY) { if (action == UIClipboardShelfItem.ACTION_PASTE_LINK) @@ -399,10 +392,25 @@ public class ClipboardBean throw fileExistsErr; } } - if (operationComplete == false) + catch (Throwable e) { - String copyOf = Application.getMessage(FacesContext.getCurrentInstance(), MSG_COPY_OF); - name = copyOf + ' ' + name; + // some other type of exception occured - rollback and exit + throw e; + } + finally + { + // rollback if the operation didn't complete + if (operationComplete == false) + { + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + String copyOf = Application.getMessage(FacesContext.getCurrentInstance(), MSG_COPY_OF); + name = copyOf + ' ' + name; + } + else + { + // commit the transaction + tx.commit(); + } } } } diff --git a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java index dd11533c0d..881facb299 100644 --- a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java +++ b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ package org.alfresco.web.bean.content; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.ResourceBundle; @@ -35,17 +18,9 @@ import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.data.IDataContainer; import org.alfresco.web.data.QuickSort; -import org.alfresco.web.templating.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.alfresco.model.ContentModel; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.ContentWriter; -import java.io.OutputStreamWriter; -import org.alfresco.web.app.servlet.FacesHelper; - /** * Bean implementation for the "Create Content Wizard" dialog * @@ -53,14 +28,12 @@ import org.alfresco.web.app.servlet.FacesHelper; */ public class CreateContentWizard extends BaseContentWizard { - protected String content = null; - protected String templateTypeName; - protected List createMimeTypes; - - private static final Log LOGGER = - LogFactory.getLog(CreateContentWizard.class); - - + protected String content = null; + + protected List createMimeTypes; + + private static Log logger = LogFactory.getLog(CreateContentWizard.class); + // ------------------------------------------------------------------------------ // Wizard implementation @@ -68,28 +41,10 @@ public class CreateContentWizard extends BaseContentWizard protected String finishImpl(FacesContext context, String outcome) throws Exception { - LOGGER.debug("saving file content to " + this.fileName); - saveContent(null, this.content); - if (this.templateTypeName != null) - { - LOGGER.debug("generating template output for " + this.templateTypeName); - this.nodeService.setProperty(this.createdNode, - TemplatingService.TT_QNAME, - this.templateTypeName); - TemplatingService ts = TemplatingService.getInstance(); - TemplateType tt = this.getTemplateType(); - OutputUtil.generate(this.createdNode, - ts.parseXML(this.content), - tt, - this.fileName, - this.getContainerNodeRef(), - this.fileFolderService, - this.contentService, - this.nodeService); - } - - // return the default outcome - return outcome; + saveContent(null, this.content); + + // return the default outcome + return outcome; } @Override @@ -99,7 +54,6 @@ public class CreateContentWizard extends BaseContentWizard this.content = null; this.inlineEdit = true; - this.templateTypeName = null; this.mimeType = MimetypeMap.MIMETYPE_HTML; } @@ -162,20 +116,6 @@ public class CreateContentWizard extends BaseContentWizard { this.content = content; } - - public List getCreateTemplateTypes() - { - Collection ttl = TemplatingService.getInstance().getTemplateTypes(); - List sil = new ArrayList(ttl.size()); - for (TemplateType tt : ttl) - { - sil.add(new SelectItem(tt.getName(), tt.getName())); - } - - QuickSort sorter = new QuickSort(sil, "label", true, IDataContainer.SORT_CASEINSENSITIVE); - sorter.sort(); - return sil; - } /** * @return Returns a list of mime types to allow the user to select from @@ -213,37 +153,18 @@ public class CreateContentWizard extends BaseContentWizard } else { - LOGGER.warn("Could not find 'create-mime-types' configuration element"); + logger.warn("Could not find 'create-mime-types' configuration element"); } } else { - LOGGER.warn("Could not find 'Content Wizards' configuration section"); + logger.warn("Could not find 'Content Wizards' configuration section"); } } return this.createMimeTypes; } - - public String getTemplateTypeName() - { - return this.templateTypeName; - } - - public TemplateType getTemplateType() - { - final TemplatingService ts = TemplatingService.getInstance(); - return ts.getTemplateType(this.getTemplateTypeName()); - } - - /** - * @param templateType Sets the currently selected template type - */ - public void setTemplateTypeName(final String templateTypeName) - { - this.templateTypeName = templateTypeName; - } /** * @return Returns the summary data for the wizard. diff --git a/source/java/org/alfresco/web/bean/content/ViewContentPropertiesDialog.java b/source/java/org/alfresco/web/bean/content/ViewContentPropertiesDialog.java new file mode 100644 index 0000000000..1b3f75825f --- /dev/null +++ b/source/java/org/alfresco/web/bean/content/ViewContentPropertiesDialog.java @@ -0,0 +1,75 @@ +package org.alfresco.web.bean.content; + +import java.util.Map; + +import javax.faces.context.FacesContext; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.dialog.BaseDialogBean; +import org.alfresco.web.bean.repository.Node; + +/** + * Bean implementation of the "View Content Properties" dialog. + * + * @author gavinc + */ +public class ViewContentPropertiesDialog extends BaseDialogBean +{ + protected static final String TEMP_PROP_MIMETYPE = "mimetype"; + + protected Node viewingNode; + + // ------------------------------------------------------------------------------ + // Dialog implementation + + @Override + public void init(Map parameters) + { + super.init(parameters); + + // setup the editable node + this.viewingNode = new Node(this.browseBean.getDocument().getNodeRef()); + + // special case for Mimetype - since this is a sub-property of the ContentData object + // we must extract it so it can be edited in the client, then we check for it later + // and create a new ContentData object to wrap it and it's associated URL + ContentData content = (ContentData)this.viewingNode.getProperties().get(ContentModel.PROP_CONTENT); + if (content != null) + { + this.viewingNode.getProperties().put(TEMP_PROP_MIMETYPE, content.getMimetype()); + } + + // add the specially handled 'size' property + this.viewingNode.addPropertyResolver("size", this.browseBean.resolverSize); + } + + @Override + protected String finishImpl(FacesContext context, String outcome) + throws Exception + { + // nothing to do as the finish button is not shown and the dialog is read only + + return outcome; + } + + @Override + public String getCancelButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "close"); + } + + // ------------------------------------------------------------------------------ + // Bean getters and setters + + /** + * Returns the node being viewed + * + * @return The node being viewed + */ + public Node getViewingNode() + { + return this.viewingNode; + } +} diff --git a/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java b/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java index 615570d480..4ff8d46793 100644 --- a/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java +++ b/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java @@ -125,6 +125,14 @@ public class DashboardWizard extends BaseWizardBean // ------------------------------------------------------------------------------ // Dashboard Wizard bean getters + /** + * @return true to allow the Guest user to configure the dashboard, false otherwise + */ + public boolean getAllowGuestConfig() + { + return DashboardManager.getDashboardConfig().getAllowGuestConfig(); + } + /** * @return The currently selected layout ID - used by the Dynamic Description component */ diff --git a/source/java/org/alfresco/web/bean/dashboard/GettingStartedBean.java b/source/java/org/alfresco/web/bean/dashboard/GettingStartedBean.java new file mode 100644 index 0000000000..11cbb1fd6f --- /dev/null +++ b/source/java/org/alfresco/web/bean/dashboard/GettingStartedBean.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.bean.dashboard; + +import javax.faces.context.FacesContext; + +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.NavigationBean; + +/** + * Backing bean for the Getting Started Dashlet page. + * + * @author Kevin Roast + */ +public class GettingStartedBean +{ + private NavigationBean navigationBean; + + + /** + * @param navigationBean The navigationBean to set. + */ + public void setNavigationBean(NavigationBean navigationBean) + { + this.navigationBean = navigationBean; + } + + public String browseHomeSpace() + { + this.navigationBean.setCurrentNodeId(getHomeSpaceId()); + return "browse"; + } + + public String createSpace() + { + this.navigationBean.setCurrentNodeId(getHomeSpaceId()); + return "dialog:createSpace"; + } + + public String createContent() + { + this.navigationBean.setCurrentNodeId(getHomeSpaceId()); + return "wizard:createContent"; + } + + public String addContent() + { + this.navigationBean.setCurrentNodeId(getHomeSpaceId()); + return "addContent"; + } + + private String getHomeSpaceId() + { + return Application.getCurrentUser(FacesContext.getCurrentInstance()).getHomeSpaceId(); + } +} diff --git a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java index 586eb6bd83..535506eb18 100644 --- a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java +++ b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java @@ -59,6 +59,11 @@ public abstract class BaseDialogBean implements IDialogBean this.isFinished = false; } + public void restored() + { + // do nothing by default, subclasses can override if necessary + } + public String cancel() { return getDefaultCancelOutcome(); @@ -126,6 +131,16 @@ public abstract class BaseDialogBean implements IDialogBean return true; } + public String getTitle() + { + return null; + } + + public String getDescription() + { + return null; + } + /** * @param browseBean The BrowseBean to set. */ diff --git a/source/java/org/alfresco/web/bean/dialog/DialogManager.java b/source/java/org/alfresco/web/bean/dialog/DialogManager.java index c47c6d8c62..c7998ab253 100644 --- a/source/java/org/alfresco/web/bean/dialog/DialogManager.java +++ b/source/java/org/alfresco/web/bean/dialog/DialogManager.java @@ -20,11 +20,10 @@ import org.alfresco.web.ui.common.component.UIActionLink; * * @author gavinc */ -public class DialogManager +public final class DialogManager { - protected IDialogBean currentDialog; - protected DialogConfig currentDialogConfig; - protected Map currentDialogParams; + private DialogState currentDialogState; + private Map paramsToApply; /** * Action handler used to setup parameters for the dialog being launched @@ -38,7 +37,7 @@ public class DialogManager if (component instanceof UIActionLink) { // store the parameters - this.currentDialogParams = ((UIActionLink)component).getParameterMap(); + this.paramsToApply = ((UIActionLink)component).getParameterMap(); } } @@ -49,22 +48,48 @@ public class DialogManager */ public void setCurrentDialog(DialogConfig config) { - this.currentDialogConfig = config; - - String beanName = this.currentDialogConfig.getManagedBean(); - this.currentDialog = (IDialogBean)FacesHelper.getManagedBean( + String beanName = config.getManagedBean(); + IDialogBean dialog = (IDialogBean)FacesHelper.getManagedBean( FacesContext.getCurrentInstance(), beanName); - if (this.currentDialog == null) + if (dialog == null) { throw new AlfrescoRuntimeException("Failed to find managed bean '" + beanName + "'"); } // initialise the managed bean - this.currentDialog.init(this.currentDialogParams); + dialog.init(this.paramsToApply); // reset the current parameters so subsequent dialogs don't get them - this.currentDialogParams = null; + this.paramsToApply = null; + + // create the DialogState object + this.currentDialogState = new DialogState(config, dialog); + } + + /** + * Returns the state of the currently active dialog + * + * @return Current dialog's state + */ + public DialogState getState() + { + return this.currentDialogState; + } + + /** + * Restores the dialog represented by the given DialogState object. + * NOTE: The dialog's restored() method is also called during this + * method. + * + * @param state The DialogState for the dialog to restore + */ + public void restoreState(DialogState state) + { + this.currentDialogState = state; + + // retrieve the dialog and call it's restored() method + this.currentDialogState.getDialog().restored(); } /** @@ -74,7 +99,7 @@ public class DialogManager */ public DialogConfig getCurrentDialog() { - return this.currentDialogConfig; + return this.currentDialogState.getConfig(); } /** @@ -84,7 +109,7 @@ public class DialogManager */ public IDialogBean getBean() { - return this.currentDialog; + return this.currentDialogState.getDialog(); } /** @@ -94,7 +119,7 @@ public class DialogManager */ public String getIcon() { - return this.currentDialogConfig.getIcon(); + return this.currentDialogState.getConfig().getIcon(); } /** @@ -105,7 +130,7 @@ public class DialogManager public String getErrorMessage() { return Application.getMessage(FacesContext.getCurrentInstance(), - this.currentDialogConfig.getErrorMessageId()); + this.currentDialogState.getConfig().getErrorMessageId()); } /** @@ -115,15 +140,23 @@ public class DialogManager */ public String getTitle() { - String title = this.currentDialogConfig.getTitleId(); + // try and get the title directly from the dialog + String title = this.currentDialogState.getDialog().getTitle(); - if (title != null) + if (title == null) { - title = Application.getMessage(FacesContext.getCurrentInstance(), title); - } - else - { - title = this.currentDialogConfig.getTitle(); + // try and get the title via a message bundle key + title = this.currentDialogState.getConfig().getTitleId(); + + if (title != null) + { + title = Application.getMessage(FacesContext.getCurrentInstance(), title); + } + else + { + // try and get the title from the configuration + title = this.currentDialogState.getConfig().getTitle(); + } } return title; @@ -136,15 +169,23 @@ public class DialogManager */ public String getDescription() { - String desc = this.currentDialogConfig.getDescriptionId(); + // try and get the description directly from the dialog + String desc = this.currentDialogState.getDialog().getDescription(); - if (desc != null) + if (desc == null) { - desc = Application.getMessage(FacesContext.getCurrentInstance(), desc); - } - else - { - desc = this.currentDialogConfig.getDescription(); + // try and get the description via a message bundle key + desc = this.currentDialogState.getConfig().getDescriptionId(); + + if (desc != null) + { + desc = Application.getMessage(FacesContext.getCurrentInstance(), desc); + } + else + { + // try and get the description from the configuration + desc = this.currentDialogState.getConfig().getDescription(); + } } return desc; @@ -158,7 +199,7 @@ public class DialogManager */ public String getActions() { - return this.currentDialogConfig.getActionsConfigId(); + return this.currentDialogState.getConfig().getActionsConfigId(); } /** @@ -168,7 +209,7 @@ public class DialogManager */ public String getPage() { - return this.currentDialogConfig.getPage(); + return this.currentDialogState.getConfig().getPage(); } /** @@ -178,7 +219,7 @@ public class DialogManager */ public boolean isOKButtonVisible() { - return this.currentDialogConfig.isOKButtonVisible(); + return this.currentDialogState.getConfig().isOKButtonVisible(); } /** @@ -191,10 +232,10 @@ public class DialogManager List buttons = null; // get a list of buttons to display from the configuration - List cfgButtons = this.currentDialogConfig.getButtons(); + List cfgButtons = this.currentDialogState.getConfig().getButtons(); // get a list of buttons added dynamically by the dialog - List dynButtons = this.currentDialog.getAdditionalButtons(); + List dynButtons = this.currentDialogState.getDialog().getAdditionalButtons(); if (cfgButtons != null && dynButtons != null) { @@ -223,7 +264,7 @@ public class DialogManager */ public String getCancelButtonLabel() { - return this.currentDialog.getCancelButtonLabel(); + return this.currentDialogState.getDialog().getCancelButtonLabel(); } /** @@ -233,7 +274,7 @@ public class DialogManager */ public String getFinishButtonLabel() { - return this.currentDialog.getFinishButtonLabel(); + return this.currentDialogState.getDialog().getFinishButtonLabel(); } /** @@ -243,7 +284,7 @@ public class DialogManager */ public boolean getFinishButtonDisabled() { - return this.currentDialog.getFinishButtonDisabled(); + return this.currentDialogState.getDialog().getFinishButtonDisabled(); } /** @@ -253,7 +294,7 @@ public class DialogManager */ public String finish() { - return this.currentDialog.finish(); + return this.currentDialogState.getDialog().finish(); } /** @@ -263,6 +304,6 @@ public class DialogManager */ public String cancel() { - return this.currentDialog.cancel(); + return this.currentDialogState.getDialog().cancel(); } } diff --git a/source/java/org/alfresco/web/bean/dialog/DialogState.java b/source/java/org/alfresco/web/bean/dialog/DialogState.java new file mode 100644 index 0000000000..aee2a53ab2 --- /dev/null +++ b/source/java/org/alfresco/web/bean/dialog/DialogState.java @@ -0,0 +1,53 @@ +package org.alfresco.web.bean.dialog; + +import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.config.DialogsConfigElement.DialogConfig; + +/** + * Object responsible for holding the current state of an active dialog. + * + * @author gavinc + */ +public final class DialogState +{ + private DialogConfig config; + private IDialogBean dialog; + + /** + * Default constructor + * + * @param config The configuration for the dialog + * @param dialog The dialog bean instance + */ + public DialogState(DialogConfig config, IDialogBean dialog) + { + this.config = config; + this.dialog = dialog; + } + + /** + * Returns the configuration for the dialog + * + * @return The dialog configuration + */ + public DialogConfig getConfig() + { + return config; + } + + /** + * Returns the bean representing the dialog instance + * + * @return The dialog bean instance + */ + public IDialogBean getDialog() + { + return dialog; + } + + @Override + public String toString() + { + return AlfrescoNavigationHandler.DIALOG_PREFIX + this.config.getName(); + } +} diff --git a/source/java/org/alfresco/web/bean/dialog/IDialogBean.java b/source/java/org/alfresco/web/bean/dialog/IDialogBean.java index fe2e9b59dc..becb29932b 100644 --- a/source/java/org/alfresco/web/bean/dialog/IDialogBean.java +++ b/source/java/org/alfresco/web/bean/dialog/IDialogBean.java @@ -19,6 +19,11 @@ public interface IDialogBean */ public void init(Map parameters); + /** + * Called when the dialog is restored after a nested dialog is closed + */ + public void restored(); + /** * Method handler called when the cancel button of the dialog is pressed * @@ -60,4 +65,22 @@ public interface IDialogBean * @return true if the button should be disabled */ public boolean getFinishButtonDisabled(); + + /** + * Returns the title to be used for the dialog + *

If this returns null the DialogManager will + * lookup the title via the dialog configuration

+ * + * @return The title or null if the title is to be acquired via configuration + */ + public String getTitle(); + + /** + * Returns the description to be used for the dialog + *

If this returns null the DialogManager will + * lookup the description via the dialog configuration

+ * + * @return The title or null if the title is to be acquired via configuration + */ + public String getDescription(); } diff --git a/source/java/org/alfresco/web/bean/generator/HeaderSeparatorGenerator.java b/source/java/org/alfresco/web/bean/generator/HeaderSeparatorGenerator.java index 2cb6e31f9b..8b316dcc42 100644 --- a/source/java/org/alfresco/web/bean/generator/HeaderSeparatorGenerator.java +++ b/source/java/org/alfresco/web/bean/generator/HeaderSeparatorGenerator.java @@ -12,7 +12,6 @@ import org.alfresco.web.ui.repo.component.property.PropertySheetItem; */ public class HeaderSeparatorGenerator extends SeparatorGenerator { - @Override protected String getHtml(UIComponent component, PropertySheetItem item) { String html = "
 " + diff --git a/source/java/org/alfresco/web/bean/generator/HtmlSeparatorGenerator.java b/source/java/org/alfresco/web/bean/generator/HtmlSeparatorGenerator.java new file mode 100644 index 0000000000..3e8153750b --- /dev/null +++ b/source/java/org/alfresco/web/bean/generator/HtmlSeparatorGenerator.java @@ -0,0 +1,79 @@ +package org.alfresco.web.bean.generator; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; + +import org.alfresco.web.ui.repo.component.property.PropertySheetItem; +import org.alfresco.web.ui.repo.component.property.UIPropertySheet; + +/** + * Generates a component to represent a separator. + *

The HTML to be used for the separator is configured via the + * setHtml method. + * + * @author gavinc + */ +public class HtmlSeparatorGenerator extends BaseComponentGenerator +{ + protected String html = "default"; + + /** + * Returns the HTML configured to be used for this separator + * + * @return The HTML to display + */ + public String getHtml() + { + return html; + } + + /** + * Sets the HTML to display for the separator + * + * @param html The HTML + */ + public void setHtml(String html) + { + this.html = html; + } + + @SuppressWarnings("unchecked") + public UIComponent generate(FacesContext context, String id) + { + UIComponent component = this.createOutputTextComponent(context, id); + component.getAttributes().put("escape", Boolean.FALSE); + + return component; + } + + @Override + @SuppressWarnings("unchecked") + protected UIComponent createComponent(FacesContext context, UIPropertySheet propertySheet, + PropertySheetItem item) + { + UIComponent component = this.generate(context, item.getName()); + + // set the HTML to use + component.getAttributes().put("value", getResolvedHtml(component, item)); + + return component; + } + + /** + * Returns the resolved HTML to use for the separator. + *

In the default case we just return the HTML set + * via setHtml however subclasses may choose to generate + * the resulting HTML using a combination of the HTML set + * via setHtml and the given PropertySheetItem. + * + * @param component The JSF component representing the separator + * @param item The separator item + * @return The resolved HTML + */ + protected String getResolvedHtml(UIComponent component, PropertySheetItem item) + { + // In the default case we just return the HTML set via setHtml + + return this.html; + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/web/bean/generator/LabelSeparatorGenerator.java b/source/java/org/alfresco/web/bean/generator/LabelSeparatorGenerator.java new file mode 100644 index 0000000000..7cbaf898c9 --- /dev/null +++ b/source/java/org/alfresco/web/bean/generator/LabelSeparatorGenerator.java @@ -0,0 +1,85 @@ +package org.alfresco.web.bean.generator; + +import javax.faces.component.UIComponent; + +import org.alfresco.web.ui.repo.component.property.PropertySheetItem; + +/** + * Generates a component to represent a separator that uses the + * property sheet display label configuration. The CSS class used + * for the HTML representing the label can also be configured via + * the setStyleClass method. + * + * @author gavinc + */ +public class LabelSeparatorGenerator extends HtmlSeparatorGenerator +{ + protected String style = "margin-top: 6px; margin-bottom: 6px;"; + protected String styleClass; + + /** + * Returns the CSS class configured to be used for this separator + * + * @return The CSS class + */ + public String getStyleClass() + { + return styleClass; + } + + /** + * Sets the CSS class to use for the separator + * + * @param styleClass The CSS class + */ + public void setStyleClass(String styleClass) + { + this.styleClass = styleClass; + } + + /** + * Returns the CSS style configured to be used for this separator + * + * @return The CSS style + */ + public String getStyle() + { + return style; + } + + /** + * Sets the CSS style to use for the separator + * + * @param style The CSS style + */ + public void setStyle(String style) + { + this.style = style; + } + + @Override + protected String getResolvedHtml(UIComponent component, PropertySheetItem item) + { + StringBuilder htmlBuilder = new StringBuilder(" 0) + { + htmlBuilder.append(" class=\""); + htmlBuilder.append(this.styleClass); + htmlBuilder.append("\""); + } + + if (this.style != null && this.style.length() > 0) + { + htmlBuilder.append(" style=\""); + htmlBuilder.append(this.style); + htmlBuilder.append("\""); + } + + // add the display label and close the div + htmlBuilder.append("> "); + htmlBuilder.append(item.getDisplayLabel()); + htmlBuilder.append("

"); + + return htmlBuilder.toString(); + } +} diff --git a/source/java/org/alfresco/web/bean/generator/SeparatorGenerator.java b/source/java/org/alfresco/web/bean/generator/SeparatorGenerator.java index 49076c1fa1..2157229577 100644 --- a/source/java/org/alfresco/web/bean/generator/SeparatorGenerator.java +++ b/source/java/org/alfresco/web/bean/generator/SeparatorGenerator.java @@ -1,49 +1,16 @@ package org.alfresco.web.bean.generator; -import javax.faces.component.UIComponent; -import javax.faces.context.FacesContext; - -import org.alfresco.web.ui.repo.component.property.PropertySheetItem; -import org.alfresco.web.ui.repo.component.property.UIPropertySheet; - /** - * Generates a component to represent a separator. + * Generates a component to represent a separator using the HTML <hr/> element. * * @author gavinc */ -public class SeparatorGenerator extends BaseComponentGenerator +public class SeparatorGenerator extends HtmlSeparatorGenerator { - @SuppressWarnings("unchecked") - public UIComponent generate(FacesContext context, String id) + public SeparatorGenerator() { - UIComponent component = this.createOutputTextComponent(context, id); - component.getAttributes().put("escape", Boolean.FALSE); + // For the standard separator just show a
element - return component; - } - - @Override - @SuppressWarnings("unchecked") - protected UIComponent createComponent(FacesContext context, UIPropertySheet propertySheet, - PropertySheetItem item) - { - UIComponent component = this.generate(context, item.getName()); - - // set the HTML to use - component.getAttributes().put("value", getHtml(component, item)); - - return component; - } - - /** - * Returns the HTML to display for the separator - * - * @param component The JSF component representing the separator - * @param item The separator item - * @return The HTML - */ - protected String getHtml(UIComponent component, PropertySheetItem item) - { - return "

"; + this.html = "

"; } } \ No newline at end of file diff --git a/source/java/org/alfresco/web/bean/repository/TransientNode.java b/source/java/org/alfresco/web/bean/repository/TransientNode.java index 50a2c11e32..9f5332fd8b 100644 --- a/source/java/org/alfresco/web/bean/repository/TransientNode.java +++ b/source/java/org/alfresco/web/bean/repository/TransientNode.java @@ -1,7 +1,9 @@ package org.alfresco.web.bean.repository; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Map; import org.alfresco.error.AlfrescoRuntimeException; @@ -10,6 +12,8 @@ import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; @@ -54,9 +58,6 @@ public class TransientNode extends Node // initialise the node initNode(data); - - if (logger.isDebugEnabled()) - logger.debug("Constructed transient node: " + this); } /** @@ -93,11 +94,64 @@ public class TransientNode extends Node { if (assocDef.isChild()) { - this.childAssociations.put(item, data.get(item)); + // TODO: handle lists of NodeRef's + NodeRef child = null; + Object obj = data.get(item); + if (obj instanceof String) + { + child = new NodeRef((String)obj); + } + else if (obj instanceof NodeRef) + { + child = (NodeRef)obj; + } + else if (obj instanceof List) + { + if (logger.isWarnEnabled()) + logger.warn("0..* child associations are not supported yet"); + } + + if (child != null) + { + // create a child association reference, add it to a list and add the list + // to the list of child associations for this node + List assocs = new ArrayList(1); + ChildAssociationRef childRef = new ChildAssociationRef(assocDef.getName(), this.nodeRef, + null, child); + assocs.add(childRef); + + this.childAssociations.put(item, assocs); + } } else { - this.associations.put(item, data.get(item)); + // TODO: handle lists of NodeRef's + NodeRef target = null; + Object obj = data.get(item); + if (obj instanceof String) + { + target = new NodeRef((String)obj); + } + else if (obj instanceof NodeRef) + { + target = (NodeRef)obj; + } + else if (obj instanceof List) + { + if (logger.isWarnEnabled()) + logger.warn("0..* associations are not supported yet"); + } + + if (target != null) + { + // create a association reference, add it to a list and add the list + // to the list of associations for this node + List assocs = new ArrayList(1); + AssociationRef assocRef = new AssociationRef(this.nodeRef, assocDef.getName(), target); + assocs.add(assocRef); + + this.associations.put(item, assocs); + } } } } @@ -140,7 +194,7 @@ public class TransientNode extends Node // don't reset anything otherwise we'll lose our data // with no way of getting it back!! } - + @Override public String toString() { diff --git a/source/java/org/alfresco/web/bean/users/EmailSpaceUsersDialog.java b/source/java/org/alfresco/web/bean/users/EmailSpaceUsersDialog.java index 53eb16465f..1bf167d1ae 100644 --- a/source/java/org/alfresco/web/bean/users/EmailSpaceUsersDialog.java +++ b/source/java/org/alfresco/web/bean/users/EmailSpaceUsersDialog.java @@ -130,7 +130,7 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis Set mailedAuthorities = new HashSet(usersGroups.size()); - // walk the list of users/groups to notify + // walk the list of users/groups to notify - handle duplicates along the way for (Map node : usersGroups) { String authority = (String)node.get(PROP_USERNAME); @@ -254,31 +254,47 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis tx = Repository.getUserTransaction(context, true); tx.begin(); - // Return all the permissions set against the current node - // for any authentication instance (user/group). - // Then combine them into a single list for each authentication found. + // Return all the permissions set against the current node for any authentication + // instance (user/group), walking the parent space inheritance chain. + // Then combine them into a single list for each authentication found. + String currentAuthority = Application.getCurrentUser(context).getUserName(); Map> permissionMap = new HashMap>(8, 1.0f); - Set permissions = permissionService.getAllSetPermissions(getSpace().getNodeRef()); - for (AccessPermission permission : permissions) + NodeRef spaceRef = getSpace().getNodeRef(); + while (spaceRef != null) { - // we are only interested in Allow and not groups/owner etc. - if (permission.getAccessStatus() == AccessStatus.ALLOWED && - (permission.getAuthorityType() == AuthorityType.USER || - permission.getAuthorityType() == AuthorityType.GROUP || - permission.getAuthorityType() == AuthorityType.GUEST || - permission.getAuthorityType() == AuthorityType.EVERYONE)) + Set permissions = permissionService.getAllSetPermissions(spaceRef); + for (AccessPermission permission : permissions) { - String authority = permission.getAuthority(); - - List userPermissions = permissionMap.get(authority); - if (userPermissions == null) + // we are only interested in Allow and not Guest/Everyone/owner + if (permission.getAccessStatus() == AccessStatus.ALLOWED && + (permission.getAuthorityType() == AuthorityType.USER || + permission.getAuthorityType() == AuthorityType.GROUP)) { - // create for first time - userPermissions = new ArrayList(4); - permissionMap.put(authority, userPermissions); + String authority = permission.getAuthority(); + + if (currentAuthority.equals(authority) == false) + { + List userPermissions = permissionMap.get(authority); + if (userPermissions == null) + { + // create for first time + userPermissions = new ArrayList(4); + permissionMap.put(authority, userPermissions); + } + // add the permission name for this authority + userPermissions.add(permission.getPermission()); + } } - // add the permission name for this authority - userPermissions.add(permission.getPermission()); + } + + // walk parent inheritance chain until root or no longer inherits + if (permissionService.getInheritParentPermissions(spaceRef)) + { + spaceRef = nodeService.getPrimaryParent(spaceRef).getParentRef(); + } + else + { + spaceRef = null; } } @@ -316,79 +332,6 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis } return this.usersGroups; } - - /** - * Build a Map representing a user/group with a set of useful property values required - * by the UIUserGroupPicker UI component. - * - * @param authority User/Group authority - * @param roles Role text for the authority - * - * @return Map - */ - private Map buildAuthorityMap(String authority, String roles) - { - Map node = null; - - if (AuthorityType.getAuthorityType(authority) == AuthorityType.GUEST || - this.personService.personExists(authority)) - { - NodeRef nodeRef = this.personService.getPerson(authority); - if (nodeRef != null) - { - // create our Node representation - node = new MapNode(nodeRef); - - // set data binding properties - // this will also force initialisation of the props now during the UserTransaction - // it is much better for performance to do this now rather than during page bind - Map props = ((MapNode)node).getProperties(); - props.put(PROP_FULLNAME, ((String)props.get("firstName")) + ' ' + ((String)props.get("lastName"))); - props.put(PROP_ICON, WebResources.IMAGE_PERSON); - props.put(PROP_ISGROUP, false); - } - } - else if (AuthorityType.getAuthorityType(authority) == AuthorityType.GROUP) - { - // need a map (dummy node) to represent props for this Group Authority - node = new HashMap(8, 1.0f); - if (authority.startsWith(PermissionService.GROUP_PREFIX) == true) - { - node.put(PROP_FULLNAME, authority.substring(PermissionService.GROUP_PREFIX.length())); - } - else - { - node.put(PROP_FULLNAME, authority); - } - node.put(PROP_USERNAME, authority); - node.put(PROP_ID, authority); - node.put(PROP_ICON, WebResources.IMAGE_GROUP); - node.put(PROP_ISGROUP, true); - node.put(PROP_EXPANDED, false); - } - if (node != null) - { - // add the common properties - node.put(PROP_ROLES, roles); - node.put(PROP_PARENT, null); - - if (this.userGroupLookup.get(authority) != null) - { - // this authority already exists in the list somewhere else - mark as duplicate - node.put(PROP_DUPLICATE, true); - node.put(PROP_SELECTED, false); - } - else - { - // add to table for the first time, not a duplicate - this.userGroupLookup.put(authority, node); - node.put(PROP_DUPLICATE, false); - node.put(PROP_SELECTED, true); - } - } - - return node; - } /** * @return TemplateMailHelperBean instance for this wizard @@ -398,6 +341,29 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis return this.mailHelper; } + /** + * @return true if any authorities are selected, false otherwise + */ + public boolean getFinishButtonDisabled() + { + boolean disabled = true; + + if (this.usersGroups != null) + { + for (Map userGroup : this.usersGroups) + { + if (((Boolean)userGroup.get(PROP_EXPANDED)) == false && + ((Boolean)userGroup.get(PROP_SELECTED)) == true) + { + disabled = false; + break; + } + } + } + + return disabled; + } + // ------------------------------------------------------------------------------ // Action Event Listeners @@ -435,16 +401,25 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis { // expand the list for this group by adding the immediate child authorities boolean selected = (Boolean)userGroup.get(PROP_SELECTED); + String currentAuthority = + Application.getCurrentUser(FacesContext.getCurrentInstance()).getUserName(); Set authorities = authorityService.getContainedAuthorities( null, pickerEvent.Authority, true); for (String authority : authorities) { - Map node = buildAuthorityMap(authority, (String)userGroup.get(PROP_ROLES)); - if (node != null) + if (currentAuthority.equals(authority) == false) { - node.put(PROP_PARENT, userGroup); - node.put(PROP_SELECTED, selected); - this.usersGroups.add(++index, node); + if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER || + AuthorityType.getAuthorityType(authority) == AuthorityType.GROUP) + { + Map node = buildAuthorityMap(authority, (String)userGroup.get(PROP_ROLES)); + if (node != null) + { + node.put(PROP_PARENT, userGroup); + node.put(PROP_SELECTED, selected); + this.usersGroups.add(++index, node); + } + } } } } @@ -494,4 +469,81 @@ public class EmailSpaceUsersDialog extends BaseDialogBean implements IContextLis } } } + + + // ------------------------------------------------------------------------------ + // Private helpers + + /** + * Build a Map representing a user/group with a set of useful property values required + * by the UIUserGroupPicker UI component. + * + * @param authority User/Group authority + * @param roles Role text for the authority + * + * @return Map + */ + private Map buildAuthorityMap(String authority, String roles) + { + Map node = null; + + if (AuthorityType.getAuthorityType(authority) == AuthorityType.GUEST || + this.personService.personExists(authority)) + { + NodeRef nodeRef = this.personService.getPerson(authority); + if (nodeRef != null) + { + // create our Node representation + node = new MapNode(nodeRef); + + // set data binding properties + // this will also force initialisation of the props now during the UserTransaction + // it is much better for performance to do this now rather than during page bind + Map props = ((MapNode)node).getProperties(); + props.put(PROP_FULLNAME, ((String)props.get("firstName")) + ' ' + ((String)props.get("lastName"))); + props.put(PROP_ICON, WebResources.IMAGE_PERSON); + props.put(PROP_ISGROUP, false); + } + } + else if (AuthorityType.getAuthorityType(authority) == AuthorityType.GROUP) + { + // need a map (dummy node) to represent props for this Group Authority + node = new HashMap(8, 1.0f); + if (authority.startsWith(PermissionService.GROUP_PREFIX) == true) + { + node.put(PROP_FULLNAME, authority.substring(PermissionService.GROUP_PREFIX.length())); + } + else + { + node.put(PROP_FULLNAME, authority); + } + node.put(PROP_USERNAME, authority); + node.put(PROP_ID, authority); + node.put(PROP_ICON, WebResources.IMAGE_GROUP); + node.put(PROP_ISGROUP, true); + } + if (node != null) + { + // add the common properties + node.put(PROP_ROLES, roles); + node.put(PROP_PARENT, null); + node.put(PROP_EXPANDED, false); + + if (this.userGroupLookup.get(authority) != null) + { + // this authority already exists in the list somewhere else - mark as duplicate + node.put(PROP_DUPLICATE, true); + node.put(PROP_SELECTED, false); + } + else + { + // add to table for the first time, not a duplicate + this.userGroupLookup.put(authority, node); + node.put(PROP_DUPLICATE, false); + node.put(PROP_SELECTED, true); + } + } + + return node; + } } diff --git a/source/java/org/alfresco/web/bean/wizard/WizardManager.java b/source/java/org/alfresco/web/bean/wizard/WizardManager.java index a967648627..c70115e53b 100644 --- a/source/java/org/alfresco/web/bean/wizard/WizardManager.java +++ b/source/java/org/alfresco/web/bean/wizard/WizardManager.java @@ -26,16 +26,12 @@ import org.apache.commons.logging.LogFactory; * * @author gavinc */ -public class WizardManager +public final class WizardManager { private static Log logger = LogFactory.getLog(WizardManager.class); - protected int currentStep = 1; - protected PageConfig currentPageCfg; - protected WizardConfig currentWizardConfig; - protected IWizardBean currentWizard; - protected List steps; - protected Map currentWizardParams; + private WizardState currentWizardState; + private Map paramsToApply; /** * Action handler used to setup parameters for the wizard being launched @@ -49,7 +45,7 @@ public class WizardManager if (component instanceof UIActionLink) { // store the parameters - this.currentWizardParams = ((UIActionLink)component).getParameterMap(); + this.paramsToApply = ((UIActionLink)component).getParameterMap(); } } @@ -60,31 +56,53 @@ public class WizardManager */ public void setCurrentWizard(WizardConfig config) { - this.currentStep = 1; - this.currentWizardConfig = config; - - String beanName = this.currentWizardConfig.getManagedBean(); - this.currentWizard = (IWizardBean)FacesHelper.getManagedBean( + String beanName = config.getManagedBean(); + IWizardBean wizard = (IWizardBean)FacesHelper.getManagedBean( FacesContext.getCurrentInstance(), beanName); - if (this.currentWizard == null) + if (wizard == null) { throw new AlfrescoRuntimeException("Failed to find managed bean '" + beanName + "'"); } // initialise the managed bean - this.currentWizard.init(this.currentWizardParams); + wizard.init(this.paramsToApply); // reset the current parameters so subsequent wizards don't get them - this.currentWizardParams = null; + this.paramsToApply = null; - // get the steps for the wizard - this.steps = this.currentWizardConfig.getStepsAsList(); + // create the WizardState object + this.currentWizardState = new WizardState(config, wizard); // setup the first step determineCurrentPage(); } + /** + * Returns the state of the currently active wizard + * + * @return Current wizard's state + */ + public WizardState getState() + { + return this.currentWizardState; + } + + /** + * Restores the wizard represented by the given WizardState object. + * NOTE: The wizard's restored() method is also called during this + * method. + * + * @param state The WizardState for the wizard to restore + */ + public void restoreState(WizardState state) + { + this.currentWizardState = state; + + // retrieve the wizard and call it's restored() method + this.currentWizardState.getWizard().restored(); + } + /** * Returns the config for the current wizard * @@ -92,7 +110,7 @@ public class WizardManager */ public WizardConfig getCurrentWizard() { - return this.currentWizardConfig; + return this.currentWizardState.getConfig(); } /** @@ -102,7 +120,7 @@ public class WizardManager */ public IWizardBean getBean() { - return this.currentWizard; + return this.currentWizardState.getWizard(); } /** @@ -112,7 +130,7 @@ public class WizardManager */ public String getIcon() { - return this.currentWizardConfig.getIcon(); + return this.currentWizardState.getConfig().getIcon(); } /** @@ -123,7 +141,7 @@ public class WizardManager public String getErrorMessage() { return Application.getMessage(FacesContext.getCurrentInstance(), - this.currentWizardConfig.getErrorMessageId()); + this.currentWizardState.getConfig().getErrorMessageId()); } /** @@ -133,15 +151,23 @@ public class WizardManager */ public String getTitle() { - String title = this.currentWizardConfig.getTitleId(); + // try and get the title directly from the wizard + String title = this.currentWizardState.getWizard().getTitle(); - if (title != null) + if (title == null) { - title = Application.getMessage(FacesContext.getCurrentInstance(), title); - } - else - { - title = this.currentWizardConfig.getTitle(); + // try and get the title via a message bundle key + title = this.currentWizardState.getConfig().getTitleId(); + + if (title != null) + { + title = Application.getMessage(FacesContext.getCurrentInstance(), title); + } + else + { + // try and get the title from the configuration + title = this.currentWizardState.getConfig().getTitle(); + } } return title; @@ -154,15 +180,23 @@ public class WizardManager */ public String getDescription() { - String desc = this.currentWizardConfig.getDescriptionId(); + // try and get the description directly from the dialog + String desc = this.currentWizardState.getWizard().getDescription(); - if (desc != null) + if (desc == null) { - desc = Application.getMessage(FacesContext.getCurrentInstance(), desc); - } - else - { - desc = this.currentWizardConfig.getDescription(); + // try and get the description via a message bundle key + desc = this.currentWizardState.getConfig().getDescriptionId(); + + if (desc != null) + { + desc = Application.getMessage(FacesContext.getCurrentInstance(), desc); + } + else + { + // try and get the description from the configuration + desc = this.currentWizardState.getConfig().getDescription(); + } } return desc; @@ -175,7 +209,7 @@ public class WizardManager */ public int getCurrentStep() { - return this.currentStep; + return this.currentWizardState.getCurrentStep(); } /** @@ -185,7 +219,7 @@ public class WizardManager */ public String getCurrentStepAsString() { - return Integer.toString(this.currentStep); + return Integer.toString(this.currentWizardState.getCurrentStep()); } /** @@ -197,7 +231,8 @@ public class WizardManager */ public String getCurrentStepName() { - return ((StepConfig)this.steps.get(this.currentStep-1)).getName(); + return ((StepConfig)this.currentWizardState.getSteps().get( + this.currentWizardState.getCurrentStep()-1)).getName(); } /** @@ -207,12 +242,12 @@ public class WizardManager */ public List getStepItems() { - List items = new ArrayList(this.steps.size()); + List items = new ArrayList(this.currentWizardState.getSteps().size()); - for (int x = 0; x < this.steps.size(); x++) + for (int x = 0; x < this.currentWizardState.getSteps().size(); x++) { String uiStepNumber = Integer.toString(x + 1); - StepConfig stepCfg = this.steps.get(x); + StepConfig stepCfg = this.currentWizardState.getSteps().get(x); UIListItem item = new UIListItem(); item.setValue(uiStepNumber); @@ -255,7 +290,7 @@ public class WizardManager */ public String getPage() { - return this.currentPageCfg.getPath(); + return this.currentWizardState.getCurrentPageCfg().getPath(); } /** @@ -265,7 +300,7 @@ public class WizardManager */ public String getStepTitle() { - String title = this.currentPageCfg.getTitleId(); + String title = this.currentWizardState.getCurrentPageCfg().getTitleId(); if (title != null) { @@ -273,7 +308,7 @@ public class WizardManager } else { - title = this.currentPageCfg.getTitle(); + title = this.currentWizardState.getCurrentPageCfg().getTitle(); } return title; @@ -286,7 +321,7 @@ public class WizardManager */ public String getStepDescription() { - String desc = this.currentPageCfg.getDescriptionId(); + String desc = this.currentWizardState.getCurrentPageCfg().getDescriptionId(); if (desc != null) { @@ -294,7 +329,7 @@ public class WizardManager } else { - desc = this.currentPageCfg.getDescription(); + desc = this.currentWizardState.getCurrentPageCfg().getDescription(); } return desc; @@ -307,7 +342,7 @@ public class WizardManager */ public String getStepInstructions() { - String instruction = this.currentPageCfg.getInstructionId(); + String instruction = this.currentWizardState.getCurrentPageCfg().getInstructionId(); if (instruction != null) { @@ -315,7 +350,7 @@ public class WizardManager } else { - instruction = this.currentPageCfg.getInstruction(); + instruction = this.currentWizardState.getCurrentPageCfg().getInstruction(); } return instruction; @@ -328,7 +363,7 @@ public class WizardManager */ public String getNextButtonLabel() { - return this.currentWizard.getNextButtonLabel(); + return this.currentWizardState.getWizard().getNextButtonLabel(); } /** @@ -338,13 +373,13 @@ public class WizardManager */ public boolean getNextButtonDisabled() { - if (this.currentStep == this.steps.size()) + if (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size()) { return true; } else { - return this.currentWizard.getNextButtonDisabled(); + return this.currentWizardState.getWizard().getNextButtonDisabled(); } } @@ -355,7 +390,7 @@ public class WizardManager */ public String getBackButtonLabel() { - return this.currentWizard.getBackButtonLabel(); + return this.currentWizardState.getWizard().getBackButtonLabel(); } /** @@ -365,7 +400,7 @@ public class WizardManager */ public boolean getBackButtonDisabled() { - if (this.currentStep == 1) + if (this.currentWizardState.getCurrentStep() == 1) { return true; } @@ -382,7 +417,7 @@ public class WizardManager */ public String getCancelButtonLabel() { - return this.currentWizard.getCancelButtonLabel(); + return this.currentWizardState.getWizard().getCancelButtonLabel(); } /** @@ -392,7 +427,7 @@ public class WizardManager */ public String getFinishButtonLabel() { - return this.currentWizard.getFinishButtonLabel(); + return this.currentWizardState.getWizard().getFinishButtonLabel(); } /** @@ -402,13 +437,13 @@ public class WizardManager */ public boolean getFinishButtonDisabled() { - if (this.currentStep == this.steps.size()) + if (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size()) { return false; } else { - return this.currentWizard.getFinishButtonDisabled(); + return this.currentWizardState.getWizard().getFinishButtonDisabled(); } } @@ -419,13 +454,16 @@ public class WizardManager */ public void next() { - this.currentStep++; + // calculate next step number and update wizard state + int currentStep = this.currentWizardState.getCurrentStep(); + currentStep++; + this.currentWizardState.setCurrentStep(currentStep); if (logger.isDebugEnabled()) - logger.debug("next called, current step is now: " + this.currentStep); + logger.debug("next called, current step is now: " + this.currentWizardState.getCurrentStep()); // tell the wizard the next button has been pressed - this.currentWizard.next(); + this.currentWizardState.getWizard().next(); determineCurrentPage(); } @@ -437,13 +475,16 @@ public class WizardManager */ public void back() { - this.currentStep--; + // calculate next step number and update wizard state + int currentStep = this.currentWizardState.getCurrentStep(); + currentStep--; + this.currentWizardState.setCurrentStep(currentStep); if (logger.isDebugEnabled()) - logger.debug("back called, current step is now: " + this.currentStep); + logger.debug("back called, current step is now: " + this.currentWizardState.getCurrentStep()); // tell the wizard the back button has been pressed - this.currentWizard.back(); + this.currentWizardState.getWizard().back(); determineCurrentPage(); } @@ -455,7 +496,7 @@ public class WizardManager */ public String finish() { - return this.currentWizard.finish(); + return this.currentWizardState.getWizard().finish(); } /** @@ -465,7 +506,7 @@ public class WizardManager */ public String cancel() { - return this.currentWizard.cancel(); + return this.currentWizardState.getWizard().cancel(); } /** @@ -473,10 +514,14 @@ public class WizardManager */ protected void determineCurrentPage() { - this.currentPageCfg = null; + // reset the current page config in the state object + this.currentWizardState.setCurrentPageCfg(null); + + PageConfig currentPageCfg = null; // get the config for the current step position - StepConfig stepCfg = this.steps.get(this.currentStep-1); + StepConfig stepCfg = this.currentWizardState.getSteps().get( + this.currentWizardState.getCurrentStep()-1); // is the step conditional? if (stepCfg.hasConditionalPages()) @@ -497,25 +542,28 @@ public class WizardManager Object obj = vb.getValue(context); if (obj instanceof Boolean && ((Boolean)obj).booleanValue()) { - this.currentPageCfg = pageCfg; + currentPageCfg = pageCfg; break; } } } // if none of the conditions passed use the default page - if (this.currentPageCfg == null) + if (currentPageCfg == null) { - this.currentPageCfg = stepCfg.getDefaultPage(); + currentPageCfg = stepCfg.getDefaultPage(); } - if (this.currentPageCfg == null) + if (currentPageCfg == null) { throw new AlfrescoRuntimeException("Failed to determine page for step '" + stepCfg.getName() + "'. Make sure a default page is configured."); } + // save the current page config in the state object + this.currentWizardState.setCurrentPageCfg(currentPageCfg); + if (logger.isDebugEnabled()) - logger.debug("Config for current page: " + this.currentPageCfg); + logger.debug("Config for current page: " + this.currentWizardState.getCurrentPageCfg()); } } diff --git a/source/java/org/alfresco/web/bean/wizard/WizardState.java b/source/java/org/alfresco/web/bean/wizard/WizardState.java new file mode 100644 index 0000000000..d006e8f342 --- /dev/null +++ b/source/java/org/alfresco/web/bean/wizard/WizardState.java @@ -0,0 +1,113 @@ +package org.alfresco.web.bean.wizard; + +import java.util.List; + +import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.config.WizardsConfigElement.PageConfig; +import org.alfresco.web.config.WizardsConfigElement.StepConfig; +import org.alfresco.web.config.WizardsConfigElement.WizardConfig; + +/** + * Object responsible for holding the current state of an active wizard. + * + * @author gavinc + */ +public final class WizardState +{ + private int currentStep = 1; + private PageConfig currentPageCfg; + private WizardConfig config; + private IWizardBean wizard; + private List steps; + + /** + * Default constructor + * + * @param config The configuration for the wizard + * @param wizard The wizard bean instance + */ + public WizardState(WizardConfig config, IWizardBean wizard) + { + this.config = config; + this.wizard = wizard; + + this.steps = this.config.getStepsAsList(); + } + + /** + * Sets the configuration for the current page of the wizard + * + * @param currentPageCfg The configuration + */ + public void setCurrentPageCfg(PageConfig currentPageCfg) + { + this.currentPageCfg = currentPageCfg; + } + + /** + * Sets the current step the wizard is on + * + * @param currentStep The current step number + */ + public void setCurrentStep(int currentStep) + { + this.currentStep = currentStep; + } + + /** + * Returns the wizard bean instance + * + * @return The wizard bean instance + */ + public IWizardBean getWizard() + { + return this.wizard; + } + + /** + * Returns the configuration for the current wizard + * + * @return The wizard configuration + */ + public WizardConfig getConfig() + { + return this.config; + } + + /** + * Returns the configuration for the current page of the wizard + * + * @return The current page configuration + */ + public PageConfig getCurrentPageCfg() + { + return currentPageCfg; + } + + /** + * The current step the wizard is on + * + * @return The current wizard step + */ + public int getCurrentStep() + { + return currentStep; + } + + /** + * Returns the list of steps the wizard has + * + * @return List of wizard steps + */ + public List getSteps() + { + return steps; + } + + @Override + public String toString() + { + return AlfrescoNavigationHandler.WIZARD_PREFIX + this.config.getName() + + "[" + this.currentStep + "]"; + } +} diff --git a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java new file mode 100644 index 0000000000..936199c415 --- /dev/null +++ b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java @@ -0,0 +1,667 @@ +package org.alfresco.web.bean.workflow; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; +import javax.transaction.UserTransaction; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.workflow.WorkflowInstance; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; +import org.alfresco.service.cmr.workflow.WorkflowTransition; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.dialog.BaseDialogBean; +import org.alfresco.web.bean.repository.MapNode; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.NodePropertyResolver; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.repository.TransientNode; +import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIActionLink; +import org.alfresco.web.ui.common.component.data.UIRichList; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Bean implementation for the "Manage Task" dialog. + * + * @author gavinc + */ +public class ManageTaskDialog extends BaseDialogBean +{ + protected WorkflowService workflowService; + protected Node taskNode; + protected WorkflowTask task; + protected WorkflowInstance workflowInstance; + protected WorkflowTransition[] transitions; + protected NodeRef workflowPackage; + protected List resources; + protected TaskCompleteResolver completeResolver = new TaskCompleteResolver(); + protected UIRichList packageItemsRichList; + protected List packageItemsToAdd; + protected List packageItemsToRemove; + protected String[] itemsToAdd; + protected boolean isItemBeingAdded = false; + + protected final Log logger = LogFactory.getLog(getClass()); + + protected static final String ID_PREFIX = "transition_"; + protected static final String CLIENT_ID_PREFIX = AlfrescoNavigationHandler.DIALOG_PREFIX + ID_PREFIX; + + // ------------------------------------------------------------------------------ + // Dialog implementation + + @Override + public void init(Map parameters) + { + super.init(parameters); + + // reset variables + this.task = null; + this.taskNode = null; + this.workflowInstance = null; + this.transitions = null; + this.workflowPackage = null; + this.resources = null; + this.itemsToAdd = null; + this.packageItemsToAdd = null; + this.packageItemsToRemove = null; + this.isItemBeingAdded = false; + if (this.packageItemsRichList != null) + { + this.packageItemsRichList.setValue(null); + this.packageItemsRichList = null; + } + + // get the task details + String taskId = this.parameters.get("id"); + this.task = this.workflowService.getTaskById(taskId); + + if (this.task != null) + { + // setup a transient node to represent the task we're managing + WorkflowTaskDefinition taskDef = this.task.definition; + this.taskNode = new TransientNode(taskDef.metadata.getName(), + "task_" + System.currentTimeMillis(), this.task.properties); + + // get access to the workflow instance for the task + this.workflowInstance = this.task.path.instance; + + // setup the workflow package for the task + Serializable obj = this.task.properties.get(WorkflowModel.ASSOC_PACKAGE); + // TODO: remove this workaroud where JBPM may return a String and not the NodeRef + if (obj instanceof NodeRef) + { + this.workflowPackage = (NodeRef)obj; + } + else if (obj instanceof String) + { + this.workflowPackage = new NodeRef((String)obj); + } + + if (logger.isDebugEnabled()) + { + logger.debug("Task: " + this.task); + logger.debug("Trasient node: " + this.taskNode); + logger.debug("Workflow package: " + this.workflowPackage ); + } + } + } + + @Override + public void restored() + { + // reset the workflow package rich list so everything gets re-evaluated + if (this.packageItemsRichList != null) + { + this.packageItemsRichList.setValue(null); + this.packageItemsRichList = null; + } + } + + @Override + protected String finishImpl(FacesContext context, String outcome) + throws Exception + { + if (logger.isDebugEnabled()) + logger.debug("Saving task: " + this.task.id); + + // prepare the edited parameters for saving + Map params = WorkflowBean.prepareTaskParams(this.taskNode); + + if (logger.isDebugEnabled()) + logger.debug("Saving task with parameters: " + params); + + // remove any items the user selected to remove + if (this.workflowPackage != null && this.packageItemsToRemove != null && + this.packageItemsToRemove.size() > 0) + { + for (String removedItem : this.packageItemsToRemove) + { + this.nodeService.removeChild(this.workflowPackage, new NodeRef(removedItem)); + } + } + + // add any items the user selected to add + if (this.workflowPackage != null && this.packageItemsToAdd != null && + this.packageItemsToAdd.size() > 0) + { + for (String addedItem : this.packageItemsToAdd) + { + NodeRef addedNodeRef = new NodeRef(addedItem); + this.nodeService.addChild(this.workflowPackage, addedNodeRef, + ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, + QName.createValidLocalName((String)this.nodeService.getProperty( + addedNodeRef, ContentModel.PROP_NAME)))); + } + } + + // update the task with the updated parameters + this.workflowService.updateTask(this.task.id, params, null, null); + + return outcome; + } + + @Override + public List getAdditionalButtons() + { + List buttons = null; + + if (this.task != null) + { + // get the transitions available from this task and + // show them in the dialog as additional buttons + this.transitions = this.task.path.node.transitions; + + if (this.transitions != null) + { + buttons = new ArrayList(this.transitions.length); + + for (WorkflowTransition trans : this.transitions) + { + buttons.add(new DialogButtonConfig(ID_PREFIX + trans.title, trans.title, null, + "#{DialogManager.bean.transition}", "false", null)); + } + } + } + + return buttons; + } + + @Override + public String getFinishButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "save"); + } + + @Override + public boolean getFinishButtonDisabled() + { + return false; + } + + @Override + public String getTitle() + { + String titleStart = Application.getMessage(FacesContext.getCurrentInstance(), "manage_task_title"); + + return titleStart + ": " + this.task.title; + } + + @Override + public String getDescription() + { + return this.task.description; + } + + // ------------------------------------------------------------------------------ + // Event handlers + + @SuppressWarnings("unused") + public String transition() + { + String outcome = getDefaultFinishOutcome(); + + if (logger.isDebugEnabled()) + logger.debug("Transitioning task: " + this.task.id); + + // to find out which transition button was pressed we need + // to look for the button's id in the request parameters, + // the first non-null result is the button that was pressed. + FacesContext context = FacesContext.getCurrentInstance(); + Map reqParams = context.getExternalContext().getRequestParameterMap(); + + String selectedTransition = null; + for (WorkflowTransition trans : this.transitions) + { + Object result = reqParams.get(CLIENT_ID_PREFIX + trans.title); + if (result != null) + { + // this was the button that was pressed + selectedTransition = trans.id; + break; + } + } + + if (selectedTransition != null) + { + UserTransaction tx = null; + + try + { + tx = Repository.getUserTransaction(context); + tx.begin(); + + // prepare the edited parameters for saving + Map params = WorkflowBean.prepareTaskParams(this.taskNode); + + if (logger.isDebugEnabled()) + logger.debug("Transitioning task with parameters: " + params); + + // update the task with the updated parameters + this.workflowService.updateTask(this.task.id, params, null, null); + + // signal the selected transition to the workflow task + this.workflowService.endTask(this.task.id, selectedTransition); + + // commit the changes + tx.commit(); + + if (logger.isDebugEnabled()) + logger.debug("Ended task with transition: " + selectedTransition); + } + catch (Throwable e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage(formatErrorMessage(e), e); + outcome = this.getErrorOutcome(e); + } + } + + return outcome; + } + + /** + * Prepares the dialog to allow the user to add an item to the workflow package + * + * @param event The event + */ + public void prepareForAdd(ActionEvent event) + { + this.isItemBeingAdded = true; + } + + /** + * Cancels the adding of an item to the workflow package + * + * @param event The event + */ + public void cancelAddPackageItems(ActionEvent event) + { + this.isItemBeingAdded = false; + } + + /** + * Adds an item to the workflow package + * + * @param event The event + */ + public void addPackageItems(ActionEvent event) + { + if (this.itemsToAdd != null) + { + if (this.packageItemsToAdd == null) + { + // create the list of items to add if necessary + this.packageItemsToAdd = new ArrayList(this.itemsToAdd.length); + } + + for (String item : this.itemsToAdd) + { + // if this item is in the remove list it means it was there originally + // and has now been re-added, as a result we don't need to do anything + // to the original workflow package, therefore remove from the remove list + if (this.packageItemsToRemove != null && this.packageItemsToRemove.contains(item)) + { + this.packageItemsToRemove.remove(item); + + if (logger.isDebugEnabled()) + logger.debug("Removed item from the removed list: " + item); + } + else + { + this.packageItemsToAdd.add(item); + + if (logger.isDebugEnabled()) + logger.debug("Added item to the added list: " + item); + } + } + + // reset the rich list so it re-renders + this.packageItemsRichList.setValue(null); + } + + this.isItemBeingAdded = false; + this.itemsToAdd = null; + } + + /** + * Removes an item from the workflow package + * + * @param event The event containing a reference to the item to remove + */ + public void removePackageItem(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String nodeRef = new NodeRef(Repository.getStoreRef(), params.get("id")).toString(); + + if (this.packageItemsToAdd != null && this.packageItemsToAdd.contains(nodeRef)) + { + // remove the item from the added list if it was added in this dialog session + this.packageItemsToAdd.remove(nodeRef); + + if (logger.isDebugEnabled()) + logger.debug("Removed item from the added list: " + nodeRef); + } + else + { + // add the node to the list of items to remove + if (this.packageItemsToRemove == null) + { + this.packageItemsToRemove = new ArrayList(1); + } + + this.packageItemsToRemove.add(nodeRef); + + if (logger.isDebugEnabled()) + logger.debug("Added item to the removed list: " + nodeRef); + } + + // reset the rich list so it re-renders + this.packageItemsRichList.setValue(null); + } + + /** + * Toggles the complete flag for a workflow package item + * + * @param event The event containing a reference to the item to toggle the status for + */ + public void togglePackageItemComplete(ActionEvent event) + { + // TODO: implement this! + } + + // ------------------------------------------------------------------------------ + // Bean Getters and Setters + + /** + * Returns a String array of NodeRef's that are being added to the workflow package + * + * @return String array of NodeRef's + */ + public String[] getItemsToAdd() + { + return this.itemsToAdd; + } + + /** + * Sets the NodeRef's to add as items to the workflow package + * + * @param itemsToAdd NodeRef's to add to the workflow package + */ + public void setItemsToAdd(String[] itemsToAdd) + { + this.itemsToAdd = itemsToAdd; + } + + /** + * Determines whether an item is currently being added to the workflow package + * + * @return true if an item is being added + */ + public boolean isItemBeingAdded() + { + return this.isItemBeingAdded; + } + + /** + * Sets the rich list being used for the workflow package items + * + * @param richList The rich list instance + */ + public void setPackageItemsRichList(UIRichList richList) + { + this.packageItemsRichList = richList; + } + + /** + * Returns the rich list being used for the workflow package items + * + * @return The rich list instance + */ + public UIRichList getPackageItemsRichList() + { + return this.packageItemsRichList; + } + + /** + * Returns the Node representing the task + * + * @return The node + */ + public Node getTaskNode() + { + return this.taskNode; + } + + /** + * Returns the WorkflowInstance that the current task belongs to + * + * @return The workflow instance + */ + public WorkflowInstance getWorkflowInstance() + { + return this.workflowInstance; + } + + /** + * Returns the action group the current task uses for the workflow package + * + * @return action group id + */ + public String getPackageActionGroup() + { + return (String)this.task.properties.get( + WorkflowModel.PROP_PACKAGE_ACTION_GROUP); + } + + /** + * Returns the action group the current task uses for each workflow package item + * + * @return action group id + */ + public String getPackageItemActionGroup() + { + return (String)this.task.properties.get( + WorkflowModel.PROP_PACKAGE_ITEM_ACTION_GROUP); + } + + /** + * Returns a list of resources associated with this task + * i.e. the children of the workflow package + * + * @return The list of nodes + */ + public List getResources() + { + this.resources = new ArrayList(4); + + if (this.workflowPackage != null) + { + UserTransaction tx = null; + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context, true); + tx.begin(); + + // get existing workflow package items + List childRefs = this.nodeService.getChildAssocs( + this.workflowPackage, ContentModel.ASSOC_CONTAINS, + RegexQNamePattern.MATCH_ALL); + + for (ChildAssociationRef ref: childRefs) + { + // create our Node representation from the NodeRef + NodeRef nodeRef = ref.getChildRef(); + + if (this.nodeService.exists(nodeRef)) + { + // find it's type so we can see if it's a node we are interested in + QName type = this.nodeService.getType(nodeRef); + + // make sure the type is defined in the data dictionary + TypeDefinition typeDef = this.dictionaryService.getType(type); + + if (typeDef != null) + { + // look for content nodes or links to content + // NOTE: folders within workflow packages are ignored for now + if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) || + ContentModel.TYPE_FILELINK.equals(type)) + { + // if the node is not in the removed list then add create the + // client side representation and add to the list + if (this.packageItemsToRemove == null || + this.packageItemsToRemove.contains(nodeRef.toString()) == false) + { + createAndAddNode(nodeRef); + } + } + } + else + { + if (logger.isWarnEnabled()) + logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type); + } + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); + } + } + + // now iterate through the items to add list and add them to the list of resources + if (this.packageItemsToAdd != null) + { + for (String newItem : this.packageItemsToAdd) + { + NodeRef nodeRef = new NodeRef(newItem); + if (this.nodeService.exists(nodeRef)) + { + // we know the type is correct as this was added as a result of a query + // for all content items so just add the item to the resources list + createAndAddNode(nodeRef); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); + } + } + } + + // commit the transaction + tx.commit(); + } + catch (Throwable err) + { + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); + this.resources = Collections.emptyList(); + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + } + } + else if (logger.isDebugEnabled()) + { + logger.debug("Failed to find workflow package for task: " + this.task.id); + } + + return this.resources; + } + + /** + * Sets the workflow service to use + * + * @param workflowService + * WorkflowService instance + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + // ------------------------------------------------------------------------------ + // Helper methods + + protected void createAndAddNode(NodeRef nodeRef) + { + // create our Node representation + MapNode node = new MapNode(nodeRef, this.nodeService, true); + this.browseBean.setupCommonBindingProperties(node); + + // add property resolvers to show path information + node.addPropertyResolver("path", this.browseBean.resolverPath); + node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath); + + // add a property resolver to indicate whether the item has been completed or not +// node.addPropertyResolver("completed", this.completeResolver); + + this.resources.add(node); + } + + // ------------------------------------------------------------------------------ + // Inner classes + + /** + * Property resolver to determine if the given node has been flagged as complete + */ + protected class TaskCompleteResolver implements NodePropertyResolver + { + public Object get(Node node) + { + String result = Application.getMessage(FacesContext.getCurrentInstance(), "no"); + + List completedItems = (List)task.properties.get( + WorkflowModel.PROP_COMPLETED_ITEMS); + + if (completedItems != null && completedItems.size() > 0 && + completedItems.contains(node.getNodeRef())) + { + result = Application.getMessage(FacesContext.getCurrentInstance(), "yes"); + } + + return result; + } + } +} diff --git a/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java deleted file mode 100644 index 05842b6c22..0000000000 --- a/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java +++ /dev/null @@ -1,476 +0,0 @@ -package org.alfresco.web.bean.workflow; - -import java.io.Serializable; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import javax.faces.context.FacesContext; -import javax.faces.event.ActionEvent; -import javax.transaction.UserTransaction; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.workflow.WorkflowModel; -import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.cmr.workflow.WorkflowTask; -import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; -import org.alfresco.service.cmr.workflow.WorkflowTransition; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.RegexQNamePattern; -import org.alfresco.web.app.Application; -import org.alfresco.web.bean.dialog.BaseDialogBean; -import org.alfresco.web.bean.repository.MapNode; -import org.alfresco.web.bean.repository.Node; -import org.alfresco.web.bean.repository.NodePropertyResolver; -import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.bean.repository.TransientNode; -import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig; -import org.alfresco.web.ui.common.Utils; -import org.alfresco.web.ui.common.component.UIActionLink; -import org.alfresco.web.ui.common.component.data.UIRichList; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Bean implementation for the "Manage WorkItem" dialog. - * - * @author gavinc - */ -public class ManageWorkItemDialog extends BaseDialogBean -{ - protected WorkflowService workflowService; - protected Node workItemNode; - protected WorkflowTask workItem; - protected WorkflowTransition[] transitions; - protected List resources; - protected WorkItemCompleteResolver completeResolver = new WorkItemCompleteResolver(); - protected UIRichList packageItemsRichList; - - protected static final String ID_PREFIX = "transition_"; - protected static final String CLIENT_ID_PREFIX = "dialog:" + ID_PREFIX; - - private static final Log logger = LogFactory.getLog(ManageWorkItemDialog.class); - - // ------------------------------------------------------------------------------ - // Dialog implementation - - @Override - public void init(Map parameters) - { - super.init(parameters); - - String taskId = this.parameters.get("id"); - this.workItem = this.workflowService.getTaskById(taskId); - - if (this.workItem != null) - { - // setup a transient node to represent the work item we're managing - WorkflowTaskDefinition taskDef = this.workItem.definition; - this.workItemNode = new TransientNode(taskDef.metadata.getName(), - "task_" + System.currentTimeMillis(), this.workItem.properties); - } - } - - @Override - protected String finishImpl(FacesContext context, String outcome) - throws Exception - { - if (logger.isDebugEnabled()) - logger.debug("Saving work item: " + this.workItemNode.getId()); - - // prepare the edited parameters for saving - Map params = WorkflowBean.prepareWorkItemParams(this.workItemNode); - - // update the task with the updated parameters - this.workflowService.updateTask(this.workItem.id, params, null, null); - - return outcome; - } - - @Override - public List getAdditionalButtons() - { - List buttons = null; - - if (this.workItem != null) - { - // get the transitions available from this work item and - // show them in the dialog as additional buttons - this.transitions = this.workItem.path.node.transitions; - - if (this.transitions != null) - { - buttons = new ArrayList(this.transitions.length); - - for (WorkflowTransition trans : this.transitions) - { - buttons.add(new DialogButtonConfig(ID_PREFIX + trans.title, trans.title, null, - "#{DialogManager.bean.transition}", "false", null)); - } - } - } - - return buttons; - } - - @Override - public String getFinishButtonLabel() - { - return Application.getMessage(FacesContext.getCurrentInstance(), "save"); - } - - @Override - public boolean getFinishButtonDisabled() - { - return false; - } - - // ------------------------------------------------------------------------------ - // Event handlers - - @SuppressWarnings("unused") - public String transition() - { - String outcome = getDefaultFinishOutcome(); - - if (logger.isDebugEnabled()) - logger.debug("Transitioning work item: " + this.workItemNode.getId()); - - // to find out which transition button was pressed we need - // to look for the button's id in the request parameters, - // the first non-null result is the button that was pressed. - FacesContext context = FacesContext.getCurrentInstance(); - Map reqParams = context.getExternalContext().getRequestParameterMap(); - - String selectedTransition = null; - for (WorkflowTransition trans : this.transitions) - { - Object result = reqParams.get(CLIENT_ID_PREFIX + trans.title); - if (result != null) - { - // this was the button that was pressed - selectedTransition = trans.id; - break; - } - } - - if (selectedTransition != null) - { - UserTransaction tx = null; - - try - { - tx = Repository.getUserTransaction(context); - tx.begin(); - - // prepare the edited parameters for saving - Map params = WorkflowBean.prepareWorkItemParams(this.workItemNode); - - // update the task with the updated parameters - this.workflowService.updateTask(this.workItem.id, params, null, null); - - // signal the selected transition to the workflow task - this.workflowService.endTask(this.workItem.id, selectedTransition); - - // commit the changes - tx.commit(); - - if (logger.isDebugEnabled()) - logger.debug("Ended work item with transition: " + selectedTransition); - } - catch (Throwable e) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} - Utils.addErrorMessage(formatErrorMessage(e), e); - outcome = this.getErrorOutcome(e); - } - } - - return outcome; - } - - /** - * Removes an item from the workflow package - * - * @param event The event containing a reference to the item to remove - */ - public void removePackageItem(ActionEvent event) - { - logger.info("remove package item: " + event); - } - - /** - * Toggles the complete flag for a workflow package item - * - * @param event The event containing a reference to the item to toggle the status for - */ - public void togglePackageItemComplete(ActionEvent event) - { - UserTransaction tx = null; - try - { - FacesContext context = FacesContext.getCurrentInstance(); - tx = Repository.getUserTransaction(context); - tx.begin(); - - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - - // create the node ref for the item we are toggling - NodeRef nodeRef = new NodeRef(Repository.getStoreRef(), - (String)params.get("id")); - - // get the existing list of completed items - List completedItems = (List)this.workItem.properties.get( - WorkflowModel.PROP_COMPLETED_ITEMS); - - if (completedItems == null) - { - // if it doesn't exist yet create the list and add the noderef - completedItems = new ArrayList(1); - completedItems.add(nodeRef); - this.workItem.properties.put(WorkflowModel.PROP_COMPLETED_ITEMS, - (Serializable)completedItems); - } - else - { - if (completedItems.contains(nodeRef)) - { - // the item is already in the list remove it - completedItems.remove(nodeRef); - - // NOTE: There is a bug somwehere which causes the list to be - // returned as a byte array instead of a list if an empty - // list is persisted, therefore if the list is now empty - // set the completed items back to null - if (completedItems.size() == 0) - { - this.workItem.properties.put(WorkflowModel.PROP_COMPLETED_ITEMS, null); - } - } - else - { - // the noderef is not in the list yet so just add it - completedItems.add(nodeRef); - } - } - - // update the task with the updated parameters - this.workflowService.updateTask(this.workItem.id, this.workItem.properties, - null, null); - - // commit the transaction - tx.commit(); - - // reset the rich list if the change was successful - this.packageItemsRichList.setValue(null); - } - catch (Throwable err) - { - Utils.addErrorMessage(MessageFormat.format(Application.getMessage( - FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); - this.resources = Collections.emptyList(); - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} - } - } - - // ------------------------------------------------------------------------------ - // Bean Getters and Setters - - /** - * Sets the rich list being used for the workflow package items - * - * @param richList The rich list instance - */ - public void setPackageItemsRichList(UIRichList richList) - { - this.packageItemsRichList = richList; - } - - /** - * Returns the rich list being used for the workflow package items - * - * @return The rich list instance - */ - public UIRichList getPackageItemsRichList() - { - return this.packageItemsRichList; - } - - /** - * Returns the Node representing the work item - * - * @return The node - */ - public Node getWorkItemNode() - { - return this.workItemNode; - } - - /** - * Returns the action group the current task uses for the workflow package - * - * @return action group id - */ - public String getPackageActionGroup() - { - return (String)this.workItem.properties.get( - WorkflowModel.PROP_PACKAGE_ACTION_GROUP); - } - - /** - * Returns the action group the current task uses for each workflow package item - * - * @return action group id - */ - public String getPackageItemActionGroup() - { - return (String)this.workItem.properties.get( - WorkflowModel.PROP_PACKAGE_ITEM_ACTION_GROUP); - } - - /** - * Returns a list of resources associated with this work item - * i.e. the children of the workflow package - * - * @return The list of nodes - */ - public List getResources() - { - NodeRef workflowPackage = null; - Serializable obj = this.workItem.properties.get(WorkflowModel.ASSOC_PACKAGE); - // TODO: remove this workaroud where JBPM may return a String and not the NodeRef - if (obj instanceof NodeRef) - { - workflowPackage = (NodeRef)obj; - } - else if (obj instanceof String) - { - workflowPackage = new NodeRef((String)obj); - } - - this.resources = new ArrayList(4); - - if (workflowPackage != null) - { - UserTransaction tx = null; - try - { - FacesContext context = FacesContext.getCurrentInstance(); - tx = Repository.getUserTransaction(context, true); - tx.begin(); - - if (logger.isDebugEnabled()) - logger.debug("Found workflow package for work item '" + - this.workItem.id + "': " + workflowPackage ); - - List childRefs = this.nodeService.getChildAssocs(workflowPackage, - ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); - - for (ChildAssociationRef ref: childRefs) - { - // create our Node representation from the NodeRef - NodeRef nodeRef = ref.getChildRef(); - - if (this.nodeService.exists(nodeRef)) - { - // find it's type so we can see if it's a node we are interested in - QName type = this.nodeService.getType(nodeRef); - - // make sure the type is defined in the data dictionary - TypeDefinition typeDef = this.dictionaryService.getType(type); - - if (typeDef != null) - { - // look for content nodes or links to content - // NOTE: folders within workflow packages are ignored for now - if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) || - ContentModel.TYPE_FILELINK.equals(type)) - { - // create our Node representation - MapNode node = new MapNode(nodeRef, this.nodeService, true); - this.browseBean.setupCommonBindingProperties(node); - - // add property resolvers to show path information - node.addPropertyResolver("path", this.browseBean.resolverPath); - node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath); - - // add a property resolver to indicate whether the item has been completed or not - node.addPropertyResolver("completed", this.completeResolver); - - this.resources.add(node); - } - } - else - { - if (logger.isWarnEnabled()) - logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type); - } - } - } - - // commit the transaction - tx.commit(); - } - catch (Throwable err) - { - Utils.addErrorMessage(MessageFormat.format(Application.getMessage( - FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); - this.resources = Collections.emptyList(); - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} - } - } - else if (logger.isDebugEnabled()) - { - logger.debug("Failed to find workflow package for work item: " + this.workItem.id); - } - - return this.resources; - } - - /** - * Sets the workflow service to use - * - * @param workflowService - * WorkflowService instance - */ - public void setWorkflowService(WorkflowService workflowService) - { - this.workflowService = workflowService; - } - - // ------------------------------------------------------------------------------ - // Helper methods - - - // ------------------------------------------------------------------------------ - // Inner classes - - /** - * Property resolver to determine if the given node has been flagged as complete - */ - protected class WorkItemCompleteResolver implements NodePropertyResolver - { - public Object get(Node node) - { - String result = Application.getMessage(FacesContext.getCurrentInstance(), "no"); - - List completedItems = (List)workItem.properties.get( - WorkflowModel.PROP_COMPLETED_ITEMS); - - if (completedItems != null && completedItems.size() > 0 && - completedItems.contains(node.getNodeRef())) - { - result = Application.getMessage(FacesContext.getCurrentInstance(), "yes"); - } - - return result; - } - } -} diff --git a/source/java/org/alfresco/web/bean/workflow/ReassignTaskDialog.java b/source/java/org/alfresco/web/bean/workflow/ReassignTaskDialog.java new file mode 100644 index 0000000000..f543730687 --- /dev/null +++ b/source/java/org/alfresco/web/bean/workflow/ReassignTaskDialog.java @@ -0,0 +1,199 @@ +package org.alfresco.web.bean.workflow; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.model.SelectItem; +import javax.transaction.UserTransaction; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.dialog.BaseDialogBean; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.SortableSelectItem; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIGenericPicker; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Bean implementation for the "Reassign Task" dialog + * + * @author gavinc + */ +public class ReassignTaskDialog extends BaseDialogBean +{ + protected String taskId; + + protected WorkflowService workflowService; + protected PersonService personService; + + private static final Log logger = LogFactory.getLog(ReassignTaskDialog.class); + + // ------------------------------------------------------------------------------ + // Dialog implementation + + @Override + public void init(Map parameters) + { + super.init(parameters); + + this.taskId = this.parameters.get("task-id"); + if (this.taskId == null || this.taskId.length() == 0) + { + throw new IllegalArgumentException("Reassign task dialog called without task id"); + } + } + + @Override + protected String finishImpl(FacesContext context, String outcome) + throws Exception + { + if (logger.isDebugEnabled()) + logger.debug("Reassigning task with id: " + this.taskId); + + UIComponent picker = context.getViewRoot().findComponent("dialog:dialog-body:user-picker"); + + if (picker != null && picker instanceof UIGenericPicker) + { + UIGenericPicker userPicker = (UIGenericPicker)picker; + String[] user = userPicker.getSelectedResults(); + if (user != null && user.length > 0) + { + // create a map to hold the new owner property then update the task + String userName = user[0]; + Map params = new HashMap(1); + params.put(ContentModel.PROP_OWNER, userName); + this.workflowService.updateTask(this.taskId, params, null, null); + } + else + { + if (logger.isWarnEnabled()) + logger.warn("Failed to find selected user, reassign was unsuccessful"); + } + } + else + { + if (logger.isWarnEnabled()) + logger.warn("Failed to find user-picker component, reassign was unsuccessful"); + } + + if (logger.isDebugEnabled()) + logger.debug("Reassigning task with id: " + this.taskId); + + return outcome; + } + + @Override + protected String getErrorMessageId() + { + return "error_reassign_task"; + } + + // ------------------------------------------------------------------------------ + // Bean Getters and Setters + + /** + * Property accessed by the Generic Picker component. + * + * @return the array of filter options to show in the users/groups picker + */ + public SelectItem[] getFilters() + { + ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance()); + return new SelectItem[] {new SelectItem("0", bundle.getString("users"))}; + } + + /** + * Query callback method executed by the Generic Picker component. + * This method is part of the contract to the Generic Picker, it is up to the backing bean + * to execute whatever query is appropriate and return the results. + * + * @param filterIndex Index of the filter drop-down selection + * @param contains Text from the contains textbox + * + * @return An array of SelectItem objects containing the results to display in the picker. + */ + public SelectItem[] pickerCallback(int filterIndex, String contains) + { + FacesContext context = FacesContext.getCurrentInstance(); + + SelectItem[] items; + + UserTransaction tx = null; + try + { + tx = Repository.getUserTransaction(context, true); + tx.begin(); + + // build xpath to match available User/Person objects + NodeRef peopleRef = personService.getPeopleContainer(); + // NOTE: see SearcherComponentTest + String xpath = "*[like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "firstName, '%" + contains + "%', false)" + + " or " + "like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "lastName, '%" + contains + "%', false)]"; + + List nodes = searchService.selectNodes( + peopleRef, + xpath, + null, + this.namespaceService, + false); + + items = new SelectItem[nodes.size()]; + for (int index=0; index workflows; protected WorkflowService workflowService; protected Node startTaskNode; + protected List resources; + protected List packageItemsToAdd; + protected UIRichList packageItemsRichList; + protected String[] itemsToAdd; + protected boolean isItemBeingAdded = false; protected boolean nextButtonDisabled = false; private static final Log logger = LogFactory.getLog(StartWorkflowWizard.class); @@ -65,6 +78,43 @@ public class StartWorkflowWizard extends BaseWizardBean } this.startTaskNode = null; + this.resources = null; + this.itemsToAdd = null; + this.packageItemsToAdd = new ArrayList(); + this.isItemBeingAdded = false; + if (this.packageItemsRichList != null) + { + this.packageItemsRichList.setValue(null); + this.packageItemsRichList = null; + } + + // TODO: Does this need to be in a read-only transaction?? + + // add the item the workflow wizard was started on to the list of resources + String itemToWorkflowId = this.parameters.get("item-to-workflow"); + if (itemToWorkflowId != null && itemToWorkflowId.length() > 0) + { + // create the node ref for the item and determine its type + NodeRef itemToWorkflow = new NodeRef(Repository.getStoreRef(), itemToWorkflowId); + QName type = this.nodeService.getType(itemToWorkflow); + + if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) || + this.dictionaryService.isSubClass(type, ContentModel.TYPE_FILELINK)) + { + this.packageItemsToAdd.add(itemToWorkflow.toString()); + } + } + } + + @Override + public void restored() + { + // reset the workflow package rich list so everything gets re-evaluated + if (this.packageItemsRichList != null) + { + this.packageItemsRichList.setValue(null); + this.packageItemsRichList = null; + } } @Override @@ -77,26 +127,23 @@ public class StartWorkflowWizard extends BaseWizardBean logger.debug("Starting workflow: " + this.selectedWorkflow); // prepare the parameters from the current state of the property sheet - Map params = WorkflowBean.prepareWorkItemParams(this.startTaskNode); + Map params = WorkflowBean.prepareTaskParams(this.startTaskNode); + + if (logger.isDebugEnabled()) + logger.debug("Starting workflow with parameters: " + params); // create a workflow package for the attached items and add them - String itemToWorkflowId = this.parameters.get("item-to-workflow"); - if (itemToWorkflowId != null && itemToWorkflowId.length() > 0) + if (this.packageItemsToAdd.size() > 0) { - // create the node ref for the item and determine its type - NodeRef itemToWorkflow = new NodeRef(Repository.getStoreRef(), itemToWorkflowId); - QName type = this.nodeService.getType(itemToWorkflow); + NodeRef workflowPackage = this.workflowService.createPackage(null); - NodeRef workflowPackage = null; - if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) || - this.dictionaryService.isSubClass(type, ContentModel.TYPE_FILELINK)) + for (String addedItem : this.packageItemsToAdd) { - // create a workflow package and add the given item to workflow as a child - workflowPackage = this.workflowService.createPackage(null); - this.nodeService.addChild(workflowPackage, itemToWorkflow, + NodeRef addedNodeRef = new NodeRef(addedItem); + this.nodeService.addChild(workflowPackage, addedNodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName((String)this.nodeService.getProperty( - itemToWorkflow, ContentModel.PROP_NAME)))); + addedNodeRef, ContentModel.PROP_NAME)))); } // add the workflow package to the parameter map @@ -175,9 +222,131 @@ public class StartWorkflowWizard extends BaseWizardBean return this.nextButtonDisabled; } + // ------------------------------------------------------------------------------ + // Event Handlers + + /** + * Prepares the dialog to allow the user to add an item to the workflow package + * + * @param event The event + */ + public void prepareForAdd(ActionEvent event) + { + this.isItemBeingAdded = true; + } + + /** + * Cancels the adding of an item to the workflow package + * + * @param event The event + */ + public void cancelAddPackageItems(ActionEvent event) + { + this.isItemBeingAdded = false; + } + + /** + * Adds items to the workflow package + * + * @param event The event + */ + public void addPackageItems(ActionEvent event) + { + if (this.itemsToAdd != null) + { + for (String item : this.itemsToAdd) + { + this.packageItemsToAdd.add(item); + + if (logger.isDebugEnabled()) + logger.debug("Added item to the added list: " + item); + } + + // reset the rich list so it re-renders + this.packageItemsRichList.setValue(null); + } + + this.isItemBeingAdded = false; + this.itemsToAdd = null; + } + + /** + * Removes an item from the workflow package + * + * @param event The event containing a reference to the item to remove + */ + public void removePackageItem(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String nodeRef = new NodeRef(Repository.getStoreRef(), params.get("id")).toString(); + + if (this.packageItemsToAdd.contains(nodeRef)) + { + // remove the item from the added list if it was added in this dialog session + this.packageItemsToAdd.remove(nodeRef); + + if (logger.isDebugEnabled()) + logger.debug("Removed item from the added list: " + nodeRef); + } + + // reset the rich list so it re-renders + this.packageItemsRichList.setValue(null); + } + // ------------------------------------------------------------------------------ // Bean Getters and Setters + /** + * Returns a String array of NodeRef's that are being added to the workflow package + * + * @return String array of NodeRef's + */ + public String[] getItemsToAdd() + { + return this.itemsToAdd; + } + + /** + * Sets the NodeRef's to add as items to the workflow package + * + * @param itemsToAdd NodeRef's to add to the workflow package + */ + public void setItemsToAdd(String[] itemsToAdd) + { + this.itemsToAdd = itemsToAdd; + } + + /** + * Determines whether an item is currently being added to the workflow package + * + * @return true if an item is being added + */ + public boolean isItemBeingAdded() + { + return this.isItemBeingAdded; + } + + /** + * Sets the rich list being used for the workflow package items + * + * @param richList The rich list instance + */ + public void setPackageItemsRichList(UIRichList richList) + { + this.packageItemsRichList = richList; + } + + /** + * Returns the rich list being used for the workflow package items + * + * @return The rich list instance + */ + public UIRichList getPackageItemsRichList() + { + return this.packageItemsRichList; + } + /** * Returns the workflow selected by the user * @@ -317,6 +486,59 @@ public class StartWorkflowWizard extends BaseWizardBean return availableWorkflows; } + /** + * Returns a list of resources associated with this task + * i.e. the children of the workflow package + * + * @return The list of nodes + */ + public List getResources() + { + this.resources = new ArrayList(4); + + UserTransaction tx = null; + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context, true); + tx.begin(); + + for (String newItem : this.packageItemsToAdd) + { + NodeRef nodeRef = new NodeRef(newItem); + if (this.nodeService.exists(nodeRef)) + { + // create our Node representation + MapNode node = new MapNode(nodeRef, this.nodeService, true); + this.browseBean.setupCommonBindingProperties(node); + + // add property resolvers to show path information + node.addPropertyResolver("path", this.browseBean.resolverPath); + node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath); + + this.resources.add(node); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); + } + } + + // commit the transaction + tx.commit(); + } + catch (Throwable err) + { + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); + this.resources = Collections.emptyList(); + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + } + + return this.resources; + } + /** * Sets the workflow service to use * diff --git a/source/java/org/alfresco/web/bean/workflow/ViewCompletedTaskDialog.java b/source/java/org/alfresco/web/bean/workflow/ViewCompletedTaskDialog.java new file mode 100644 index 0000000000..b037ad74ce --- /dev/null +++ b/source/java/org/alfresco/web/bean/workflow/ViewCompletedTaskDialog.java @@ -0,0 +1,48 @@ +package org.alfresco.web.bean.workflow; + +import java.util.List; + +import javax.faces.context.FacesContext; + +import org.alfresco.web.app.Application; +import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig; + +/** + * Bean implementation for the "View Completed Task" dialog. + * + * @author gavinc + */ +public class ViewCompletedTaskDialog extends ManageTaskDialog +{ + // ------------------------------------------------------------------------------ + // Dialog implementation + + @Override + protected String finishImpl(FacesContext context, String outcome) + throws Exception + { + // nothing to do as the finish button is not shown and the dialog is read only + + return outcome; + } + + @Override + public String getCancelButtonLabel() + { + return Application.getMessage(FacesContext.getCurrentInstance(), "close"); + } + + @Override + public List getAdditionalButtons() + { + return null; + } + + @Override + public String getTitle() + { + String titleStart = Application.getMessage(FacesContext.getCurrentInstance(), "view_completed_task_title"); + + return titleStart + ": " + this.task.title; + } +} diff --git a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java index 5368ca9be6..9800da87b5 100644 --- a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java +++ b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java @@ -39,8 +39,8 @@ public class WorkflowBean { protected NodeService nodeService; protected WorkflowService workflowService; - protected List workItems; - protected List completedWorkItems; + protected List tasks; + protected List completedTasks; private static final Log logger = LogFactory.getLog(WorkflowBean.class); @@ -48,12 +48,12 @@ public class WorkflowBean // Bean Getters and Setters /** - * Returns a list of nodes representing the to do work items the + * Returns a list of nodes representing the to do tasks the * current user has. * - * @return List of to do work items + * @return List of to do tasks */ - public List getWorkItemsToDo() + public List getTasksToDo() { // get the current username FacesContext context = FacesContext.getCurrentInstance(); @@ -71,14 +71,14 @@ public class WorkflowBean userName, WorkflowTaskState.IN_PROGRESS); // create a list of transient nodes to represent - this.workItems = new ArrayList(tasks.size()); + this.tasks = new ArrayList(tasks.size()); for (WorkflowTask task : tasks) { - Node node = createWorkItem(task); - this.workItems.add(node); + Node node = createTask(task); + this.tasks.add(node); if (logger.isDebugEnabled()) - logger.debug("Added to do work item: " + node); + logger.debug("Added to do task: " + node); } // commit the changes @@ -88,19 +88,19 @@ public class WorkflowBean { // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} - Utils.addErrorMessage("Failed to get to do work items: " + e.toString(), e); + Utils.addErrorMessage("Failed to get to do tasks: " + e.toString(), e); } - return this.workItems; + return this.tasks; } /** - * Returns a list of nodes representing the completed work items the + * Returns a list of nodes representing the completed tasks the * current user has. * - * @return List of completed work items + * @return List of completed tasks */ - public List getWorkItemsCompleted() + public List getTasksCompleted() { // get the current username FacesContext context = FacesContext.getCurrentInstance(); @@ -118,14 +118,14 @@ public class WorkflowBean userName, WorkflowTaskState.COMPLETED); // create a list of transient nodes to represent - this.completedWorkItems = new ArrayList(tasks.size()); + this.completedTasks = new ArrayList(tasks.size()); for (WorkflowTask task : tasks) { - Node node = createWorkItem(task); - this.completedWorkItems.add(node); + Node node = createTask(task); + this.completedTasks.add(node); if (logger.isDebugEnabled()) - logger.debug("Added completed work item: " + node); + logger.debug("Added completed task: " + node); } // commit the changes @@ -135,10 +135,10 @@ public class WorkflowBean { // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} - Utils.addErrorMessage("Failed to get completed work items: " + e.toString(), e); + Utils.addErrorMessage("Failed to get completed tasks: " + e.toString(), e); } - return this.completedWorkItems; + return this.completedTasks; } /** @@ -164,7 +164,7 @@ public class WorkflowBean // ------------------------------------------------------------------------------ // Helper methods - public static Map prepareWorkItemParams(Node node) + public static Map prepareTaskParams(Node node) { Map params = new HashMap(); @@ -199,9 +199,6 @@ public class WorkflowBean params.put(assocQName, (Serializable)targets); } - if (logger.isDebugEnabled()) - logger.debug("Prepared parameters: " + params); - return params; } @@ -211,7 +208,7 @@ public class WorkflowBean * * @param task The task to create a representation of */ - protected TransientMapNode createWorkItem(WorkflowTask task) + protected TransientMapNode createTask(WorkflowTask task) { // get the type of the task WorkflowTaskDefinition taskDef = task.definition; diff --git a/source/java/org/alfresco/web/config/ClientConfigElement.java b/source/java/org/alfresco/web/config/ClientConfigElement.java index 0f6a3e216e..b151b3b0fe 100644 --- a/source/java/org/alfresco/web/config/ClientConfigElement.java +++ b/source/java/org/alfresco/web/config/ClientConfigElement.java @@ -40,7 +40,7 @@ public class ClientConfigElement extends ConfigElementAdapter private String editLinkType = "http"; private String homeSpacePermission = null; private boolean ajaxEnabled = false; - private String initialLocation = null; + private String initialLocation = "myalfresco"; /** * Default Constructor diff --git a/source/java/org/alfresco/web/config/DashboardsConfigElement.java b/source/java/org/alfresco/web/config/DashboardsConfigElement.java index 83ed1a8039..d5e19db865 100644 --- a/source/java/org/alfresco/web/config/DashboardsConfigElement.java +++ b/source/java/org/alfresco/web/config/DashboardsConfigElement.java @@ -37,6 +37,7 @@ public class DashboardsConfigElement extends ConfigElementAdapter private Map layoutDefs = new LinkedHashMap(4, 1.0f); private Map dashletDefs = new LinkedHashMap(8, 1.0f); + private boolean allowGuestConfig = false; /** * Default constructor @@ -77,9 +78,24 @@ public class DashboardsConfigElement extends ConfigElementAdapter combinedElement.layoutDefs.putAll(this.layoutDefs); combinedElement.layoutDefs.putAll(newElement.layoutDefs); + if (newElement.allowGuestConfig != combinedElement.allowGuestConfig) + { + combinedElement.allowGuestConfig = newElement.allowGuestConfig; + } + return combinedElement; } + /*package*/ void setAllowGuestConfig(boolean allow) + { + this.allowGuestConfig = allow; + } + + public boolean getAllowGuestConfig() + { + return this.allowGuestConfig; + } + /*package*/ void addLayoutDefinition(LayoutDefinition def) { this.layoutDefs.put(def.Id, def); diff --git a/source/java/org/alfresco/web/config/DashboardsElementReader.java b/source/java/org/alfresco/web/config/DashboardsElementReader.java index e532ec8486..e599251f71 100644 --- a/source/java/org/alfresco/web/config/DashboardsElementReader.java +++ b/source/java/org/alfresco/web/config/DashboardsElementReader.java @@ -37,6 +37,7 @@ public class DashboardsElementReader implements ConfigElementReader public static final String ELEMENT_LAYOUT = "layout"; public static final String ELEMENT_DASHLETS = "dashlets"; public static final String ELEMENT_DASHLET = "dashlet"; + public static final String ELEMENT_GUESTCONFIG = "allow-guest-config"; public static final String ATTR_ID = "id"; public static final String ATTR_COLUMNS = "columns"; public static final String ATTR_COLUMNLENGTH = "column-length"; @@ -85,6 +86,13 @@ public class DashboardsElementReader implements ConfigElementReader configElement.addDashletDefinition(dashletDef); } } + + Element guestConfigElement = element.element(ELEMENT_GUESTCONFIG); + if (guestConfigElement != null) + { + boolean allow = Boolean.parseBoolean(guestConfigElement.getTextTrim()); + configElement.setAllowGuestConfig(allow); + } } return configElement; diff --git a/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java b/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java new file mode 100644 index 0000000000..2aeec8d7a4 --- /dev/null +++ b/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the GNU Lesser General Public License as + * published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + * You may obtain a copy of the License at + * + * http://www.gnu.org/licenses/lgpl.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.ui.repo.component; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.faces.component.UIInput; +import javax.faces.context.FacesContext; +import javax.faces.context.ResponseWriter; +import javax.faces.el.ValueBinding; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.Utils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Component for selecting content from the repository + * + * @author gavinc + */ +public class UIContentSelector extends UIInput +{ + private final static Log logger = LogFactory.getLog(UIContentSelector.class); + + private final static String ACTION_SEPARATOR = ";"; + private final static String ACTION_SEARCH = "0"; + + private final static String FIELD_CONTAINS = "_contains"; + private final static String FIELD_AVAILABLE = "_available"; + private final static String MSG_SEARCH = "search"; + + protected String availableOptionsSize; + protected Boolean disabled; + private Boolean multiSelect; + + /** List containing the currently available options */ + protected List availableOptions; + + // ------------------------------------------------------------------------------ + // Component implementation + + /** + * @see javax.faces.component.UIComponent#getFamily() + */ + public String getFamily() + { + return "org.alfresco.faces.ContentSelector"; + } + + /** + * Default constructor + */ + public UIContentSelector() + { + setRendererType(null); + } + + /** + * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object) + */ + @SuppressWarnings("unchecked") + public void restoreState(FacesContext context, Object state) + { + Object values[] = (Object[])state; + // standard component attributes are restored by the super class + super.restoreState(context, values[0]); + this.availableOptions = (List)values[1]; + this.availableOptionsSize = (String)values[2]; + this.disabled = (Boolean)values[3]; + this.multiSelect = (Boolean)values[4]; + } + + /** + * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext) + */ + public Object saveState(FacesContext context) + { + Object values[] = new Object[10]; + // standard component attributes are saved by the super class + values[0] = super.saveState(context); + values[1] = this.availableOptions; + values[2] = this.availableOptionsSize; + values[3] = this.disabled; + values[4] = this.multiSelect; + + return (values); + } + + /** + * @see javax.faces.component.UIComponent#decode(javax.faces.context.FacesContext) + */ + public void decode(FacesContext context) + { + Map requestMap = context.getExternalContext().getRequestParameterMap(); + Map valuesMap = context.getExternalContext().getRequestParameterValuesMap(); + String fieldId = getHiddenFieldName(); + String value = (String)requestMap.get(fieldId); + + if (value != null && value.equals(ACTION_SEARCH)) + { + // user has issued a search action, fill the list with options + String contains = (String)requestMap.get(fieldId + FIELD_CONTAINS); + this.availableOptions = new ArrayList(); + getAvailableOptions(FacesContext.getCurrentInstance(), contains); + } + else + { + // set the submitted value (if there is one) + String[] addedItems = (String[])valuesMap.get(fieldId + FIELD_AVAILABLE); + this.setSubmittedValue(addedItems); + } + } + + /** + * @see javax.faces.component.UIComponent#encodeBegin(javax.faces.context.FacesContext) + */ + public void encodeBegin(FacesContext context) throws IOException + { + if (isRendered() == false) + { + return; + } + + ResponseWriter out = context.getResponseWriter(); + + // get the child associations currently on the node and any that have been added + NodeService nodeService = Repository.getServiceRegistry(context).getNodeService(); + + if (isDisabled()) + { + // TODO: if the component is disabled just show the current value as text + } + else + { + // start outer table + out.write(""); + + // show the search field + out.write(""); + + // show available options i.e. all content in repository + renderAvailableOptions(context, out, nodeService); + + // close table + out.write("
  
"); + } + } + + /** + * Determines whether the component should be rendered in a disabled state + * + * @return Returns whether the component is disabled + */ + public boolean isDisabled() + { + if (this.disabled == null) + { + ValueBinding vb = getValueBinding("disabled"); + if (vb != null) + { + this.disabled = (Boolean)vb.getValue(getFacesContext()); + } + } + + if (this.disabled == null) + { + this.disabled = Boolean.FALSE; + } + + return this.disabled; + } + + /** + * Determines whether the component should be rendered in a disabled state + * + * @param disabled true to disable the component + */ + public void setDisabled(boolean disabled) + { + this.disabled = disabled; + } + + /** + * Returns the size of the select control when multiple items + * can be selected + * + * @return The size of the select control + */ + public String getAvailableOptionsSize() + { + if (this.availableOptionsSize == null) + { + this.availableOptionsSize = "6"; + } + + return this.availableOptionsSize; + } + + /** + * Sets the size of the select control used when multiple items can + * be selected + * + * @param availableOptionsSize The size + */ + public void setAvailableOptionsSize(String availableOptionsSize) + { + this.availableOptionsSize = availableOptionsSize; + } + + /** + * @return true if multi select should be enabled. + */ + public boolean getMultiSelect() + { + ValueBinding vb = getValueBinding("multiSelect"); + if (vb != null) + { + this.multiSelect = (Boolean)vb.getValue(getFacesContext()); + } + + return multiSelect != null ? multiSelect.booleanValue() : true; + } + + /** + * @param multiSelect Flag to determine whether multi select is enabled + */ + public void setMultiSelect(boolean multiSelect) + { + this.multiSelect = Boolean.valueOf(multiSelect); + } + + /** + * Renders the list of available options + * + * @param context FacesContext + * @param out Writer to write output to + * @param nodeService The NodeService + * @throws IOException + */ + protected void renderAvailableOptions(FacesContext context, ResponseWriter out, NodeService nodeService) + throws IOException + { + boolean itemsPresent = (this.availableOptions != null && this.availableOptions.size() > 0); + + out.write(""); + } + + /** + * Retrieves the available options for the current association + * + * @param context Faces Context + * @param contains The contains part of the query + */ + protected void getAvailableOptions(FacesContext context, String contains) + { + // query for all content in the current repository + StringBuilder query = new StringBuilder("+TYPE:\""); + query.append(ContentModel.TYPE_CONTENT); + query.append("\""); + + if (contains != null && contains.length() > 0) + { + String safeContains = Utils.remove(contains.trim(), "\""); + query.append(" AND +@"); + + String nameAttr = Repository.escapeQName(QName.createQName( + NamespaceService.CONTENT_MODEL_1_0_URI, "name")); + query.append(nameAttr); + + query.append(":*" + safeContains + "*"); + } + + if (logger.isDebugEnabled()) + logger.debug("Query: " + query.toString()); + + ResultSet results = null; + try + { + results = Repository.getServiceRegistry(context).getSearchService().query( + Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString()); + this.availableOptions = results.getNodeRefs(); + } + finally + { + if (results != null) + { + results.close(); + } + } + + if (logger.isDebugEnabled()) + logger.debug("Found " + this.availableOptions.size() + " available options"); + } + + /** + * We use a hidden field per picker instance on the page. + * + * @return hidden field name + */ + private String getHiddenFieldName() + { + return getClientId(getFacesContext()); + } + + /** + * Generate FORM submit JavaScript for the specified action + * + * @param context FacesContext + * @param action Action string + * + * @return FORM submit JavaScript + */ + private String generateFormSubmit(FacesContext context, String action) + { + return Utils.generateFormSubmit(context, this, getHiddenFieldName(), action); + } +} diff --git a/source/java/org/alfresco/web/ui/repo/component/UIWorkflowSummary.java b/source/java/org/alfresco/web/ui/repo/component/UIWorkflowSummary.java new file mode 100644 index 0000000000..40676f0844 --- /dev/null +++ b/source/java/org/alfresco/web/ui/repo/component/UIWorkflowSummary.java @@ -0,0 +1,163 @@ +package org.alfresco.web.ui.repo.component; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ResourceBundle; + +import javax.faces.context.FacesContext; +import javax.faces.context.ResponseWriter; +import javax.faces.el.ValueBinding; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.workflow.WorkflowInstance; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.component.SelfRenderingComponent; + +/** + * JSF component that displays summary information about a workflow. + * + * @author gavinc + */ +public class UIWorkflowSummary extends SelfRenderingComponent +{ + protected WorkflowInstance value = null; + + // ------------------------------------------------------------------------------ + // Component Impl + + @Override + public String getFamily() + { + return "org.alfresco.faces.WorkflowSummary"; + } + + @Override + public void restoreState(FacesContext context, Object state) + { + Object values[] = (Object[])state; + // standard component attributes are restored by the super class + super.restoreState(context, values[0]); + this.value = (WorkflowInstance)values[1]; + } + + @Override + public Object saveState(FacesContext context) + { + Object values[] = new Object[8]; + // standard component attributes are saved by the super class + values[0] = super.saveState(context); + values[1] = this.value; + return values; + } + + @Override + @SuppressWarnings("unchecked") + public void encodeBegin(FacesContext context) throws IOException + { + if (!isRendered()) return; + + WorkflowInstance wi = getValue(); + + if (wi != null) + { + ResponseWriter out = context.getResponseWriter(); + ResourceBundle bundle = Application.getBundle(context); + SimpleDateFormat format = new SimpleDateFormat(bundle.getString("date_pattern")); + + // output surrounding table and style if necessary + out.write(""); + + // output the title and description + out.write(""); + out.write(bundle.getString("title")); + out.write(":"); + out.write(wi.definition.title); + out.write(""); + out.write(bundle.getString("description")); + out.write(":"); + out.write(wi.definition.description); + out.write(""); + out.write(bundle.getString("initiated_by")); + out.write(":"); + if (wi.initiator != null) + { + NodeService nodeService = Repository.getServiceRegistry( + context).getNodeService(); + String userName = (String)nodeService.getProperty( + wi.initiator, ContentModel.PROP_USERNAME); + out.write(userName); + } + out.write(""); + out.write(bundle.getString("start_date")); + out.write(":"); + if (wi.startDate != null) + { + out.write(format.format(wi.startDate)); + } + out.write(""); + out.write(bundle.getString("due_date")); + out.write(":"); + if (wi.endDate != null) + { + out.write(format.format(wi.endDate)); + } + out.write(""); + } + } + + @Override + public void encodeEnd(FacesContext context) throws IOException + { + if (!isRendered()) return; + } + + @Override + public boolean getRendersChildren() + { + return false; + } + + // ------------------------------------------------------------------------------ + // Strongly typed component property accessors + + /** + * Returns the workflow instance this component is showing information on + * + * @return The workflow instance + */ + public WorkflowInstance getValue() + { + ValueBinding vb = getValueBinding("value"); + if (vb != null) + { + this.value = (WorkflowInstance)vb.getValue(getFacesContext()); + } + + return this.value; + } + + /** + * Sets the workflow instance to show the summary for + * + * @param value The workflow instance + */ + public void setValue(WorkflowInstance value) + { + this.value = value; + } +} diff --git a/source/java/org/alfresco/web/ui/repo/tag/ContentSelectorTag.java b/source/java/org/alfresco/web/ui/repo/tag/ContentSelectorTag.java new file mode 100644 index 0000000000..c40549baa3 --- /dev/null +++ b/source/java/org/alfresco/web/ui/repo/tag/ContentSelectorTag.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.ui.repo.tag; + +import javax.faces.component.UIComponent; + +import org.alfresco.web.ui.common.tag.HtmlComponentTag; + +/** + * Tag class to allow the content selector component to be added to a JSP page + * + * @author gavinc + */ +public class ContentSelectorTag extends HtmlComponentTag +{ + private String availableOptionsSize; + private String disabled; + private String value; + private String multiSelect; + + /** + * @see javax.faces.webapp.UIComponentTag#getComponentType() + */ + public String getComponentType() + { + return "org.alfresco.faces.ContentSelector"; + } + + /** + * @see javax.faces.webapp.UIComponentTag#getRendererType() + */ + public String getRendererType() + { + return null; + } + + /** + * @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent) + */ + protected void setProperties(UIComponent component) + { + super.setProperties(component); + + setStringStaticProperty(component, "availableOptionsSize", this.availableOptionsSize); + setStringProperty(component, "value", this.value); + setBooleanProperty(component, "disabled", this.disabled); + setBooleanProperty(component, "multiSelect", this.multiSelect); + } + + /** + * @param value The value to set. + */ + public void setValue(String value) + { + this.value = value; + } + + /** + * @param availableOptionsSize Sets the size of the available options size when + * multiple items can be selected + */ + public void setAvailableOptionsSize(String availableOptionsSize) + { + this.availableOptionsSize = availableOptionsSize; + } + + /** + * Set the multiSelect + * + * @param mutliSelect the multiSelect + */ + public void setMultiSelect(String multiSelect) + { + this.multiSelect = multiSelect; + } + + /** + * Sets whether the component should be rendered in a disabled state + * + * @param disabled true to render the component in a disabled state + */ + public void setDisabled(String disabled) + { + this.disabled = disabled; + } + + /** + * @see javax.faces.webapp.UIComponentTag#release() + */ + public void release() + { + this.availableOptionsSize = null; + this.disabled = null; + this.value = null; + this.multiSelect = null; + + super.release(); + } +} diff --git a/source/java/org/alfresco/web/ui/repo/tag/WorkflowSummaryTag.java b/source/java/org/alfresco/web/ui/repo/tag/WorkflowSummaryTag.java new file mode 100644 index 0000000000..b5b159e9fb --- /dev/null +++ b/source/java/org/alfresco/web/ui/repo/tag/WorkflowSummaryTag.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.ui.repo.tag; + +import javax.faces.component.UIComponent; + +import org.alfresco.web.ui.common.tag.HtmlComponentTag; + +/** + * Tag that allows the workflow summary component to be placed on a JSP page + * + * @author gavinc + */ +public class WorkflowSummaryTag extends HtmlComponentTag +{ + /** + * @see javax.faces.webapp.UIComponentTag#getComponentType() + */ + public String getComponentType() + { + return "org.alfresco.faces.WorkflowSummary"; + } + + /** + * @see javax.faces.webapp.UIComponentTag#getRendererType() + */ + public String getRendererType() + { + return null; + } + + /** + * @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent) + */ + protected void setProperties(UIComponent component) + { + super.setProperties(component); + + setStringProperty(component, "value", this.value); + } + + /** + * @see org.alfresco.web.ui.common.tag.HtmlComponentTag#release() + */ + public void release() + { + super.release(); + this.value = null; + } + + /** + * Set the value (binding to the list of user/group data) + * + * @param value the value + */ + public void setValue(String value) + { + this.value = value; + } + + /** the value (binding to the workflow instance) */ + private String value; +} diff --git a/source/java/org/alfresco/web/ui/repo/tag/property/BaseAssociationEditorTag.java b/source/java/org/alfresco/web/ui/repo/tag/property/BaseAssociationEditorTag.java index 276852ebfb..2a1382f56d 100644 --- a/source/java/org/alfresco/web/ui/repo/tag/property/BaseAssociationEditorTag.java +++ b/source/java/org/alfresco/web/ui/repo/tag/property/BaseAssociationEditorTag.java @@ -34,6 +34,7 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag private String selectedItemsMsg; private String noSelectedItemsMsg; private String disabled; + private String value; /** * @see javax.faces.webapp.UIComponentTag#getRendererType() @@ -56,9 +57,18 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag setStringProperty(component, "selectItemsMsg", this.selectItemsMsg); setStringProperty(component, "selectedItemsMsg", this.selectedItemsMsg); setStringProperty(component, "noSelectedItemsMsg", this.noSelectedItemsMsg); + setStringProperty(component, "value", this.value); setBooleanProperty(component, "disabled", this.disabled); } + /** + * @param value The value to set. + */ + public void setValue(String value) + { + this.value = value; + } + /** * Sets the association name * @@ -140,6 +150,7 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag this.selectedItemsMsg = null; this.noSelectedItemsMsg = null; this.disabled = null; + this.value = null; super.release(); } diff --git a/source/web/WEB-INF/faces-config-app.xml b/source/web/WEB-INF/faces-config-app.xml index 3637d56faa..ea4a942c45 100644 --- a/source/web/WEB-INF/faces-config-app.xml +++ b/source/web/WEB-INF/faces-config-app.xml @@ -6,7 +6,7 @@ org.alfresco.web.app.AlfrescoNavigationHandler - org.springframework.web.jsf.DelegatingVariableResolver + org.alfresco.web.app.AlfrescoVariableResolver en diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index fb26e4ff66..8aa2677f2a 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -31,6 +31,10 @@ browseBean #{BrowseBean} + + userPreferencesBean + #{UserPreferencesBean} + @@ -60,6 +64,10 @@ ruleService #{RuleService} + + userPreferencesBean + #{UserPreferencesBean} + @@ -583,6 +591,56 @@ + + + The bean that backs up the View Content Properties Dialog + + ViewContentPropertiesDialog + org.alfresco.web.bean.content.ViewContentPropertiesDialog + session + + nodeService + #{NodeService} + + + fileFolderService + #{FileFolderService} + + + dictionaryService + #{DictionaryService} + + + browseBean + #{BrowseBean} + + + + + + The bean that backs up the Set Content Properties Dialog + + SetContentPropertiesDialog + org.alfresco.web.bean.content.SetContentPropertiesDialog + session + + nodeService + #{NodeService} + + + fileFolderService + #{FileFolderService} + + + dictionaryService + #{DictionaryService} + + + browseBean + #{BrowseBean} + + + The bean that backs up the Edit Content Properties Dialog @@ -1386,10 +1444,6 @@ fileFolderService #{FileFolderService} - - searchService - #{SearchService} - navigator #{NavigationBean} @@ -1551,8 +1605,8 @@ #{ContentService} - dictionaryService - #{DictionaryService} + namespaceService + #{NamespaceService} @@ -1657,10 +1711,47 @@ browseBean #{BrowseBean} + + dictionaryService + #{DictionaryService} + namespaceService #{NamespaceService} + + + + + The bean that backs up the Delete Post Dialog + + DeletePostDialog + org.alfresco.web.bean.forums.DeletePostDialog + session + + nodeService + #{NodeService} + + + fileFolderService + #{FileFolderService} + + + searchService + #{SearchService} + + + navigator + #{NavigationBean} + + + browseBean + #{BrowseBean} + + + dictionaryService + #{DictionaryService} + namespaceService #{NamespaceService} @@ -1765,10 +1856,51 @@ - The bean that backs up the Manage WorkItem Dialog + The bean that backs up the Manage Task Dialog - ManageWorkItemDialog - org.alfresco.web.bean.workflow.ManageWorkItemDialog + ManageTaskDialog + org.alfresco.web.bean.workflow.ManageTaskDialog + session + + nodeService + #{NodeService} + + + fileFolderService + #{FileFolderService} + + + searchService + #{SearchService} + + + navigator + #{NavigationBean} + + + browseBean + #{BrowseBean} + + + dictionaryService + #{DictionaryService} + + + namespaceService + #{NamespaceService} + + + workflowService + #{WorkflowService} + + + + + + The bean that backs up the View Completed Task Dialog + + ViewCompletedTaskDialog + org.alfresco.web.bean.workflow.ViewCompletedTaskDialog session nodeService @@ -1829,8 +1961,8 @@ #{BrowseBean} - namespaceService - #{NamespaceService} + dictionaryService + #{DictionaryService} namespaceService @@ -1885,10 +2017,10 @@ - The bean that backs up the Reassign Work Item Dialog + The bean that backs up the Reassign Task Dialog - ReassignWorkItemDialog - org.alfresco.web.bean.workflow.ReassignWorkItemDialog + ReassignTaskDialog + org.alfresco.web.bean.workflow.ReassignTaskDialog session nodeService @@ -1976,29 +2108,27 @@ - Bean that manages the Dashboard framework - DashboardManager - org.alfresco.web.bean.dashboard.DashboardManager - session - - - - The bean that backs up the Dashboard Config Wizard + The bean that backs up the Getting Started Dashlet page - DashboardWizard - org.alfresco.web.bean.dashboard.DashboardWizard + GettingStartedBean + org.alfresco.web.bean.dashboard.GettingStartedBean session - nodeService - #{NodeService} - - - dashboardManager - #{DashboardManager} + navigationBean + #{NavigationBean} + + + The bean that backs up the User Preferences page + + UserPreferencesBean + org.alfresco.web.bean.UserPreferencesBean + session + + @@ -2143,18 +2273,45 @@ SeparatorGenerator org.alfresco.web.bean.generator.SeparatorGenerator request - - - - - Bean that generates a header separator component - - HeaderSeparatorGenerator - org.alfresco.web.bean.generator.HeaderSeparatorGenerator - request + + + Bean that generates a label separator component + + LabelSeparatorGenerator + org.alfresco.web.bean.generator.LabelSeparatorGenerator + request + + + + Bean that generates a label separator component rendered as a heading + + HeaderSeparatorGenerator + org.alfresco.web.bean.generator.LabelSeparatorGenerator + request + + styleClass + wizardSectionHeading mainSubTitle + + + + + @@ -2174,32 +2331,4 @@ - - - - - Bean that returns information on a node - - NodeInfoBean - org.alfresco.web.bean.ajax.NodeInfoBean - request - - nodeService - #{NodeService} - - - contentService - #{ContentService} - - - - - - Bean that returns information on a node - - XFormsBean - org.alfresco.web.bean.ajax.XFormsBean - session - - diff --git a/source/web/WEB-INF/faces-config-navigation.xml b/source/web/WEB-INF/faces-config-navigation.xml index 44da3c35b6..60e54eee7a 100644 --- a/source/web/WEB-INF/faces-config-navigation.xml +++ b/source/web/WEB-INF/faces-config-navigation.xml @@ -57,6 +57,10 @@ dashboard /jsp/browse/dashboard.jsp + + addContent + /jsp/content/add-content-dialog.jsp + @@ -878,9 +882,10 @@ - /jsp/dialog/container.jsp + + forumsDeleted /jsp/forums/forums.jsp @@ -893,6 +898,45 @@ topicDeleted /jsp/forums/forum.jsp + + + + + checkoutFile + /jsp/dialog/checkout-file.jsp + + + checkinFile + /jsp/dialog/checkin-file.jsp + + + undoCheckoutFile + /jsp/dialog/undocheckout-file.jsp + + + updateFile + /jsp/dialog/update-file.jsp + + + editFile + /jsp/dialog/edit-file.jsp + + + editHtmlInline + /jsp/dialog/edit-html-inline.jsp + + + editTextInline + /jsp/dialog/edit-text-inline.jsp + + + itemDetails + /jsp/trashcan/item-details.jsp + + + recoveryReport + /jsp/trashcan/recovery-report.jsp + diff --git a/source/web/WEB-INF/faces-config-repo.xml b/source/web/WEB-INF/faces-config-repo.xml index 9b779c54f9..72eefca71b 100644 --- a/source/web/WEB-INF/faces-config-repo.xml +++ b/source/web/WEB-INF/faces-config-repo.xml @@ -54,6 +54,11 @@ org.alfresco.web.ui.repo.component.UISpaceSelector + + org.alfresco.faces.ContentSelector + org.alfresco.web.ui.repo.component.UIContentSelector + + org.alfresco.faces.CategorySelector org.alfresco.web.ui.repo.component.UICategorySelector @@ -144,6 +149,10 @@ org.alfresco.web.ui.repo.component.UIUserGroupPicker + + org.alfresco.faces.WorkflowSummary + org.alfresco.web.ui.repo.component.UIWorkflowSummary + diff --git a/source/web/WEB-INF/repo.tld b/source/web/WEB-INF/repo.tld index 55b9930f2e..ea920aeef3 100644 --- a/source/web/WEB-INF/repo.tld +++ b/source/web/WEB-INF/repo.tld @@ -209,11 +209,17 @@ associationEditor - org.alfresco.web.ui.repo.tag.AssociationEditorTag + org.alfresco.web.ui.repo.tag.property.AssociationEditorTag JSP - assocationName + value + true + true + + + + associationName true true @@ -329,11 +335,17 @@ childAssociationEditor - org.alfresco.web.ui.repo.tag.ChildAssociationEditorTag + org.alfresco.web.ui.repo.tag.property.ChildAssociationEditorTag JSP - assocationName + value + true + true + + + + associationName true true @@ -721,6 +733,60 @@ + + contentSelector + org.alfresco.web.ui.repo.tag.ContentSelectorTag + JSP + + + value + true + true + + + + availableOptionsSize + false + true + + + + multiSelect + false + true + + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + categorySelector org.alfresco.web.ui.repo.tag.CategorySelectorTag @@ -1614,4 +1680,50 @@ + + workflowSummary + org.alfresco.web.ui.repo.tag.WorkflowSummaryTag + JSP + + + Shows summary information of a workflow instance. + + + + id + false + true + + + + value + true + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + diff --git a/source/web/WEB-INF/web.xml b/source/web/WEB-INF/web.xml index 6ae45b32a1..aeabc86ba8 100644 --- a/source/web/WEB-INF/web.xml +++ b/source/web/WEB-INF/web.xml @@ -94,24 +94,14 @@ + - - LogFilter - org.jbpm.webapp.filter.LogFilter - JbpmContextFilter org.jbpm.webapp.filter.JbpmContextFilter - - @@ -138,31 +128,14 @@ + - - LogFilter - /faces/jbpm/* - JbpmContextFilter /faces/jbpm/* - - JbpmContextFilter - /processimage - - - JbpmContextFilter - /faces/jsp/dashboards/* - - @@ -241,30 +214,6 @@ JBPMDeployProcessServlet org.alfresco.web.app.servlet.JBPMDeployProcessServlet - - - - - - - - - - - - ProcessImageServlet - org.jbpm.webapp.servlet.ProcessImageServlet - - - - - Faces Servlet @@ -316,28 +265,6 @@ /jbpm/deployprocess - - - - - - - - - - ProcessImageServlet - /processimage - - - - - - 60 diff --git a/source/web/css/main.css b/source/web/css/main.css index dc8bd137bd..9e3053357c 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -528,3 +528,14 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl border-style: solid; border-color: #AAAAAA; } + +.workflowSummary +{ + margin-left: 6px; +} + +.workflowSummary td +{ + padding-right: 9px; + padding-top: 4px; +} diff --git a/source/web/images/filetypes/tif.gif b/source/web/images/filetypes/tif.gif new file mode 100644 index 0000000000000000000000000000000000000000..a19a44c3f9c97d0aaaebbc351429d8b866db4c2a GIT binary patch literal 129 zcmZ?wbhEHb6krfwSi}GV|Ns97;sXZ`G&D4T*kGXelZBCift5iA!~>~iV0Mexa3?^Z z$ss#7@FwrE$+NFExMT_`NeDRKUUbDg@Qw9>O{KFO{kAtPV0fAw$aXNOe~Ynik-_y` Ww%kM0X3bNc%3CO#;HJpPU=08>0xlB( literal 0 HcmV?d00001 diff --git a/source/web/images/filetypes/tiff.gif b/source/web/images/filetypes/tiff.gif new file mode 100644 index 0000000000000000000000000000000000000000..a19a44c3f9c97d0aaaebbc351429d8b866db4c2a GIT binary patch literal 129 zcmZ?wbhEHb6krfwSi}GV|Ns97;sXZ`G&D4T*kGXelZBCift5iA!~>~iV0Mexa3?^Z z$ss#7@FwrE$+NFExMT_`NeDRKUUbDg@Qw9>O{KFO{kAtPV0fAw$aXNOe~Ynik-_y` Ww%kM0X3bNc%3CO#;HJpPU=08>0xlB( literal 0 HcmV?d00001 diff --git a/source/web/images/filetypes32/tif.gif b/source/web/images/filetypes32/tif.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ca54b78eca005fd3df5d167fa8e1982f9f2e5c9 GIT binary patch literal 407 zcmZ?wbhEHbRA5kGIKlt||NsAAxNzx$1xpScI(qZw?WzkK=X`STaabN(Bi`wx_! z^B+huT)TGd*s)^=4jkCOfB)94Tj$J~Gi}N21Ako__J^lYK4D zL6OWt>zfZWEbzTKXVXE)*HY|N@oz$_6}Zk_ou2Bq{`SjOovPHW4XI)*RfT$W;_V&n zz6N5B1)0oke3SY3rwVnqa_Cjt7wL&lTO=eVGP7<@q2mh1h0~Xcig))m$F~|RTq3e@ zqwkuzx~mPl)FsTf^w-SSU&zD7d7hJh6XX6>6VLGTaG$$yS@d|{0iV-nd2XM(EPU*$ z{^Q!Uou7msv_5KiD=x?@`1hZ?vn6w%zm#mecxJN53b t!x;)ktrcFUd^z&*ytQstkcgONq|h19sRr4ZIWr&6Jv!UsdkX`DH2`C{vn~Jt literal 0 HcmV?d00001 diff --git a/source/web/images/filetypes32/tiff.gif b/source/web/images/filetypes32/tiff.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ca54b78eca005fd3df5d167fa8e1982f9f2e5c9 GIT binary patch literal 407 zcmZ?wbhEHbRA5kGIKlt||NsAAxNzx$1xpScI(qZw?WzkK=X`STaabN(Bi`wx_! z^B+huT)TGd*s)^=4jkCOfB)94Tj$J~Gi}N21Ako__J^lYK4D zL6OWt>zfZWEbzTKXVXE)*HY|N@oz$_6}Zk_ou2Bq{`SjOovPHW4XI)*RfT$W;_V&n zz6N5B1)0oke3SY3rwVnqa_Cjt7wL&lTO=eVGP7<@q2mh1h0~Xcig))m$F~|RTq3e@ zqwkuzx~mPl)FsTf^w-SSU&zD7d7hJh6XX6>6VLGTaG$$yS@d|{0iV-nd2XM(EPU*$ z{^Q!Uou7msv_5KiD=x?@`1hZ?vn6w%zm#mecxJN53b t!x;)ktrcFUd^z&*ytQstkcgONq|h19sRr4ZIWr&6Jv!UsdkX`DH2`C{vn~Jt literal 0 HcmV?d00001 diff --git a/source/web/images/icons/completed_workflow_task.gif b/source/web/images/icons/completed_workflow_task.gif new file mode 100644 index 0000000000000000000000000000000000000000..65970ff7892f4d1b8c1d5393cd9f53bdeb9bd67c GIT binary patch literal 606 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 literal 0 HcmV?d00001 diff --git a/source/web/images/icons/gettingstarted_featuretour.gif b/source/web/images/icons/gettingstarted_featuretour.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a09ca0072b6000e18d6a61d67bfec2fc47b3147 GIT binary patch literal 4544 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 literal 0 HcmV?d00001 diff --git a/source/web/images/icons/gettingstarted_onlinehelp.gif b/source/web/images/icons/gettingstarted_onlinehelp.gif new file mode 100644 index 0000000000000000000000000000000000000000..79fe49e31663af7b3e01bd90741a1e2756c93aa3 GIT binary patch literal 1024 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 A5&!@I literal 0 HcmV?d00001 diff --git a/source/web/images/icons/reassign_workflow_task_large.gif b/source/web/images/icons/reassign_workflow_task_large.gif new file mode 100644 index 0000000000000000000000000000000000000000..09c30fb95e164043b190bb479b106e470f7af30f GIT binary patch literal 1648 zcmV-$29NniNk%w1VITk?0QUd@00030|NmoSsA6KLWMrsjW~pdst7m7bW@e{qYO8E) zt!rznZf>n`aIbG~u5xm)bab(Gb+UGLvUqs2d3m&Zd$oOiwtjxMfPlDyg1Li(x`c$f zhljj|hP#M}y^M^%i;KRHkinCa!;g=?mX^eomBX2t#+aDJot?;>oX4M^$)cjmrKQcL zrp>6R&aAA_s;bYivD3M^*p!s2#Khj%*y*ICsBUkoU}1)Yg|df;wVR!^x4Fq&USqw% z$z^kav$?$hW|;$MngnQ@24gM#$a${Gh_}y{z}1?<*P_STzS!l^4sX~skQkc3|o4i<+S02>E_qj*2&Arij9bgjE9?^nVFoIv9zz!)zIkc=H=+)2Au-__XD+TPdM z-PYIJ)YjV5RaaAFW@2DsUR_^X)!ET+ac!!tr+t5Wd3$$tcXM-fadC5RzQMbVkBi{r z-QVKe-r?Kb;M&{X*xKFKp`)Llp`Dzbn#s$@y1cl!y0+}@>gVa@+1uCF*wlJ^d2w=Z zrKY5so0*rGmXwu~l9Q2-kdBFph=PNG_V@Mm_Vo1i^Yirb^7HZW^6>ES@7&$n$H>O2 ztEsNBs@&h$+1%B3cyow~g@%ZOtF5TQ#J}d~H`T6+x`1iiPz5M+A^z`)X?Ck35>gVU@ z!S9Bp+eHfB~zcS5&V)pNJVd2A5E{xloB};zMkhFkyJG8M1@vSUhavUSVS;i;yEn zh$U*;W~>-7K(Vap!iFthx^?`lZQ`{lj+r1(l7vxH6J#GjfsA=8gw54Db?MZtW9JT@ zJUeZORPo}43l$^0|DoGcO4gunzylrsveu5B`F73Y$(sjeN*6C(&}f-*B-BA$;Rt~n z^j*-aOz*f8k1q;wGtV797_kK!T%fT97E~zl146Jk5>9^LAR`JUxWofbFQd>x%P7Cl za|RPwWT8bCSX5C46KNzg%V!pb!^$7#*ddQRo6usIA(+$yL=jY2afKCBlre@9Y$znn zEHi%AN;mh=GtWGF7!r;nwP0e7Jx@46Mj2#C5d{-T$gxl?k32aeEVfvaOFi{)GfFL! zjFJr=`LuyV6Hq`Q#u7rT!3aa3P%}-NZo-m@Ip*BshaP&^vX4Id^zgA;i_}t?vKKWq(%Fhe~>|hEUZn%*O4+H$*5J-qb0?Db3So6!J`pC*p zKQ3th$#@8VhF_6+%ifhs2pIh3kj>B zLJB6FP(lHsC4$N+D5DI`B8zyE$^#vv5HblOgb>093OodoGpY3Kb1KUOtpLb0*Zctp z9(1sQ0d;BOOwd8AA~hweBw+IgA9%n)2N_^+0R=fX?F=PUuTsg`%;-=-(i(Ve0R+KJ05yd5%-)wYe#tX9BoM&^4KT2P0S6F( uf=v^Jq6{aTC=<#?C=g(P0R<2szyO;Mbx=YJH6#!X7z|)L1~d#55CA*d3tI^Q literal 0 HcmV?d00001 diff --git a/source/web/images/icons/workflow_task.gif b/source/web/images/icons/workflow_task.gif new file mode 100644 index 0000000000000000000000000000000000000000..6cee9ec03951236aa82eee35b0dba94ab51934e8 GIT binary patch literal 595 zcmZ?wbhEHb6krfwc*Xz%|NsA=w_x6{-@ktR{PF$A_n!Xlmv3IQwztfgH+%NnS+nNM z{P_99hfnX{zJK%P-RoCxUN*HhOqx1j;*|agllz{&c>Lt~qsPx4K74Zj_Wc{T?p?om z_u7p+SFhi`GIhqJnRBM~PwegK>w5I`{=+Bt?mxP7@8Rvc4{qJLfAjXe8}k;-nK5hH zv>8*TPM*p_CJ$wH0>9ZG4zJB}iRawG^PK=E1>M-r_UcfdG_$pllu=J-@E_tPFHtFXIK036-#H$o-uRQ z^pBt3zyI*|-TOCx{`~&=^T&@L-@kqPI&a?GWlNX-{{8#@{rg+DZk;h>MoUWzFdV?) zL03ZYCkrD3LnMO^$W~CCFtBfEh-_*Kb@Ol!ZSHCgW%Bb6FujEH!_sl(!xC4GTeusU3+qv81 zn)b#vcuxR_(`xrksF6*arl1^_j@3>yFd literal 0 HcmV?d00001 diff --git a/source/web/images/icons/workflow_task_large.gif b/source/web/images/icons/workflow_task_large.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf5bd9108408e965254a944c10fed8b98685a9cc GIT binary patch literal 1540 zcmd6m`#aMM0LHf&Hp@vwo=_9@(4nT>x}7H^my;f(oO4Lg<)k_aEpsa~V;D9hmoVji z$-Z)#JqR<#(A>ss%-Y=6T*h)K&*RkjE6)4F`}6yJp3m##a@qEbKN5rlZGwJgcXxOD z+xF(x=EmkmGrgHoM9DA6&&kd4_4Dz$`Pak8fnnj#$r&V4dRj^v5uXqj8;8Z>Vq#)n zt|{az^5x~#rKJ_wmnErGwm82y$Ky|o^SHfi78(A{?6-;R`2tQ`~X>s9=V7-TT_@0KZ%QH~nt= zj`4<`1piY*t*opmi+&jy5rqkl3=0cKqr*Z&(ZRu?PX>qB{hxYU+vzE3$%)AcgrxWx z@s#khU|PhVnwb;`d6QG)l(z+iMfqFv9Xbn5e|nl zI5;>kFwoc6$6~R1dU}{lCWFCfYinz5ZKc!cG#ag`si~o%p{}kD0D#)s+N!Fmii(Po zl9Iy0!XIA!=hy$b47Z_R5U3Yq_H*UWPk>;%pbWUav-@q+3y24tKPY8h9SItUMo4UL zD##-Y0}9jzj5=;uu}Ba!8KkFbWg9_+c}iHxk0xk#6(O@dq+-ALgVfTLJew@fNqtzl zX8AjaYn>ckX3xnzWS0eh<#o}-mRsmSAzB@%TplLrp9#8x z?pGbuQ_Be=0{%*A6<*=Uqb3q`NR_0mrQ29}oxus2d zIju8bC@8f=M;8dej;yE|1Xb^PIu=~7@~(R@<%+s@7U5`q5DN;SI;rf*Kk=*y>6l)1 z19(%U0c{#3vyHucv5sgWjRZx)Jc{g9HqmP?8kTYU5N7vbfSr!La}4{0stL(KI~g_X ztm&Fb;%FDTWp`+4DLfJ8^~NN;zdnbGIN7GbxVZoL+4L^WD<)kK9n=dILGmi;z1p2RtkTBt};(0gWTS`+<$LF9?v`26W#eaXKeq9gg6R;$Ym~MBR!m&C}WK zq`k=|o%T82`lnn@w(MwPA!^Soh$x1MJK?q25jbP7I#_Op!2Z$~YiI>pXP37_l}s&| z6C`_0m-7LEFvU@k(y%JAzI_pHQ!Xz@mA!q~Z{fp1LDNsSYe1e@L5H1T&KEeu?GAUjN=Yfv$1Wzlr21_6Qu4$?K`eo zJ-v$8IAaDt_bJwbt6P%{fG#6f%N>}ZF^Q_AbsED?(29-m@m6>4{~~X3!yp(;i@U^C z2P7VZW1;G=gzSmVK0n%OXzTw$%R(Y>I{aeKTfhwouUj8{v1Q0O{99p*rZbN9RB_ln fd3C+N4kGF}WIIE_sp@$c4B5fWM@epAFzDRB?aA9U literal 0 HcmV?d00001 diff --git a/source/web/index.jsp b/source/web/index.jsp index 8916281a16..699051315b 100644 --- a/source/web/index.jsp +++ b/source/web/index.jsp @@ -1,21 +1,51 @@ <%-- - Copyright (C) 2005 Alfresco, Inc. - - Licensed under the Mozilla Public License version 1.1 - with a permitted attribution clause. You may obtain a - copy of the License at - - http://www.alfresco.org/legal/license.txt - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - either express or implied. See the License for the specific - language governing permissions and limitations under the - License. ---%> - -<%-- redirect to the web application's start page --%> -<% -response.sendRedirect(request.getContextPath() + "/faces/jsp/browse/browse.jsp"); -%> \ No newline at end of file +Copyright (C) 2005 Alfresco, Inc. + +Licensed under the Mozilla Public License version 1.1 +with a permitted attribution clause. You may obtain a +copy of the License at + +http://www.alfresco.org/legal/license.txt + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the +License. +--%> + +<%@ page import="org.springframework.web.context.support.WebApplicationContextUtils" %> +<%@ page import="org.alfresco.config.ConfigService" %> +<%@ page import="org.alfresco.web.app.servlet.AuthenticationHelper" %> +<%@ page import="org.alfresco.web.bean.NavigationBean" %> +<%@ page import="org.alfresco.web.bean.repository.User" %> +<%@ page import="org.alfresco.web.bean.repository.PreferencesService" %> +<%@ page import="org.alfresco.web.config.ClientConfigElement" %> + +<%-- redirect to the web application's appropriate start page --%> +<% +// get the start location as configured by the web-client config +ConfigService configService = (ConfigService)WebApplicationContextUtils.getRequiredWebApplicationContext(session.getServletContext()).getBean("webClientConfigService"); +ClientConfigElement configElement = (ClientConfigElement)configService.getGlobalConfig().getConfigElement("client"); +String location = configElement.getInitialLocation(); + +// override with the users preference if they have one +User user = (User)session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER); +if (user != null) +{ + String preference = (String)PreferencesService.getPreferences(user).getValue("start-location"); + if (preference != null) + { + location = preference; + } +} +if (NavigationBean.LOCATION_MYALFRESCO.equals(location)) +{ + response.sendRedirect(request.getContextPath() + "/faces/jsp/dashboards/container.jsp"); +} +else +{ + response.sendRedirect(request.getContextPath() + "/faces/jsp/browse/browse.jsp"); +} +%> diff --git a/source/web/jsp/admin/admin-console.jsp b/source/web/jsp/admin/admin-console.jsp index 1afb36f029..ae88d603fc 100644 --- a/source/web/jsp/admin/admin-console.jsp +++ b/source/web/jsp/admin/admin-console.jsp @@ -126,6 +126,12 @@ + + + + + + <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "ballongrey"); %> diff --git a/source/web/jsp/content/view-content-properties.jsp b/source/web/jsp/content/view-content-properties.jsp new file mode 100644 index 0000000000..95e5c607b2 --- /dev/null +++ b/source/web/jsp/content/view-content-properties.jsp @@ -0,0 +1,24 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + + \ No newline at end of file diff --git a/source/web/jsp/dashboards/container-light.jsp b/source/web/jsp/dashboards/container-light.jsp new file mode 100644 index 0000000000..d3a97f35a6 --- /dev/null +++ b/source/web/jsp/dashboards/container-light.jsp @@ -0,0 +1,54 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.app.Application" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + + + + + + + +
+ + + +
+ +
+ +
+ +
\ No newline at end of file diff --git a/source/web/jsp/dashboards/container.jsp b/source/web/jsp/dashboards/container.jsp index adc53b82af..8a1e21eef4 100644 --- a/source/web/jsp/dashboards/container.jsp +++ b/source/web/jsp/dashboards/container.jsp @@ -74,7 +74,7 @@
- + diff --git a/source/web/jsp/dashboards/dashlets/checkedout-docs.jsp b/source/web/jsp/dashboards/dashlets/checkedout-docs.jsp new file mode 100644 index 0000000000..ea73ce7215 --- /dev/null +++ b/source/web/jsp/dashboards/dashlets/checkedout-docs.jsp @@ -0,0 +1,20 @@ +<%-- + Copyright (C) 2006 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%-- Note that this template is loaded from the classpath --%> + diff --git a/source/web/jsp/dashboards/dashlets/getting-started.jsp b/source/web/jsp/dashboards/dashlets/getting-started.jsp index f7dd0ffa14..c8b4eee5fc 100644 --- a/source/web/jsp/dashboards/dashlets/getting-started.jsp +++ b/source/web/jsp/dashboards/dashlets/getting-started.jsp @@ -24,33 +24,93 @@ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellow", "#ffffcc"); %> - - - - + + + - - - - -
- -
-
+ + + + +
+ +
+
- - - - -
- -
+ + + + +
+ +
+
+ + + + + +
+ +
+
- - + + + + + + +
+ +
+
+ + + + + + + + + + +
+ +
+
+ + + + + + + + + + +
+ +
+
+ + + + + + + + + + +
+ +
+
+
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "yellow"); %> diff --git a/source/web/jsp/dashboards/dashlets/my-docs.jsp b/source/web/jsp/dashboards/dashlets/my-docs.jsp index e79ba1c20a..2908add03f 100644 --- a/source/web/jsp/dashboards/dashlets/my-docs.jsp +++ b/source/web/jsp/dashboards/dashlets/my-docs.jsp @@ -14,9 +14,7 @@ language governing permissions and limitations under the License. --%> -<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> -<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> -<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> +<%-- Note that this template is loaded from the classpath --%> diff --git a/source/web/jsp/dashboards/dashlets/my-images.jsp b/source/web/jsp/dashboards/dashlets/my-images.jsp new file mode 100644 index 0000000000..a904b9d2b9 --- /dev/null +++ b/source/web/jsp/dashboards/dashlets/my-images.jsp @@ -0,0 +1,20 @@ +<%-- + Copyright (C) 2006 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%-- Note that this template is loaded from the classpath --%> + diff --git a/source/web/jsp/dialog/about.jsp b/source/web/jsp/dialog/about.jsp index dfcf4bb32a..0fb6309acf 100644 --- a/source/web/jsp/dialog/about.jsp +++ b/source/web/jsp/dialog/about.jsp @@ -100,9 +100,9 @@
- http://www.alfresco.org + http://www.alfresco.com

- Alfresco Software Inc. © 2005-2006 All rights reserved. Legal and License + Alfresco Software Inc. © 2005-2006 All rights reserved. Legal and License

diff --git a/source/web/jsp/dialog/checkout-file.jsp b/source/web/jsp/dialog/checkout-file.jsp index c1ac8ac394..7a4284cb69 100644 --- a/source/web/jsp/dialog/checkout-file.jsp +++ b/source/web/jsp/dialog/checkout-file.jsp @@ -121,7 +121,7 @@ - + diff --git a/source/web/jsp/dialog/edit-html-inline.jsp b/source/web/jsp/dialog/edit-html-inline.jsp index 4430c68a08..a205d7512e 100644 --- a/source/web/jsp/dialog/edit-html-inline.jsp +++ b/source/web/jsp/dialog/edit-html-inline.jsp @@ -153,7 +153,7 @@ - + diff --git a/source/web/jsp/dialog/edit-text-inline.jsp b/source/web/jsp/dialog/edit-text-inline.jsp index 137dd3e494..35cfc19545 100644 --- a/source/web/jsp/dialog/edit-text-inline.jsp +++ b/source/web/jsp/dialog/edit-text-inline.jsp @@ -126,7 +126,7 @@ - + diff --git a/source/web/jsp/dialog/undocheckout-file.jsp b/source/web/jsp/dialog/undocheckout-file.jsp index a093647aaf..ce5ad2fdab 100644 --- a/source/web/jsp/dialog/undocheckout-file.jsp +++ b/source/web/jsp/dialog/undocheckout-file.jsp @@ -115,7 +115,7 @@ - + diff --git a/source/web/jsp/users/email-space-users.jsp b/source/web/jsp/users/email-space-users.jsp index 75994aa0b6..d2005cd847 100644 --- a/source/web/jsp/users/email-space-users.jsp +++ b/source/web/jsp/users/email-space-users.jsp @@ -24,22 +24,27 @@ diff --git a/source/web/jsp/users/user-console.jsp b/source/web/jsp/users/user-console.jsp index 008991349e..6457bc0636 100644 --- a/source/web/jsp/users/user-console.jsp +++ b/source/web/jsp/users/user-console.jsp @@ -134,14 +134,25 @@
- + <%-- - - --%> + - +
+ + + +
+ :  + + <%-- Start Location drop-down selector --%> + + + +
diff --git a/source/web/jsp/workflow/manage-task-dialog.jsp b/source/web/jsp/workflow/manage-task-dialog.jsp new file mode 100644 index 0000000000..131268c079 --- /dev/null +++ b/source/web/jsp/workflow/manage-task-dialog.jsp @@ -0,0 +1,132 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + + + + + + + + + + + + + <%-- Name column --%> + + + + + + + + + + + + <%-- Description column --%> + + + + + + + + <%-- Path column --%> + + + + + + + + <%-- Created Date column --%> + + + + + + + + + + <%-- Modified Date column --%> + + + + + + + + + + <%-- Actions column --%> + + + + + + + + <%-- Completed column --%> + <%-- + + + + + + + + + --%> + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/web/jsp/workflow/reassign-task-dialog.jsp b/source/web/jsp/workflow/reassign-task-dialog.jsp new file mode 100644 index 0000000000..0e14e13887 --- /dev/null +++ b/source/web/jsp/workflow/reassign-task-dialog.jsp @@ -0,0 +1,40 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> + + + + + + \ No newline at end of file diff --git a/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp b/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp index 969d4ef1bb..4e2b0af400 100644 --- a/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp +++ b/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp @@ -44,7 +44,91 @@
+ + + + + + + + <%-- Name column --%> + + + + + + + + + + + <%-- Description column --%> + + + + + + + + <%-- Path column --%> + + + + + + + + <%-- Created Date column --%> + + + + + + + + + + <%-- Modified Date column --%> + + + + + + + + + + <%-- Actions column --%> + + + + + + + + + + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/source/web/jsp/workflow/tasks-completed-dashlet.jsp b/source/web/jsp/workflow/tasks-completed-dashlet.jsp new file mode 100644 index 0000000000..0efb655524 --- /dev/null +++ b/source/web/jsp/workflow/tasks-completed-dashlet.jsp @@ -0,0 +1,72 @@ +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + + + + <%-- Primary column for details view mode --%> + + + + + + + + + + + + + + + <%-- Task id column --%> + + + + + + + + <%-- Source column --%> + + + + + + + + <%-- Completed date column --%> + + + + + + + + + + <%-- Outcome column --%> + + + + + + + + <%-- Actions column --%> + + + + + + + + + \ No newline at end of file diff --git a/source/web/jsp/workflow/tasks-todo-dashlet.jsp b/source/web/jsp/workflow/tasks-todo-dashlet.jsp new file mode 100644 index 0000000000..ee386f5ca5 --- /dev/null +++ b/source/web/jsp/workflow/tasks-todo-dashlet.jsp @@ -0,0 +1,80 @@ +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + + + + <%-- Primary column for details view mode --%> + + + + + + + + + + + + + + + <%-- Task id column --%> + + + + + + + + <%-- Source column --%> + + + + + + + + <%-- Due date column --%> + + + + + + + + + + <%-- Status column --%> + + + + + + + + <%-- Priority column --%> + + + + + + + + <%-- Actions column --%> + + + + + + + + + \ No newline at end of file diff --git a/source/web/jsp/workflow/view-completed-task-dialog.jsp b/source/web/jsp/workflow/view-completed-task-dialog.jsp new file mode 100644 index 0000000000..6287762b9c --- /dev/null +++ b/source/web/jsp/workflow/view-completed-task-dialog.jsp @@ -0,0 +1,98 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + + + + + + + + + + + + + <%-- Name column --%> + + + + + + + + + + + + <%-- Description column --%> + + + + + + + + <%-- Path column --%> + + + + + + + + <%-- Created Date column --%> + + + + + + + + + + <%-- Modified Date column --%> + + + + + + + + + + + + + + + + + +