diff --git a/app/business/pom.xml b/app/business/pom.xml index eed82f16..ab385991 100644 --- a/app/business/pom.xml +++ b/app/business/pom.xml @@ -68,16 +68,6 @@ provided ${sakai.version} - - - org.sakaiproject.jsf - jsf-tool - - - - org.sakaiproject.jsf - jsf-app - - - org.apache.myfaces.core - myfaces-api - 1.1.5 - - - org.apache.myfaces.core - myfaces-impl - 1.1.5 - - - org.apache.myfaces.tomahawk - tomahawk - 1.1.14 - commons-fileupload @@ -203,11 +177,5 @@ javax.servlet.jsp javax.servlet.jsp-api - - - org.sakaiproject.jsf - myfaces-widgets-depend - pom - diff --git a/app/sakai-tool/pom.xml b/app/sakai-tool/pom.xml index 19898ff5..46a9b6e6 100644 --- a/app/sakai-tool/pom.xml +++ b/app/sakai-tool/pom.xml @@ -33,13 +33,13 @@ - org.sakaiproject.jsf - jsf-tool + org.sakaiproject.jsf2 + jsf2-tool - org.sakaiproject.jsf - jsf-app + org.sakaiproject.jsf2 + jsf2-app javax.faces @@ -97,21 +97,10 @@ provided - - - - org.apache.myfaces.core - myfaces-api - 1.1.10 - - - org.apache.myfaces.core - myfaces-impl - 1.1.10 - + org.apache.myfaces.tomahawk - tomahawk + tomahawk21 1.1.14 @@ -125,16 +114,15 @@ 1.1.2 - - - org.sakaiproject.jsf - myfaces-widgets-depend - pom - - org.sakaiproject.jsf - jsf-spreadsheet + org.sakaiproject.jsf2 + jsf2-spreadsheet + + org.jboss.weld.servlet + weld-servlet-shaded + ${sakai.weld.shaded.version} + diff --git a/app/sakai-tool/src/webapp/META-INF/context.xml b/app/sakai-tool/src/webapp/META-INF/context.xml new file mode 100644 index 00000000..79267c9d --- /dev/null +++ b/app/sakai-tool/src/webapp/META-INF/context.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/app/sakai-tool/src/webapp/WEB-INF/beans.xml b/app/sakai-tool/src/webapp/WEB-INF/beans.xml new file mode 100644 index 00000000..51e8caf9 --- /dev/null +++ b/app/sakai-tool/src/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/app/sakai-tool/src/webapp/WEB-INF/faces-application.xml b/app/sakai-tool/src/webapp/WEB-INF/faces-application.xml index e977bc1f..d0236025 100644 --- a/app/sakai-tool/src/webapp/WEB-INF/faces-application.xml +++ b/app/sakai-tool/src/webapp/WEB-INF/faces-application.xml @@ -1,10 +1,13 @@ - - + - org.sakaiproject.jsf.app.SakaiVariableResolver + org.sakaiproject.jsf2.app.SakaiVariableResolver diff --git a/app/sakai-tool/src/webapp/WEB-INF/spring-facades.xml b/app/sakai-tool/src/webapp/WEB-INF/spring-facades.xml index a0675b41..55fd2b8d 100644 --- a/app/sakai-tool/src/webapp/WEB-INF/spring-facades.xml +++ b/app/sakai-tool/src/webapp/WEB-INF/spring-facades.xml @@ -13,6 +13,7 @@ + - org.sakaiproject.jsf - jsf-tool + org.sakaiproject.jsf2 + jsf2-tool - org.sakaiproject.jsf - jsf-app + org.sakaiproject.jsf2 + jsf2-app - - org.apache.myfaces.core - myfaces-api - 1.1.5 - - - org.apache.myfaces.core - myfaces-impl - 1.1.5 - org.apache.myfaces.tomahawk - tomahawk + tomahawk21 1.1.14 @@ -239,13 +228,13 @@ - org.sakaiproject.jsf - myfaces-widgets-depend + org.sakaiproject.jsf2 + jsf2-widgets-sun-depend pom - org.sakaiproject.jsf - jsf-spreadsheet + org.sakaiproject.jsf2 + jsf2-spreadsheet org.apache.poi @@ -257,6 +246,11 @@ poi-ooxml ${sakai.poi.version} + + javax.el + javax.el-api + 3.0.0 + diff --git a/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties b/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties index cb69ce22..af1bb417 100644 --- a/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties +++ b/app/ui/src/bundle/org/sakaiproject/tool/gradebook/bundle/Messages.properties @@ -69,10 +69,10 @@ score_not_counted_tooltip=Not counted towards course grade # the format description string must be localized by hand to match # whatever the standard Java "short" date format is for the locale. # (Also see the DateTimeConverter.CONVERSION validator message below.) -date_entry_format_description=(mm/dd/yy) +date_entry_format_description=(mm/dd/yyyy) date_entry_today_is=Today is date_entry_week_header=Wk -date_entry_format=MM/dd/yy +date_entry_format=MM/dd/yyyy date_entry_goto=Go To Current Month # Overview page. diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/FacesUtil.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/FacesUtil.java index 5e148ae4..6f28447f 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/FacesUtil.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/FacesUtil.java @@ -39,7 +39,7 @@ import lombok.extern.slf4j.Slf4j; -import org.sakaiproject.jsf.util.LocaleUtil; +import org.sakaiproject.jsf2.util.LocaleUtil; import org.sakaiproject.tool.gradebook.ui.MessagingBean; /** diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/HtmlSortHeaderRenderer.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/HtmlSortHeaderRenderer.java index c6f2c1b4..7fe23d69 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/HtmlSortHeaderRenderer.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/HtmlSortHeaderRenderer.java @@ -58,8 +58,8 @@ import org.apache.myfaces.component.UserRoleUtils; import org.apache.myfaces.component.html.ext.HtmlDataTable; import org.apache.myfaces.custom.sortheader.HtmlCommandSortHeader; -import org.apache.myfaces.shared_impl.renderkit.html.HTML; -import org.apache.myfaces.shared_impl.renderkit.html.HtmlLinkRendererBase; +import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML; +import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlLinkRendererBase; /** * Based on org.apache.myfaces.custom.sortheader.HtmlSortHeaderRenderer. diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/PointsConverter.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/PointsConverter.java index d98f1921..f9dbff27 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/PointsConverter.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/PointsConverter.java @@ -38,6 +38,9 @@ */ @Slf4j public class PointsConverter extends NumberConverter { + + public static final String NULL_PLACEHOLDER = "NULL_PLACEHOLDER"; + public PointsConverter() { setType("number"); ResourceLoader rl = new ResourceLoader(); @@ -48,7 +51,7 @@ public String getAsString(FacesContext context, UIComponent component, Object va if (log.isDebugEnabled()) log.debug("getAsString(" + context + ", " + component + ", " + value + ")"); String formattedScore; - if (value == null) { + if (value == null || NULL_PLACEHOLDER.equals(value)) { formattedScore = FacesUtil.getLocalizedString("score_null_placeholder"); } else { if (value instanceof Number) { diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableRenderer.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableRenderer.java index 973d66bd..0cd3ba36 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableRenderer.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableRenderer.java @@ -16,7 +16,7 @@ import lombok.extern.slf4j.Slf4j; -import org.apache.myfaces.shared_impl.renderkit.html.HTML; +import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML; import org.sakaiproject.tool.cover.ToolManager; import org.sakaiproject.tool.gradebook.Category; diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableTag.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableTag.java index 7208ba1f..adc1ab70 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableTag.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/gradebookItemTable/GradebookItemTableTag.java @@ -1,12 +1,13 @@ package org.sakaiproject.tool.gradebook.jsf.gradebookItemTable; +import javax.faces.application.Application; import javax.faces.component.UIComponent; import javax.faces.component.UIData; import javax.faces.context.FacesContext; import org.apache.myfaces.component.html.ext.HtmlDataTable; -import org.apache.myfaces.taglib.html.HtmlDataTableTag; -import org.sakaiproject.jsf.util.TagUtil; +import org.apache.myfaces.shared_tomahawk.taglib.html.HtmlDataTableTag; +import org.sakaiproject.jsf2.util.TagUtil; public class GradebookItemTableTag extends HtmlDataTableTag { private String sortColumn; @@ -14,6 +15,7 @@ public class GradebookItemTableTag extends HtmlDataTableTag { private String expanded; private java.lang.String value; private java.lang.String _var; + private java.lang.String _rendered; private String cellpadding; private String cellspacing; private String columnClasses; @@ -47,11 +49,12 @@ protected void setProperties(UIComponent component) TagUtil.setString(component, "rowIndexVar", rowIndexVar); TagUtil.setString(component, "value", value); + TagUtil.setBoolean(component, "rendered", _rendered); if (_var != null) { data.setVar(_var); } - //Application application = FacesContext.getCurrentInstance().getApplication(); - //data.setValueBinding("value", application.createValueBinding(value)); + Application application = FacesContext.getCurrentInstance().getApplication(); + data.setValueBinding("value", application.createValueBinding(value)); } @@ -135,4 +138,16 @@ public void setRowIndexVar(String rowIndexVar) { public String getRowIndexVar() { return rowIndexVar; } + + public void setValue(java.lang.String value) { + this.value = value; + } + + public void setVar(java.lang.String _var) { + this._var = _var; + } + + public void setRendered(java.lang.String _rendered) { + this._rendered = _rendered; + } } diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUIRenderer.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUIRenderer.java index ac0605b6..cc10b8d1 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUIRenderer.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUIRenderer.java @@ -31,7 +31,6 @@ import javax.faces.component.UIColumn; import javax.faces.component.UIComponent; import javax.faces.component.UIData; -import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.el.ValueBinding; @@ -83,7 +82,6 @@ public void encodeBegin(FacesContext context, UIComponent component) throws IOEx int columnLock = Integer.parseInt(colLock); //Render Header Facets - UIComponent header = data.getFacet("header"); int headerFacets = getFacetCount(data, "header"); if(headerFacets > 0){ @@ -105,11 +103,17 @@ public void encodeBegin(FacesContext context, UIComponent component) throws IOEx } writer.startElement("li", data); UIComponent facet = column.getFacet("header"); + UIComponent extraHeaderFacet = column.getFacet("extra_header"); if (facet != null){ facet.encodeBegin(context); facet.encodeChildren(context); facet.encodeEnd(context); - //writer.writeText(facet.toString(), null); + //Encode "extra" header + if (extraHeaderFacet != null) { + extraHeaderFacet.encodeBegin(context); + extraHeaderFacet.encodeChildren(context); + extraHeaderFacet.encodeEnd(context); + } } writer.endElement("li"); count++; diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUITag.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUITag.java deleted file mode 100644 index 47f36759..00000000 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/jsf/spreadsheetUI/SpreadsheetUITag.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2008 The Sakai Foundation - * - * Licensed under the Educational Community License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.opensource.org/licenses/ECL-2.0 - * - * 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.sakaiproject.tool.gradebook.jsf.spreadsheetUI; - -import javax.faces.application.Application; -import javax.faces.component.UIComponent; -import javax.faces.component.UIData; -import javax.faces.context.FacesContext; - -import org.apache.myfaces.taglib.html.HtmlDataTableTag; -import org.apache.myfaces.component.html.ext.HtmlDataTable; - -import org.sakaiproject.jsf.util.TagUtil; - -public class SpreadsheetUITag extends HtmlDataTableTag -{ - private String colLock; - private String rowLock; - private String sortColumn; - private String sortAscending; - private String initialHeight; - private java.lang.String value; - private java.lang.String _var; - - - public String getRendererType() { return "SpreadsheetUIRenderer"; } - public String getComponentType() { return HtmlDataTable.COMPONENT_TYPE; } - - protected void setProperties(UIComponent component) - { - - super.setProperties(component); - - UIData data = null; - data = (UIData)component; - - FacesContext context = getFacesContext(); - TagUtil.setString(component, "colLock", colLock); - TagUtil.setString(component, "rowLock", rowLock); - TagUtil.setString(component, "sortColumn", sortColumn); - TagUtil.setString(component, "sortAscending", sortAscending); - TagUtil.setString(component, "initialHeight", initialHeight); - - TagUtil.setString(component, "value", value); - if (_var != null) { - data.setVar(_var); - } - Application application = FacesContext.getCurrentInstance().getApplication(); - data.setValueBinding("value", application.createValueBinding(value)); - } - - public String getColLock() { - return colLock; - } - - public void setColLock(String colLock) { - this.colLock = colLock; - } - - public String getRowLock() { - return rowLock; - } - - public void setRowLock(String rowLock) { - this.rowLock = rowLock; - } - - public String getSortColumn() { - return sortColumn; - } - - public void setSortColumn(String sortColumn) { - this.sortColumn = sortColumn; - } - - public String getSortAscending() { - return sortAscending; - } - - public void setSortAscending(String sortAscending) { - this.sortAscending = sortAscending; - } - - public String getInitialHeight(){ - return initialHeight; - } - - public void setInitialHeight(String initialHeight){ - this.initialHeight = initialHeight; - } - - public void setValue(java.lang.String value) { - this.value = value; - } - - public void setVar(java.lang.String _var) { - this._var = _var; - } -} diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/ConfigurationBean.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/ConfigurationBean.java index 804548a3..ecedb7fb 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/ConfigurationBean.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/ConfigurationBean.java @@ -17,11 +17,13 @@ package org.sakaiproject.tool.gradebook.ui; import java.util.Map; +import java.util.TimeZone; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; +import org.sakaiproject.time.api.UserTimeService; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -41,6 +43,7 @@ public class ConfigurationBean implements ApplicationContextAware{ private Map pluginDefaults; private ServerConfigurationService serverConfigurationService; + private UserTimeService userTimeService; /** * @param name @@ -101,4 +104,12 @@ public void setServerConfigurationService( ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; } + + public void setUserTimeService(UserTimeService userTimeService) { + this.userTimeService = userTimeService; + } + + public TimeZone getUserTimeZone(){ + return userTimeService.getLocalTimeZone(); + } } diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/CourseGradeDetailsBean.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/CourseGradeDetailsBean.java index a31947aa..6607c449 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/CourseGradeDetailsBean.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/CourseGradeDetailsBean.java @@ -34,10 +34,10 @@ import org.apache.commons.lang.StringUtils; import org.sakaiproject.component.cover.ServerConfigurationService; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterCsv; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterPdf; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterXls; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetUtil; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetDataFileWriterCsv; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetDataFileWriterPdf; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetDataFileWriterXlsx; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetUtil; import org.sakaiproject.section.api.coursemanagement.EnrollmentRecord; import org.sakaiproject.service.gradebook.shared.GradebookService; import org.sakaiproject.service.gradebook.shared.StaleObjectModificationException; @@ -468,7 +468,7 @@ else if(this.exportType.equalsIgnoreCase("Excel")){ } SpreadsheetUtil.downloadSpreadsheetData(getSpreadsheetData("excel", fields), getDownloadFileName(getLocalizedString("export_course_grade_prefix")), - new SpreadsheetDataFileWriterXls()); + new SpreadsheetDataFileWriterXlsx()); } else if(this.exportType.equalsIgnoreCase("PDF")){ if(log.isInfoEnabled()) { diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookDependentBean.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookDependentBean.java index d138a88c..31b85541 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookDependentBean.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookDependentBean.java @@ -30,7 +30,7 @@ import org.apache.commons.lang.StringUtils; import org.sakaiproject.component.cover.ServerConfigurationService; -import org.sakaiproject.jsf.util.LocaleUtil; +import org.sakaiproject.jsf2.util.LocaleUtil; import org.sakaiproject.section.api.SectionAwareness; import org.sakaiproject.section.api.coursemanagement.CourseSection; import org.sakaiproject.section.api.facade.Role; diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java index fc0efc8b..343e4cd6 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/GradebookFilePickerServlet.java @@ -26,7 +26,7 @@ import org.sakaiproject.content.api.FilePickerHelper; import org.sakaiproject.entity.api.Reference; import org.sakaiproject.entity.api.ResourceProperties; -import org.sakaiproject.jsf.util.HelperAwareJsfTool; +import org.sakaiproject.jsf2.util.HelperAwareJsfTool; import org.sakaiproject.tool.api.ToolSession; import org.sakaiproject.tool.cover.SessionManager; diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/InitializableBean.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/InitializableBean.java index 164b467a..ae1721fc 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/InitializableBean.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/InitializableBean.java @@ -16,7 +16,7 @@ package org.sakaiproject.tool.gradebook.ui; -import org.sakaiproject.jsf.model.PhaseAware; +import org.sakaiproject.jsf2.model.PhaseAware; import lombok.extern.slf4j.Slf4j; diff --git a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/RosterBean.java b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/RosterBean.java index eee9d8a6..721482b2 100644 --- a/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/RosterBean.java +++ b/app/ui/src/java/org/sakaiproject/tool/gradebook/ui/RosterBean.java @@ -30,8 +30,9 @@ import java.util.Map.Entry; import java.util.Set; +import javax.el.MethodExpression; +import javax.el.ValueExpression; import javax.faces.application.Application; -import javax.faces.component.UIColumn; import javax.faces.component.UIParameter; import javax.faces.component.html.HtmlCommandLink; import javax.faces.component.html.HtmlOutputText; @@ -39,14 +40,17 @@ import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; +import javax.faces.event.MethodExpressionActionListener; +import org.apache.commons.lang.StringUtils; import org.apache.myfaces.component.html.ext.HtmlDataTable; +import org.apache.myfaces.custom.column.HtmlSimpleColumn; import org.apache.myfaces.custom.sortheader.HtmlCommandSortHeader; import org.sakaiproject.component.cover.ServerConfigurationService; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterCsv; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterPdf; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterXls; -import org.sakaiproject.jsf.spreadsheet.SpreadsheetUtil; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetDataFileWriterCsv; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetDataFileWriterPdf; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetDataFileWriterXlsx; +import org.sakaiproject.jsf2.spreadsheet.SpreadsheetUtil; import org.sakaiproject.section.api.coursemanagement.EnrollmentRecord; import org.sakaiproject.section.api.coursemanagement.User; import org.sakaiproject.service.gradebook.shared.GradebookService; @@ -60,6 +64,7 @@ import org.sakaiproject.tool.gradebook.jsf.AssignmentPointsConverter; import org.sakaiproject.tool.gradebook.jsf.CategoryPointsConverter; import org.sakaiproject.tool.gradebook.jsf.FacesUtil; +import org.sakaiproject.tool.gradebook.jsf.PointsConverter; import org.sakaiproject.util.ResourceLoader; import lombok.extern.slf4j.Slf4j; @@ -90,7 +95,7 @@ public class GradableObjectColumn implements Serializable { private Long assignmentId; private Boolean inactive = false; private Boolean hideInAllGradesTable = false; - private Boolean hiddenChanged = false; + private Boolean hiddenChanged = false; public GradableObjectColumn() { } @@ -162,6 +167,7 @@ public boolean hasHiddenChanged(){ private transient List studentRows; private transient Map gradeRecordMap; private transient Map categoryResultMap; + private transient HtmlPanelGroup dynamicDataTableGroup; public class StudentRow implements Serializable { private EnrollmentRecord enrollment; @@ -193,6 +199,13 @@ public Map getCategoryResults() { @Override protected void init() { + final ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); + final Map paramMap = context.getRequestParameterMap(); + final String catId = paramMap.get("gbForm:selectCategoryFilter"); + if (catId != null && !catId.equals(getSelectedCategoryUid())) { + this.setSelectedCategoryFilterValue(new Integer(catId)); + } + // set the roster filter super.setSelectedSectionFilterValue(getSelectedSectionFilterValue()); super.init(); @@ -519,6 +532,9 @@ public int compare(final Object o1, final Object o2) { this.studentRows.add(new StudentRow(enrollment)); } + // Setup datatable + populateDynamicDataTable(); + // set breadcrumb page for navigation // SessionManager.getCurrentToolSession().setAttribute("breadcrumbPage", "roster"); @@ -540,19 +556,153 @@ private Long getColumnHeaderAssignmentId(final GradableObject gradableObject) { } } - // The roster table uses assignments as columns, and therefore the component - // model needs to have those columns added dynamically, based on the current - // state of the gradebook. - // In JSF 1.1, dynamic data table columns are managed by binding the component - // tag to a bean property. + /** + * Return an empty list if the input list happens to be null, otherwise, return the input list + * @param theList + * @param + * @return + */ + private static List nullSafe( List theList ) { + return theList == null ? Collections.emptyList() : theList; + } - // It's not exactly intuitive, but the convention is for the bean to return - // null, so that JSF can create and manage the UIData component itself. - public HtmlDataTable getRosterDataTable() { - if (log.isDebugEnabled()) { - log.debug("getRosterDataTable"); + private ValueExpression createValueExpression(String valueExpression, Class valueType) { + FacesContext facesContext = FacesContext.getCurrentInstance(); + return facesContext.getApplication().getExpressionFactory().createValueExpression( + facesContext.getELContext(), valueExpression, valueType); + } + + private MethodExpression createMethodActionExpression(String valueExpression) { + FacesContext facesContext = FacesContext.getCurrentInstance(); + return facesContext.getApplication().getExpressionFactory().createMethodExpression( + facesContext.getELContext(), valueExpression, null, new Class[]{ActionEvent.class}); + } + + private MethodExpressionActionListener createActionListenerExpression(String valueExpression) { + return new MethodExpressionActionListener(createMethodActionExpression(valueExpression)); + } + + private void populateDynamicDataTable() { + HtmlDataTable dynamicDataTable = null; + if (dynamicDataTableGroup != null) { + if (dynamicDataTableGroup.getChildCount() > 0 && dynamicDataTableGroup.getChildren().get(0) instanceof HtmlDataTable) { + // Find existing table, since there might be sorting details set + dynamicDataTable = (HtmlDataTable) dynamicDataTableGroup.getChildren().get(0); + dynamicDataTable.getChildren().clear(); + } } - return null; + + if (dynamicDataTable == null) { + //Initialize table and set default sorting + dynamicDataTable = new HtmlDataTable(); + dynamicDataTable.setSortColumn(getSortColumn()); + dynamicDataTable.setSortAscending(isSortAscending()); + +// // Set sortable to false, otherwise JSF will automatically set its own command sort headers + dynamicDataTable.setSortable(false); + } + + // Create . + dynamicDataTable.setValueExpression("value", + createValueExpression("#{rosterBean.studentRows}", List.class)); + dynamicDataTable.setVar("row"); + + dynamicDataTable.getAttributes().put("colLock", getColLock()); + dynamicDataTable.getAttributes().put("initialHeight", getInitialHeight()); + dynamicDataTable.setRendererType("SpreadsheetUIRenderer"); + + // set static columns + /* + + + + + + + + + + + + + */ + + HtmlSimpleColumn studNameCol = new HtmlSimpleColumn(); + dynamicDataTable.getChildren().add(studNameCol); + HtmlCommandSortHeader studNameHeader = new HtmlCommandSortHeader(); + studNameHeader.setId("studName_sorthdr"); + studNameHeader.setRendererType("org.apache.myfaces.SortHeader"); + studNameHeader.setValue(getLocalizedString("roster_student_name")); + studNameHeader.setColumnName("studentSortName"); + studNameHeader.setImmediate(true); + studNameHeader.setArrow(true); + studNameHeader.addActionListener(createActionListenerExpression("#{rosterBean.sort}")); + studNameCol.setId("studentNameData"); + studNameCol.setHeader(studNameHeader); + studNameCol.setSortable(true); + + HtmlCommandLink link = new HtmlCommandLink(); + link.setValueExpression("value", + createValueExpression("#{row.sortName}", String.class)); + link.setActionExpression(createMethodActionExpression("instructorView")); + link.getAttributes().put("studentUid", createValueExpression("#{row.studentUid}", String.class)); + link.getAttributes().put("returnToPage", "roster"); + + studNameCol.getChildren().add(link); + + /* + + + + + + + + + */ + + HtmlSimpleColumn studIdCol = new HtmlSimpleColumn(); + dynamicDataTable.getChildren().add(studIdCol); + HtmlCommandSortHeader studIdHeader = new HtmlCommandSortHeader(); + studIdHeader.setId("studId_sorthdr"); + studIdHeader.setRendererType("org.apache.myfaces.SortHeader"); + studIdHeader.setValue(getLocalizedString("roster_student_id")); + studIdHeader.setColumnName("studentDisplayId"); + studIdHeader.setImmediate(true); + studIdHeader.setArrow(true); + studIdHeader.addActionListener(createActionListenerExpression("#{rosterBean.sort}")); + studIdCol.setId("studentIdData"); + studIdCol.setHeader(studIdHeader); + studIdCol.setSortable(true); + + HtmlOutputText output = new HtmlOutputText(); + output.setValueExpression("value", + createValueExpression("#{row.displayId}", String.class)); + + studIdCol.getChildren().add(output); + + //Do dynamic column stuff + setRosterDataTable(dynamicDataTable); + + // Add the datatable to . + if (dynamicDataTableGroup != null) { + dynamicDataTableGroup.getChildren().clear(); + dynamicDataTableGroup.getChildren().add(dynamicDataTable); + } + + } + + public HtmlPanelGroup getDynamicDataTableGroup() { + // This will be called once in the first RESTORE VIEW phase. + if (dynamicDataTableGroup == null) { + dynamicDataTableGroup = new HtmlPanelGroup(); + init(); + } + return dynamicDataTableGroup; + } + + public void setDynamicDataTableGroup(HtmlPanelGroup dynamicDataTableGroup) { + this.dynamicDataTableGroup = dynamicDataTableGroup; } public void setRosterDataTable(final HtmlDataTable rosterDataTable) { @@ -567,30 +717,11 @@ public void setRosterDataTable(final HtmlDataTable rosterDataTable) { "HtmlDataTable rosterDataTable == null!"); } - //check if columns of changed due to categories - final ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); - final Map paramMap = context.getRequestParameterMap(); - final String catId = (String) paramMap.get("gbForm:selectCategoryFilter"); - //due to this set method getting called before all others, including the setSelectCategoryFilterValue, - // we have to manually set the value, then call init to get the new gradableObjectColumns array - if(catId != null && !catId.equals(getSelectedCategoryUid())) { - this.setSelectedCategoryFilterValue(new Integer(catId)); - init(); - //now destroy all of the columns to be readded - rosterDataTable.getChildren().removeAll( rosterDataTable.getChildren().subList(2, rosterDataTable.getChildren().size())); - } - - // Set the columnClasses on the data table - final StringBuilder colClasses = new StringBuilder("left,left,"); - for(final Iterator iter = this.gradableObjectColumns.iterator(); iter.hasNext();) { - iter.next(); - colClasses.append("center"); - if(iter.hasNext()) { - colClasses.append(","); - } - } - rosterDataTable.setColumnClasses(colClasses.toString()); + List colClasses = new ArrayList<>(); + nullSafe(this.gradableObjectColumns).forEach(col -> colClasses.add("center")); + + rosterDataTable.setColumnClasses("left,left," + StringUtils.join(colClasses, ",")); if (rosterDataTable.findComponent(ASSIGNMENT_COLUMN_PREFIX + "0") == null) { final Application app = FacesContext.getCurrentInstance().getApplication(); @@ -598,11 +729,12 @@ public void setRosterDataTable(final HtmlDataTable rosterDataTable) { // Add columns for each assignment. Be sure to create unique IDs // for all child components. int colpos = 0; - for (final Iterator iter = this.gradableObjectColumns.iterator(); iter.hasNext(); colpos++) { - final GradableObjectColumn columnData = (GradableObjectColumn)iter.next(); + for (final Iterator iter = nullSafe(this.gradableObjectColumns).iterator(); iter.hasNext(); colpos++) { + final GradableObjectColumn columnData = iter.next(); - final UIColumn col = new UIColumn(); + final HtmlSimpleColumn col = new HtmlSimpleColumn(); col.setId(ASSIGNMENT_COLUMN_PREFIX + colpos); + col.setSortable(true); if(columnData.getHideInAllGradesTable()){ col.setRendered(false); } @@ -656,11 +788,14 @@ public void setRosterDataTable(final HtmlDataTable rosterDataTable) { //make a panel group to add link final HtmlPanelGroup pg = new HtmlPanelGroup(); - pg.getChildren().add(sortHeader); pg.getChildren().add(br); pg.getChildren().add(detailsLink); - col.setHeader(pg); + //The data table is much happier when the sort stuff is the only thing in the header + col.setHeader(sortHeader); + + //Put the "extra" stuff in a new facet, which still gets rendered in the header via the SpreadsheetUIRenderer + col.getFacets().put("extra_header", pg); } else { col.setHeader(sortHeader); } @@ -693,10 +828,11 @@ public void setRosterDataTable(final HtmlDataTable rosterDataTable) { }else{ //Unassigned Category final HtmlOutputText headerText = new HtmlOutputText(); - headerText.setId(ASSIGNMENT_COLUMN_PREFIX + "hrd_" + colpos); + headerText.setId(ASSIGNMENT_COLUMN_PREFIX + "hdr_" + colpos); headerText.setValue(columnData.getName()); col.setHeader(headerText); + col.setSortable(false); } } @@ -704,12 +840,16 @@ public void setRosterDataTable(final HtmlDataTable rosterDataTable) { contents.setEscape(false); contents.setId(ASSIGNMENT_COLUMN_PREFIX + "cell_" + colpos); if(!columnData.getCategoryColumn()){ + // Converters no longer run on null values, so we need a special placeholder so we can let the converter do its thing + String beanValue = "row.scores[rosterBean.gradableObjectColumns[" + colpos + "].id]"; contents.setValueBinding("value", - app.createValueBinding("#{row.scores[rosterBean.gradableObjectColumns[" + colpos + "].id]}")); + app.createValueBinding("#{empty " + beanValue + " ? '" + PointsConverter.NULL_PLACEHOLDER + "' : " + beanValue + "}")); contents.setConverter(new AssignmentPointsConverter()); } else { + // Converters no longer run on null values, so we need a special placeholder so we can let the converter do its thing + String beanValue = "row.categoryResults[rosterBean.gradableObjectColumns[" + colpos + "].id]"; contents.setValueBinding("value", - app.createValueBinding("#{row.categoryResults[rosterBean.gradableObjectColumns[" + colpos + "].id]}")); + app.createValueBinding("#{empty " + beanValue + " ? '" + PointsConverter.NULL_PLACEHOLDER + "' : " + beanValue + "}")); contents.setConverter(new CategoryPointsConverter()); } @@ -738,6 +878,11 @@ public List getStudentRows() { return this.studentRows; } + public String getInitialHeight() { + int height = nullSafe(getStudentRows()).size() * 32; + return height + "px"; + } + public String getColLock() { if (isUserAbleToGradeAll() || getSelectedCategoryUid() != null) { return "3"; @@ -829,7 +974,7 @@ public void exportXlsNoCourseGrade(final ActionEvent event){ getGradebookBean().postEvent("gradebook.downloadRoster", "/gradebook/" + getGradebookId() + "/" + getAuthzLevel(), false); SpreadsheetUtil.downloadSpreadsheetData(getSpreadsheetData(false, false), getDownloadFileName(getLocalizedString("export_gradebook_prefix")), - new SpreadsheetDataFileWriterXls()); + new SpreadsheetDataFileWriterXlsx()); } public void exportCsvNoCourseGrade(final ActionEvent event){ @@ -866,11 +1011,11 @@ public void exportExcel(final ActionEvent event){ if (isUserAbleToGradeAll()) { SpreadsheetUtil.downloadSpreadsheetData(getSpreadsheetData(true, false), getDownloadFileName(getLocalizedString("export_gradebook_prefix")), - new SpreadsheetDataFileWriterXls()); + new SpreadsheetDataFileWriterXlsx()); } else { SpreadsheetUtil.downloadSpreadsheetData(getSpreadsheetData(false, false), getDownloadFileName(getLocalizedString("export_gradebook_prefix")), - new SpreadsheetDataFileWriterXls()); + new SpreadsheetDataFileWriterXlsx()); } } diff --git a/app/ui/src/webapp/WEB-INF/faces-beans.xml b/app/ui/src/webapp/WEB-INF/faces-beans.xml index 9b0b2fce..43185d3f 100644 --- a/app/ui/src/webapp/WEB-INF/faces-beans.xml +++ b/app/ui/src/webapp/WEB-INF/faces-beans.xml @@ -1,6 +1,9 @@ - - + Gradebook context gradebookBean diff --git a/app/ui/src/webapp/WEB-INF/faces-gb-jsf.xml b/app/ui/src/webapp/WEB-INF/faces-gb-jsf.xml index a84552c7..bba83f6e 100644 --- a/app/ui/src/webapp/WEB-INF/faces-gb-jsf.xml +++ b/app/ui/src/webapp/WEB-INF/faces-gb-jsf.xml @@ -1,6 +1,9 @@ - - + org.sakaiproject.tool.gradebook.jsf.iterator org.sakaiproject.tool.gradebook.jsf.iterator.IteratorComponent diff --git a/app/ui/src/webapp/WEB-INF/faces-navigation.xml b/app/ui/src/webapp/WEB-INF/faces-navigation.xml index 1d155134..4d4529ce 100644 --- a/app/ui/src/webapp/WEB-INF/faces-navigation.xml +++ b/app/ui/src/webapp/WEB-INF/faces-navigation.xml @@ -1,6 +1,9 @@ - - + * diff --git a/app/ui/src/webapp/WEB-INF/tld/gb-jsf.tld b/app/ui/src/webapp/WEB-INF/tld/gb-jsf.tld index 5d518d76..02d28258 100644 --- a/app/ui/src/webapp/WEB-INF/tld/gb-jsf.tld +++ b/app/ui/src/webapp/WEB-INF/tld/gb-jsf.tld @@ -136,71 +136,6 @@ date|time|both - - - - spreadsheetUI - org.sakaiproject.tool.gradebook.jsf.spreadsheetUI.SpreadsheetUITag - SpreadsheetUI - JSP - Spreadsheet for new UI with locking rows and cols - - value - false - false - - - The current value of this component. - - - - var - false - false - - - Name of a request-scope attribute under which the model data for the - row selected by the current value of the "rowIndex" property (i.e. - also the current value of the "rowData" property) will be exposed. - - - - colLock - false - false - - - rowLock - false - false - - - rendered - false - false - - - binding - false - false - - - sortColumn - false - false - - - sortAscending - false - false - - - initialHeight - false - true - Initial Height (in px) of the spreasheetUI scrolling viewport - - gradebookItemTable diff --git a/app/ui/src/webapp/addAssignment.jsp b/app/ui/src/webapp/addAssignment.jsp index 1bf61990..a11638b1 100644 --- a/app/ui/src/webapp/addAssignment.jsp +++ b/app/ui/src/webapp/addAssignment.jsp @@ -7,7 +7,11 @@ var MAX_NEW_ITEMS = ; + + + +
@@ -50,22 +54,28 @@ <%-- Need to attach listeners, must be here --%> diff --git a/app/ui/src/webapp/assignmentDetails.jsp b/app/ui/src/webapp/assignmentDetails.jsp index f78984a1..3e81f3b7 100644 --- a/app/ui/src/webapp/assignmentDetails.jsp +++ b/app/ui/src/webapp/assignmentDetails.jsp @@ -79,7 +79,7 @@ - + diff --git a/app/ui/src/webapp/css/gradebook.css b/app/ui/src/webapp/css/gradebook.css index 4e7fc8bb..31895e55 100644 --- a/app/ui/src/webapp/css/gradebook.css +++ b/app/ui/src/webapp/css/gradebook.css @@ -243,3 +243,19 @@ td.gbMessageAboveNumber {vertical-align:top; text-align:right; padding-right:2em vertical-align: middle; visibility: hidden; } + +.addPaddingContainer * { + padding-right: 4px; +} + +.addPaddingLeft { + padding-left: 4px; +} + +.addPaddingRight { + padding-right: 4px; +} + +.addRadioPadding tbody tr td label { + padding-left:4px; +} \ No newline at end of file diff --git a/app/ui/src/webapp/editAssignment.jsp b/app/ui/src/webapp/editAssignment.jsp index e1227f3d..5b82239f 100644 --- a/app/ui/src/webapp/editAssignment.jsp +++ b/app/ui/src/webapp/editAssignment.jsp @@ -1,4 +1,7 @@ + + +
diff --git a/app/ui/src/webapp/gradebookSetup.jsp b/app/ui/src/webapp/gradebookSetup.jsp index 063a5a7a..458ed7bd 100644 --- a/app/ui/src/webapp/gradebookSetup.jsp +++ b/app/ui/src/webapp/gradebookSetup.jsp @@ -43,14 +43,14 @@
+ valueChangeListener="#{gradebookSetupBean.processGradeEntryMethodChange}" onclick="this.form.submit();" styleClass="addRadioPadding"> + valueChangeListener="#{gradebookSetupBean.processGradeEntryMethodChange}" onclick="this.form.submit();" styleClass="addRadioPadding"> @@ -93,8 +93,8 @@

