diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 71754c227d..dcfec20cce 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -849,6 +849,24 @@ recovery_report_reason=Failure Reason # My Alfresco messages my_alfresco=My Alfresco +title_my_alfresco=My Alfresco +dashboard_info=My Alfresco Dashboard +dashboard_description=Configure this view and build your personal Alfresco dashboard +configure=Configure + +# My Alfresco Dashlets messages +layout_single_label=Single Column +layout_single_desc=This layout displays components in a single column the full width of the page +layout_narrow_left_label=Two Column Narrow Left +layout_narrow_left_desc=This layout display components in two columns with a narrow left hand column +layout_narrow_right_label=Two Column Narrow Right +layout_narrow_right_desc=This layout display components in two columns with a narrow right hand column +layout_three_column_label=Three Column +layout_three_column_desc=This layout displays components across three columns of equal width +dashlet_gettingstarted_label=Getting Started +dashlet_gettingstarted_desc=This component displays helpful information and links for getting started with the Alfresco web-client application + +# User Console and Settings messages title_user_console=User Options user_console=User Options user_console_info=User Options diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 58056f7637..c60cac453b 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -16,6 +16,7 @@ + @@ -159,7 +160,37 @@ - + + + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/web/app/Application.java b/source/java/org/alfresco/web/app/Application.java index f4fea404b6..8e00ddb3f4 100644 --- a/source/java/org/alfresco/web/app/Application.java +++ b/source/java/org/alfresco/web/app/Application.java @@ -38,6 +38,7 @@ import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.web.app.servlet.AuthenticationHelper; import org.alfresco.web.app.servlet.FacesHelper; import org.alfresco.web.bean.ErrorBean; +import org.alfresco.web.bean.dashboard.DashboardManager; import org.alfresco.web.bean.dialog.DialogManager; import org.alfresco.web.bean.repository.User; import org.alfresco.web.bean.wizard.WizardManager; @@ -189,6 +190,16 @@ public class Application return (WizardManager)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "WizardManager"); } + /** + * Retrieves the DashboardManager managed bean + * + * @return DashboardManager bean + */ + public static DashboardManager getDashboardManager() + { + return (DashboardManager)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "DashboardManager"); + } + /** * Retrieves the configured error page for the application * diff --git a/source/java/org/alfresco/web/app/servlet/BaseServlet.java b/source/java/org/alfresco/web/app/servlet/BaseServlet.java index e810ed4445..90b4c7c687 100644 --- a/source/java/org/alfresco/web/app/servlet/BaseServlet.java +++ b/source/java/org/alfresco/web/app/servlet/BaseServlet.java @@ -66,16 +66,18 @@ public abstract class BaseServlet extends HttpServlet static { validRedirectJSPs.add("/jsp/browse/browse.jsp"); - validRedirectJSPs.add("/jsp/browse/dashboard.jsp"); validRedirectJSPs.add("/jsp/admin/admin-console.jsp"); validRedirectJSPs.add("/jsp/admin/node-browser.jsp"); validRedirectJSPs.add("/jsp/admin/store-browser.jsp"); + validRedirectJSPs.add("/jsp/users/user-console.jsp"); validRedirectJSPs.add("/jsp/categories/categories.jsp"); validRedirectJSPs.add("/jsp/dialog/about.jsp"); validRedirectJSPs.add("/jsp/dialog/advanced-search.jsp"); validRedirectJSPs.add("/jsp/dialog/system-info.jsp"); + 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); diff --git a/source/java/org/alfresco/web/bean/NavigationBean.java b/source/java/org/alfresco/web/bean/NavigationBean.java index 0cc97b2301..9ed4198619 100644 --- a/source/java/org/alfresco/web/bean/NavigationBean.java +++ b/source/java/org/alfresco/web/bean/NavigationBean.java @@ -62,6 +62,10 @@ import org.apache.log4j.Logger; */ public class NavigationBean { + private static final String OUTCOME_MYALFRESCO = "myalfresco"; + + private static final String OUTCOME_BROWSE = "browse"; + /** * Default constructor */ @@ -587,6 +591,9 @@ public class NavigationBean elements.add(new NavigationBreadcrumbHandler(companyHome.getNodeRef(), companyHome.getName())); setLocation(elements); setCurrentNodeId(companyHome.getId()); + + // we need to force a navigation to refresh the browse screen breadcrumb + context.getApplication().getNavigationHandler().handleNavigation(context, null, OUTCOME_BROWSE); } else if (LOCATION_HOME.equals(location)) { @@ -597,6 +604,9 @@ public class NavigationBean elements.add(new NavigationBreadcrumbHandler(homeSpaceRef, homeSpaceName)); setLocation(elements); setCurrentNodeId(homeSpaceRef.getId()); + + // we need to force a navigation to refresh the browse screen breadcrumb + context.getApplication().getNavigationHandler().handleNavigation(context, null, OUTCOME_BROWSE); } else if (LOCATION_GUEST.equals(location)) { @@ -605,10 +615,31 @@ public class NavigationBean elements.add(new NavigationBreadcrumbHandler(guestHome.getNodeRef(), guestHome.getName())); setLocation(elements); setCurrentNodeId(guestHome.getId()); + + // we need to force a navigation to refresh the browse screen breadcrumb + context.getApplication().getNavigationHandler().handleNavigation(context, null, OUTCOME_BROWSE); + } + else if (LOCATION_DASHBOARD.equals(location)) + { + List elements = new ArrayList(1); + elements.add(new IBreadcrumbHandler() + { + public String navigationOutcome(UIBreadcrumb breadcrumb) + { + setLocation( (List)breadcrumb.getValue() ); + return OUTCOME_MYALFRESCO; + }; + + public String toString() + { + return Application.getMessage(FacesContext.getCurrentInstance(), MSG_MYALFRESCO); + }; + }); + setLocation(elements); + + // we need to force a navigation to refresh the browse screen breadcrumb + context.getApplication().getNavigationHandler().handleNavigation(context, null, OUTCOME_MYALFRESCO); } - - // we need to force a navigation to refresh the browse screen breadcrumb - context.getApplication().getNavigationHandler().handleNavigation(context, null, "browse"); } catch (InvalidNodeRefException refErr) { @@ -711,7 +742,7 @@ public class NavigationBean } else { - return "browse"; + return OUTCOME_BROWSE; } } @@ -734,6 +765,9 @@ public class NavigationBean private static final String LOCATION_COMPANY = "company"; private static final String LOCATION_HOME = "home"; private static final String LOCATION_GUEST = "guest"; + private static final String LOCATION_DASHBOARD = "dashboard"; + + private static final String MSG_MYALFRESCO = "my_alfresco"; private static final String ERROR_DELETED_FOLDER = "error_deleted_folder"; diff --git a/source/java/org/alfresco/web/config/ActionsConfigElement.java b/source/java/org/alfresco/web/config/ActionsConfigElement.java index 4331d6b85a..b57336ff36 100644 --- a/source/java/org/alfresco/web/config/ActionsConfigElement.java +++ b/source/java/org/alfresco/web/config/ActionsConfigElement.java @@ -288,7 +288,7 @@ public class ActionsConfigElement extends ConfigElementAdapter return this.actions; } - /*pacakge*/ Set getHiddenActions() + /*package*/ Set getHiddenActions() { return this.hiddenActions; } diff --git a/source/java/org/alfresco/web/config/DashboardsConfigElement.java b/source/java/org/alfresco/web/config/DashboardsConfigElement.java new file mode 100644 index 0000000000..3a3efc89ac --- /dev/null +++ b/source/java/org/alfresco/web/config/DashboardsConfigElement.java @@ -0,0 +1,151 @@ +/* + * 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.config; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.config.ConfigElement; +import org.alfresco.config.ConfigException; +import org.alfresco.config.element.ConfigElementAdapter; + +/** + * Dashboard config element. + * + * @author Kevin Roast + */ +public class DashboardsConfigElement extends ConfigElementAdapter +{ + public static final String CONFIG_ELEMENT_ID = "dashboards"; + + private Map layoutDefs = new LinkedHashMap(4, 1.0f); + private Map dashletDefs = new LinkedHashMap(8, 1.0f); + + /** + * Default constructor + */ + public DashboardsConfigElement() + { + super(CONFIG_ELEMENT_ID); + } + + /** + * @param name + */ + public DashboardsConfigElement(String name) + { + super(name); + } + + /** + * @see org.alfresco.config.element.ConfigElementAdapter#getChildren() + */ + public List getChildren() + { + throw new ConfigException("Reading the Dashboards config via the generic interfaces is not supported"); + } + + /** + * @see org.alfresco.config.element.ConfigElementAdapter#combine(org.alfresco.config.ConfigElement) + */ + public ConfigElement combine(ConfigElement configElement) + { + DashboardsConfigElement newElement = (DashboardsConfigElement)configElement; + DashboardsConfigElement combinedElement = new DashboardsConfigElement(); + + // put all into combined from this and then from new to override any already present + combinedElement.dashletDefs.putAll(this.dashletDefs); + combinedElement.dashletDefs.putAll(newElement.dashletDefs); + + combinedElement.layoutDefs.putAll(this.layoutDefs); + combinedElement.layoutDefs.putAll(newElement.layoutDefs); + + return combinedElement; + } + + /*package*/ void addLayoutDefinition(LayoutDefinition def) + { + this.layoutDefs.put(def.Id, def); + } + + public LayoutDefinition getLayoutDefinition(String id) + { + return this.layoutDefs.get(id); + } + + /*package*/ void addDashletDefinition(DashletDefinition def) + { + this.dashletDefs.put(def.Id, def); + } + + public DashletDefinition getDashletDefinition(String id) + { + return this.dashletDefs.get(id); + } + + public Iterator getLayouts() + { + return this.layoutDefs.entrySet().iterator(); + } + + public Iterator getDashlets() + { + return this.dashletDefs.entrySet().iterator(); + } + + /** + * Structure class for the definition of a dashboard page layout + */ + public static class LayoutDefinition + { + LayoutDefinition(String id) + { + this.Id = id; + } + + public String Id; + public String Image; + public int Columns; + public int ColumnLength; + public String Label; + public String LabelId; + public String Description; + public String DescriptionId; + public String JSPPage; + } + + /** + * Structure class for the definition of a dashboard dashlet component + */ + public static class DashletDefinition + { + DashletDefinition(String id) + { + this.Id = id; + } + + public String Id; + public boolean AllowNarrow = true; + public String Label; + public String LabelId; + public String Description; + public String DescriptionId; + public String JSPPage; + } +} diff --git a/source/java/org/alfresco/web/config/DashboardsElementReader.java b/source/java/org/alfresco/web/config/DashboardsElementReader.java new file mode 100644 index 0000000000..b9e3e08079 --- /dev/null +++ b/source/java/org/alfresco/web/config/DashboardsElementReader.java @@ -0,0 +1,205 @@ +/* + * 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.config; + +import java.util.Iterator; + +import org.alfresco.config.ConfigElement; +import org.alfresco.config.ConfigException; +import org.alfresco.config.xml.elementreader.ConfigElementReader; +import org.alfresco.web.config.DashboardsConfigElement.DashletDefinition; +import org.alfresco.web.config.DashboardsConfigElement.LayoutDefinition; +import org.dom4j.Element; + +/** + * Reader for the 'dashboards' config element and child elements. + * + * @author Kevin Roast + */ +public class DashboardsElementReader implements ConfigElementReader +{ + public static final String ELEMENT_DASHBOARDS = "dashboards"; + public static final String ELEMENT_LAYOUTS = "layouts"; + 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 ATTR_ID = "id"; + public static final String ATTR_COLUMNS = "columns"; + public static final String ATTR_COLUMNLENGTH = "column-length"; + public static final String ATTR_IMAGE = "image"; + public static final String ATTR_LABEL = "label"; + public static final String ATTR_DESCRIPTION = "description"; + public static final String ATTR_LABELID = "label-id"; + public static final String ATTR_DESCRIPTIONID = "description-id"; + public static final String ATTR_JSP = "jsp"; + public static final String ATTR_ALLOWNARROW = "allow-narrow"; + + /** + * @see org.alfresco.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element) + */ + @SuppressWarnings("unchecked") + public ConfigElement parse(Element element) + { + DashboardsConfigElement configElement = new DashboardsConfigElement(); + + if (element != null) + { + if (DashboardsConfigElement.CONFIG_ELEMENT_ID.equals(element.getName()) == false) + { + throw new ConfigException("DashboardsElementReader can only process elements of type 'dashboards'"); + } + + Element layoutsElement = element.element(ELEMENT_LAYOUTS); + if (layoutsElement != null) + { + Iterator layoutsItr = layoutsElement.elementIterator(ELEMENT_LAYOUT); + while (layoutsItr.hasNext()) + { + LayoutDefinition layoutDef = parseLayoutDefinition(layoutsItr.next()); + configElement.addLayoutDefinition(layoutDef); + } + } + + Element dashletsElement = element.element(ELEMENT_DASHLETS); + if (dashletsElement != null) + { + Iterator dashletsItr = dashletsElement.elementIterator(ELEMENT_DASHLET); + while (dashletsItr.hasNext()) + { + DashletDefinition dashletDef = parseDashletDefinition(dashletsItr.next()); + configElement.addDashletDefinition(dashletDef); + } + } + } + + return configElement; + } + + /** + * Parse a single Layout definition from config. + * + * @param config + * + * @return LayoutDefinition for the specified config element. + */ + private static LayoutDefinition parseLayoutDefinition(Element config) + { + String id = getMandatoryLayoutAttributeValue(config, ATTR_ID); + + LayoutDefinition def = new LayoutDefinition(id); + + String columns = getMandatoryLayoutAttributeValue(config, ATTR_COLUMNS); + def.Columns = Integer.parseInt(columns); + String columnLength = getMandatoryLayoutAttributeValue(config, ATTR_COLUMNLENGTH); + def.ColumnLength = Integer.parseInt(columnLength); + def.Image = getMandatoryLayoutAttributeValue(config, ATTR_IMAGE); + def.JSPPage = getMandatoryLayoutAttributeValue(config, ATTR_JSP); + String label = config.attributeValue(ATTR_LABEL); + String labelId = config.attributeValue(ATTR_LABELID); + if ((label == null || label.length() == 0) && (labelId == null || labelId.length() == 0)) + { + throw new ConfigException("Either 'label' or 'label-id' attribute must be specified for Dashboard 'layout' configuration element."); + } + def.Label = label; + def.LabelId = labelId; + String description = config.attributeValue(ATTR_DESCRIPTION); + String descriptionId = config.attributeValue(ATTR_DESCRIPTIONID); + if ((description == null || description.length() == 0) && (descriptionId == null || descriptionId.length() == 0)) + { + throw new ConfigException("Either 'description' or 'description-id' attribute must be specified for Dashboard 'layout' configuration element."); + } + def.Description = description; + def.DescriptionId = descriptionId; + + return def; + } + + /** + * Return a mandatory layout attribute layout. Throw an exception if the value is not found. + * + * @param config + * @param attr + * + * @return String value + */ + private static String getMandatoryLayoutAttributeValue(Element config, String attr) + { + String value = config.attributeValue(attr); + if (value == null || value.length() == 0) + { + throw new ConfigException("Missing mandatory '" + attr + "' attribute for Dashboard 'layout' configuration element."); + } + return value; + } + + /** + * Parse a single Dashlet definition from config. + * + * @param config + * + * @return DashletDefinition for the specified config element. + */ + private static DashletDefinition parseDashletDefinition(Element config) + { + String id = getMandatoryDashletAttributeValue(config, ATTR_ID); + + DashletDefinition def = new DashletDefinition(id); + + String allowNarrow = config.attributeValue(ATTR_ALLOWNARROW); + if (allowNarrow != null && allowNarrow.length() != 0) + { + def.AllowNarrow = Boolean.parseBoolean(allowNarrow); + } + def.JSPPage = getMandatoryDashletAttributeValue(config, ATTR_JSP); + String label = config.attributeValue(ATTR_LABEL); + String labelId = config.attributeValue(ATTR_LABELID); + if ((label == null || label.length() == 0) && (labelId == null || labelId.length() == 0)) + { + throw new ConfigException("Either 'label' or 'label-id' attribute must be specified for Dashboard 'dashlet' configuration element."); + } + def.Label = label; + def.LabelId = labelId; + String description = config.attributeValue(ATTR_DESCRIPTION); + String descriptionId = config.attributeValue(ATTR_DESCRIPTIONID); + if ((description == null || description.length() == 0) && (descriptionId == null || descriptionId.length() == 0)) + { + throw new ConfigException("Either 'description' or 'description-id' attribute must be specified for Dashboard 'dashlet' configuration element."); + } + def.Description = description; + def.DescriptionId = descriptionId; + + return def; + } + + /** + * Return a mandatory dashlet attribute layout. Throw an exception if the value is not found. + * + * @param config + * @param attr + * + * @return String value + */ + private static String getMandatoryDashletAttributeValue(Element config, String attr) + { + String value = config.attributeValue(attr); + if (value == null || value.length() == 0) + { + throw new ConfigException("Missing mandatory '" + attr + "' attribute for Dashboard 'dashlet' configuration element."); + } + return value; + } +} diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index c8cf45c103..cff60d1f04 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -1437,6 +1437,13 @@ session + + Bean that manages the Dashboard framework + DashboardManager + org.alfresco.web.bean.dashboard.DashboardManager + session + + diff --git a/source/web/WEB-INF/faces-config-navigation.xml b/source/web/WEB-INF/faces-config-navigation.xml index 6e0ca06a11..1528a0d7dd 100644 --- a/source/web/WEB-INF/faces-config-navigation.xml +++ b/source/web/WEB-INF/faces-config-navigation.xml @@ -32,6 +32,10 @@ browse /jsp/browse/browse.jsp + + myalfresco + /jsp/dashboards/container.jsp + about /jsp/dialog/about.jsp diff --git a/source/web/css/main.css b/source/web/css/main.css index b9ae62af06..79c9f8d46e 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -488,3 +488,18 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl { vertical-align: top; } + +.tableThirdWidth +{ + width: 33%; +} + +.tableNarrowWidth +{ + width: 30%; +} + +.tableWideWidth +{ + width: 70%; +} diff --git a/source/web/images/icons/configure.gif b/source/web/images/icons/configure.gif new file mode 100644 index 0000000000..374f787193 Binary files /dev/null and b/source/web/images/icons/configure.gif differ diff --git a/source/web/images/icons/dashboard.gif b/source/web/images/icons/dashboard.gif new file mode 100644 index 0000000000..d79e1a233b Binary files /dev/null and b/source/web/images/icons/dashboard.gif differ diff --git a/source/web/images/icons/dashboard_large.gif b/source/web/images/icons/dashboard_large.gif new file mode 100644 index 0000000000..336f7967dd Binary files /dev/null and b/source/web/images/icons/dashboard_large.gif differ diff --git a/source/web/jsp/dashboard.jsp b/source/web/jsp/dashboard.jsp deleted file mode 100644 index 190c6fcef7..0000000000 --- a/source/web/jsp/dashboard.jsp +++ /dev/null @@ -1,169 +0,0 @@ -<%-- - 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.ui.common.PanelGenerator" %> - - - - - - <%-- load a bundle of properties with I18N strings --%> - - - - - <%-- Main outer table --%> - - - <%-- Title bar --%> - - - - - <%-- Main area --%> - - <%-- Shelf --%> - - - <%-- Work Area --%> - - -
- <%@ include file="parts/titlebar.jsp" %> -
- <%@ include file="parts/shelf.jsp" %> - - - <%-- Breadcrumb --%> - <%@ include file="parts/breadcrumb.jsp" %> - - <%-- Status and Actions --%> - - - - - - - <%-- separator row with gradient shadow --%> - - - - - - - <%-- Main --%> - - - - - - - <%-- separator row with bottom panel graphics --%> - - - - - - -
- - <%-- Status and Actions inner contents table --%> - <%-- Generally this consists of an icon, textual summary and actions for the current object --%> - - - - - -
- -
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - -
- - - - - -
- - - - - -
- -
-
- -
- -
- -
\ No newline at end of file diff --git a/source/web/jsp/parts/titlebar.jsp b/source/web/jsp/parts/titlebar.jsp index 1b905a3cfd..01840f1308 100644 --- a/source/web/jsp/parts/titlebar.jsp +++ b/source/web/jsp/parts/titlebar.jsp @@ -31,7 +31,7 @@ - +