- - + +
diff --git a/app/ui/src/webapp/hideShowColumns.jsp b/app/ui/src/webapp/hideShowColumns.jsp index 7d35178a..1c255d4c 100644 --- a/app/ui/src/webapp/hideShowColumns.jsp +++ b/app/ui/src/webapp/hideShowColumns.jsp @@ -1,6 +1,6 @@ <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> -<%@ taglib uri="http://sakaiproject.org/jsf/sakai" prefix="sakai" %> +<%@ taglib uri="http://sakaiproject.org/jsf2/sakai" prefix="sakai" %> <% @@ -26,17 +26,17 @@
- + - + - + - + diff --git a/app/ui/src/webapp/inc/appMenu.jspf b/app/ui/src/webapp/inc/appMenu.jspf index 8f555d58..d682ae4b 100644 --- a/app/ui/src/webapp/inc/appMenu.jspf +++ b/app/ui/src/webapp/inc/appMenu.jspf @@ -8,48 +8,48 @@ - + <%-- Roster menu --%> - + <%-- Course Grades menu --%> - + <%-- Gradebook Setup menu --%> - + <%-- Permission Settings --%> - + <%-- Course Grade Options menu --%> - + <%-- Import Grades menu --%> - + diff --git a/app/ui/src/webapp/inc/assignmentEditing.jspf b/app/ui/src/webapp/inc/assignmentEditing.jspf index 1728c534..cf6b1146 100644 --- a/app/ui/src/webapp/inc/assignmentEditing.jspf +++ b/app/ui/src/webapp/inc/assignmentEditing.jspf @@ -61,13 +61,13 @@ - + - + @@ -108,4 +108,18 @@ diff --git a/app/ui/src/webapp/inc/bulkNewItems.jspf b/app/ui/src/webapp/inc/bulkNewItems.jspf index 327a6bc8..3b2fd23e 100644 --- a/app/ui/src/webapp/inc/bulkNewItems.jspf +++ b/app/ui/src/webapp/inc/bulkNewItems.jspf @@ -110,8 +110,7 @@ - + @@ -164,5 +163,5 @@ assignmentReleased(('gbForm:bulkNewAssignmentsTable:' + i), false); categorySelected(('gbForm:bulkNewAssignmentsTable:' + i), ''); } - + diff --git a/app/ui/src/webapp/inc/categoryEdit.jspf b/app/ui/src/webapp/inc/categoryEdit.jspf index cf7ca7f3..343f2007 100644 --- a/app/ui/src/webapp/inc/categoryEdit.jspf +++ b/app/ui/src/webapp/inc/categoryEdit.jspf @@ -4,7 +4,7 @@

+ valueChangeListener="#{gradebookSetupBean.processCategorySettingChange}" onclick="reEnableCategoryDropInputs();this.form.submit();" styleClass="addRadioPadding"> @@ -13,15 +13,15 @@ - + - + - +
diff --git a/app/ui/src/webapp/inc/gradingEventLogs.jspf b/app/ui/src/webapp/inc/gradingEventLogs.jspf index ff17e635..364d7dba 100644 --- a/app/ui/src/webapp/inc/gradingEventLogs.jspf +++ b/app/ui/src/webapp/inc/gradingEventLogs.jspf @@ -6,7 +6,7 @@ closeIconUrl="dhtmlpopup/dhtmlPopClose.gif" styleClass="dhtmlPopup" titleBarClass="dhtmlPopupTitleBar" closeClass="dhtmlPopupClose" dataRowClass="dhtmlPopupDataRow"> - + diff --git a/app/ui/src/webapp/inc/gradingEventLogsInstView.jspf b/app/ui/src/webapp/inc/gradingEventLogsInstView.jspf index 4224a3c7..7864d14c 100644 --- a/app/ui/src/webapp/inc/gradingEventLogsInstView.jspf +++ b/app/ui/src/webapp/inc/gradingEventLogsInstView.jspf @@ -6,7 +6,7 @@ closeIconUrl="dhtmlpopup/dhtmlPopClose.gif" styleClass="dhtmlPopup" titleBarClass="dhtmlPopupTitleBar" closeClass="dhtmlPopupClose" dataRowClass="dhtmlPopupDataRow"> - + diff --git a/app/ui/src/webapp/instructorView.jsp b/app/ui/src/webapp/instructorView.jsp index ed4c2b21..eef39a63 100644 --- a/app/ui/src/webapp/instructorView.jsp +++ b/app/ui/src/webapp/instructorView.jsp @@ -41,6 +41,7 @@