diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java index 5ed66765a..b1baf2481 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java @@ -130,10 +130,12 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet { data.put("siteInfo", UrlBuilder.getUrl("/editForm", "controller", "ApplicationBean")); } + //TODO: Add specific permissions for page management if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.MANAGE_MENUS.ACTIONS)) { data.put("menuManagement", UrlBuilder.getUrl("/individual", "uri", "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#DefaultMenu", "switchToDisplayModel", "true")); + data.put("pageManagement", UrlBuilder.getUrl("/pageList")); } if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.SEE_STARTUP_STATUS.ACTIONS)) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java new file mode 100644 index 000000000..9496c2aa0 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java @@ -0,0 +1,310 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeIntervalValidationVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeWithPrecisionVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils; + + +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.vocabulary.OWL; +import com.hp.hpl.jena.vocabulary.RDF; +import com.hp.hpl.jena.vocabulary.RDFS; +import com.hp.hpl.jena.vocabulary.XSD; +import com.hp.hpl.jena.ontology.OntModel; +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.AntiXssValidation; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditN3GeneratorVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.ChildVClassesOptions; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.SelectListGeneratorVTwo; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; +import edu.cornell.mannlib.vitro.webapp.utils.menuManagement.MenuManagementDataUtils; +import edu.cornell.mannlib.vitro.webapp.web.MiscWebUtils; +import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; + +/** + * Generates the form for adding and editing a page in the display model. + * + */ +public class ManagePageGenerator extends BaseEditConfigurationGenerator implements EditConfigurationGenerator{ + + private String template = "pageManagement.ftl"; + + @Override + public EditConfigurationVTwo getEditConfiguration( VitroRequest vreq, HttpSession session) { + EditConfigurationVTwo conf = new EditConfigurationVTwo(); + conf.setTemplate(template); + + //get editkey and url of form + initBasics(conf, vreq); + initPropertyParameters(vreq, session, conf); + //if object uri exists, sets object URI + initObjectPropForm(conf, vreq); + //Depending on whether this is a new individual to be created or editing + //an existing one, the var names will differ + setVarNames(conf); + //Set N3 required and optional + setN3Required(conf); + setN3Optional(conf); + + //Designate new resources if any exist + setNewResources(conf); + + //Add sparql queries + setSparqlQueries(conf); + //Set the fields + setFields(conf); + + //Adding additional data, specifically edit mode + addFormSpecificData(conf, vreq); + //Prepare + prepare(vreq, conf); + + return conf ; + } + + private void setN3Optional(EditConfigurationVTwo conf) { + //body template is not required, and a given page may or may not be a menu item, but should linked to menu if menu item + conf.setN3Optional(Arrays.asList(prefixes + pageBodyTemplateN3, + prefixes + menuItemN3 + menuN3)); + } + + private void setN3Required(EditConfigurationVTwo conf) { + conf.setN3Required(Arrays.asList(prefixes + pageN3)); + + } + + private void setFields(EditConfigurationVTwo conf) { + //Required fields for page include: Page title, page URL Mapping + //Data getter fields will be dealt with in preprocessor/util classes + //Optional fields for page include body template + + //required, therefore nonempty + FieldVTwo titleField = new FieldVTwo().setName("pageTitle"). + setValidators(Arrays.asList("nonempty")); + conf.addField(titleField); + + FieldVTwo urlField = new FieldVTwo().setName("urlMapping").setValidators(Arrays.asList("nonempty")); + conf.addField(urlField); + + //optional: body template + FieldVTwo bodyTemplateField = new FieldVTwo().setName("bodyTemplate"); + conf.addField(bodyTemplateField); + + + //For menu item, these are optional b/c they depend on menu item + FieldVTwo menuItemLinkTextField = new FieldVTwo().setName("linkText"); + conf.addField(menuItemLinkTextField); + + FieldVTwo menuItemPositionField = new FieldVTwo().setName("menuPosition"); + conf.addField(menuItemPositionField); + } + + + + private void setVarNames(EditConfigurationVTwo conf) { + if(conf.getSubjectUri() != null) { + conf.setVarNameForSubject("page"); + conf.setVarNameForPredicate("predicate"); + } else { + conf.setVarNameForSubject("subjectNotUsed"); + conf.setVarNameForPredicate("predicateNotUsed"); + } + + } + + //overriding + @Override + void initPropertyParameters(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration) { + + String subjectUri = EditConfigurationUtils.getSubjectUri(vreq); + String predicateUri = EditConfigurationUtils.getPredicateUri(vreq); + + //For the case of a new page + if(subjectUri == null) { + //Once added, return to pageList + editConfiguration.setUrlToReturnTo("/pageList"); + editConfiguration.setEntityToReturnTo("?page"); + editConfiguration.setPredicateUri(predicateUri); + + } else { + //For the case of an existing page + //Page title pageTitle or page hasDataGetter dataGetter + editConfiguration.setUrlPatternToReturnTo("/individual"); + editConfiguration.setEntityToReturnTo(subjectUri); + } + editConfiguration.setSubjectUri(subjectUri); + editConfiguration.setPredicateUri(predicateUri); + } + + + //also overriding + @Override + void prepare(VitroRequest vreq, EditConfigurationVTwo editConfig) { + //setup the model selectors for query, write and display models on editConfig + //Double-check if this will even work with over-written model in the case of display model? + setupModelSelectorsFromVitroRequest(vreq, editConfig); + OntModel queryModel = (OntModel)vreq.getAttribute("jenaOntModel"); + + if (editConfig.getSubjectUri() != null) { + editConfig.prepareForObjPropUpdate(queryModel); + } + else{ + //if no subject uri, this is creating a new page + editConfig.prepareForNonUpdate(queryModel); + } + } + + + //In the case where this is a new page, need to ensure page gets a new + private void setNewResources(EditConfigurationVTwo conf) { + //null makes default namespace be triggered + conf.addNewResource("page", DEFAULT_NS_FOR_NEW_RESOURCE); + conf.addNewResource("menuItem", DEFAULT_NS_FOR_NEW_RESOURCE); + + } + + //This is for various items + private void setSparqlQueries(EditConfigurationVTwo editConfiguration) { + //Sparql queries defining retrieval of literals etc. + editConfiguration.setSparqlForAdditionalLiteralsInScope(new HashMap()); + + Map urisInScope = new HashMap(); + editConfiguration.setSparqlForAdditionalUrisInScope(urisInScope); + + editConfiguration.setSparqlForExistingLiterals(generateSparqlForExistingLiterals()); + editConfiguration.setSparqlForExistingUris(generateSparqlForExistingUris()); + } + + + //Get page uri for object + private HashMap generateSparqlForExistingUris() { + HashMap map = new HashMap(); + return map; + } + + private HashMap generateSparqlForExistingLiterals() { + HashMap map = new HashMap(); + return map; + } + + + + + + //Form specific data + //In this case, need to get all the different data getter TYPES and labels + //Also need to pass back the map for the options presented to the user + //which is different from the above + //Maybe mapping where it does exist? I.e. sparql query from drop-down IS sparql query data getter + //Class group is hard-coded to class group but otherwise it can be changed + //Based on circumstances - specifically internal class data getter + //Need to get the hash for data getter to label TO the form so + //that can then be read by javascript? + //Also pass back current menu position? + public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) { + HashMap formSpecificData = new HashMap(); + //Get options for user: label to data getter type + //For every type of page, will need some "always required" data + addRequiredPageData(vreq, formSpecificData); + //For a new page, we will need to add the following data + addNewPageData(vreq, formSpecificData); + + editConfiguration.setFormSpecificData(formSpecificData); + } + + private String getTemplate(EditConfigurationVTwo editConfiguration) { + String returnTemplate = "default"; + if(editConfiguration.getSubjectUri() != null) { + //Then template is EXISTING template + //TODO: Get existing template value for page + } + return returnTemplate; + + } + + private void addRequiredPageData(VitroRequest vreq, Map data) { + MenuManagementDataUtils.includeRequiredSystemData(vreq.getSession().getServletContext(), data); + } + + private void addNewPageData(VitroRequest vreq, Map data) { + data.put("title", "Add Menu Item"); + data.put("menuAction", "Add"); + //Generate empty values for fields + data.put("menuItem", ""); + data.put("menuName", ""); + data.put("prettyUrl", ""); + data.put("associatedPage", ""); + data.put("associatedPageURI", ""); + data.put("classGroup", new ArrayList()); + //not a page already assigned a class group + data.put("isClassGroupPage", false); + data.put("includeAllClasses", false); + data.put("classGroups", DataGetterUtils.getClassGroups(vreq.getSession().getServletContext())); + data.put("selectedTemplateType", "default"); + //defaults to regular class group page + } + + //N3 strings + + //For new or existing page + final static String prefixes = "@prefix display: . \n" + + "@prefix rdfs: . \n"; + + final static String pageN3 = "?page a display:Page ; \n" + + "display:title ?pageTitle ;\n" + + "display:urlMapping ?urlMapping ."; + + //"display:hasDataGetter ?pageDataGetter ."; + + //A page may also require a body template so we can get that here as well + //That would be optional + + final static String pageBodyTemplateN3 = "?page display:requiresBodyTemplate ?bodyTemplate ."; + + //Menu position is added dynamically at end by default and can be changed on reordering page + final static String menuItemN3 = "?menuItem a display:NavigationElement ; \n" + + "display:menuPosition ?menuPosition; \n" + + "display:linkText ?menuLinkText; \n" + + "display:toPage ?page ."; + + //We define n3 here from default menu item up through page, but data getters are added dyamically + //so will be dealt with in the preprocessor + + final static String menuN3 = "display:DefaultMenu display:hasElement ?menuItem ."; + + //These are public static methods that can be used in the preprocessor + public final static String getDataGetterN3(int numberDataGetter) { + return prefixes + "?page display:hasDataGetter ?dataGetter" + numberDataGetter + "."; + } + + +} diff --git a/webapp/web/css/menupage/pageList.css b/webapp/web/css/menupage/pageList.css new file mode 100644 index 000000000..7b124d062 --- /dev/null +++ b/webapp/web/css/menupage/pageList.css @@ -0,0 +1,5 @@ +.menuFlag { + width:67px; + height:18px; + background: url("../../images/checkMark.png") no-repeat left center; +} \ No newline at end of file diff --git a/webapp/web/css/menupage/pageManagement.css b/webapp/web/css/menupage/pageManagement.css new file mode 100644 index 000000000..7052c6d05 --- /dev/null +++ b/webapp/web/css/menupage/pageManagement.css @@ -0,0 +1,19 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +.pageContent {"background-color":"","padding-left":"","padding-top":"","border-width":"","border-style":"","border-color":"#ccc"} + +.pageContentContainer {background-color:#f5f5f5;border-color:#ccc;border-width:1px;border-style:solid;margin-bottom:4px;} + +.pageContentTypeLabel {padding-left:6px;} + +.pageContentWrapper {background-color:#f9f9f9;padding-left:6px;padding-top:2px;border-top-width:1px;border-style:solid;border-color:#ccc;} + +.pageContentExpand {float:right;padding-right:5px;} + +.arrow { + width:13px; height:9px; display:block; +} +.expandArrow {background-image:url(../../images/individual/arrow-down.gif);} +.collapseArrow {background-image:url(../../images/individual/arrow-up.gif);} + +.deleteButton{margin-bottom:5px;} \ No newline at end of file diff --git a/webapp/web/images/checkMark.png b/webapp/web/images/checkMark.png new file mode 100644 index 000000000..197767db2 Binary files /dev/null and b/webapp/web/images/checkMark.png differ diff --git a/webapp/web/images/individual/arrow-up.gif b/webapp/web/images/individual/arrow-up.gif new file mode 100644 index 000000000..57ca5bc01 Binary files /dev/null and b/webapp/web/images/individual/arrow-up.gif differ diff --git a/webapp/web/js/menupage/pageManagementUtils.js b/webapp/web/js/menupage/pageManagementUtils.js new file mode 100644 index 000000000..ea6ac5b55 --- /dev/null +++ b/webapp/web/js/menupage/pageManagementUtils.js @@ -0,0 +1,295 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +var pageManagementUtils = { + + // on initial page setup + onLoad:function(){ + if (this.disableFormInUnsupportedBrowsers()) { + return; + } + this.mixIn(); + this.initObjects(); + this.bindEventListeners(); + this.initDisplay(); + + }, + disableFormInUnsupportedBrowsers: function() { + var disableWrapper = $('#ie67DisableWrapper'); + + // Check for unsupported browsers only if the element exists on the page + if (disableWrapper.length) { + if (vitro.browserUtils.isIELessThan8()) { + disableWrapper.show(); + $('.noIE67').hide(); + return true; + } + } + return false; + }, + + mixIn: function() { + // Mix in the custom form utility methods + $.extend(this, vitro.customFormUtils); + // Get the custom form data from the page + $.extend(this, customFormData); + }, + initObjects:function(){ + this.counter = 0; + this.contentTypeSelect = $("#typeSelect"); + //list of options + this.contentTypeSelectOptions = $('select#typeSelect option'); + this.classGroupSection = $("section#classGroup"); + this.nonClassGroupSection = $("section#nonClassGroup"); + }, + initDisplay: function(){ + //right side components + this.contentTypeSelectOptions.eq(0).attr('selected', 'selected'); + $('select#selectClassGroup option').eq(0).attr('selected', 'selected'); + + //Why would you want to hide this? This hides everything + // $("section#pageDetails").hide(); + $("section#headerBar").hide(); + this.classGroupSection.hide(); + this.nonClassGroupSection.hide(); + $("section#classesInSelectedGroup").addClass('hidden'); + $("input#moreContent").hide(); + //left side components + $("input.default-template").attr('checked',true); + $("input#menuCheckbox").attr('checked',false); + $("section#menu").hide(); + + }, + bindEventListeners:function(){ + $("input.default-template").click( function() { + $("section#custom-template").addClass('hidden'); + + }); + + $("input.custom-template").click( function() { + $("section#custom-template").removeClass('hidden'); + }); + + $("input#menuCheckbox").click( function() { + if ( $("section#menu").is(':hidden') ) { + $("section#menu").show(); + } + else { + $("section#menu").hide(); + } + }); + + $("input#submit").click( function() { + $("section#pageDetails").show(); + }); + + //Collapses the current content and creates a new section of content + //Resets the content to be cloned to default settings + $("input#moreContent").click( function() { + var selectedType = pageManagementUtils.contentTypeSelect.val(); + var selectedTypeText = $("#typeSelect :select").text(); + //Not sure why selected group here? This won't always be true for more content + //var selectedGroup = $('select#selectClassGroup').val(); + + //Aren't these already hidden? + //Hide both sections + $("section#classGroup").hide(); + $("section#nonClassGroup").hide(); + + //Reset class group + pageManagementUtils.resetClassGroupSection(); + pageManagementUtils.contentTyeSelectOptions.eq(0).attr('selected', 'selected'); + $("input#moreContent").hide(); + if ( $("div#leftSide").css("height") != undefined ) { + $("div#leftSide").css("height",""); + if ( $("div#leftSide").height() < $("div#rightSide").height() ) { + $("div#leftSide").css("height",$("div#rightSide").height() + "px"); + } + } + $("section#headerBar").hide(); + $("section#headerBar").text(""); + //pageManagementUtils.cloneContentArea(selectedType,selectedGroup); + pageManagementUtils.cloneContentArea(selectedType, selectedTypeText); + pageManagementUtils.contentTypeSelect.focus(); + }); + + $("select#selectClassGroup").change( function() { + if ( $("select#selectClassGroup").val() == "" ) { + $("section#classesInSelectedGroup").addClass('hidden'); + $("div#leftSide").css("height",""); + $("input#moreContent").hide(); + + } + else { + $("section#classesInSelectedGroup").removeClass('hidden'); + $("input#moreContent").show(); + if ( $("div#leftSide").height() < $("div#rightSide").height() ) { + $("div#leftSide").css("height",$("div#rightSide").height() + "px"); + } + } + }); + + $("select#typeSelect").change( function() { + $('input#variable').val(""); + $('textarea#textArea').val(""); + if ( $("#typeSelect").val() == "Browse Class Group" ) { + $("section#classGroup").show(); + $("section#nonClassGroup").hide(); + $("input#moreContent").hide(); + $("section#headerBar").text("Browse Class Group - "); + $("section#headerBar").show(); + } + if ( $("#typeSelect").val() == "Fixed HTML" || $("#typeSelect").val() == "SPARQL Query Results" ) { + $("section#classGroup").hide(); + if ( $("#typeSelect").val() == "Fixed HTML" ) { + $('span#taSpan').text("Enter fixed HTML here"); + $("section#headerBar").text("Fixed HTML - "); + } + else { + $('span#taSpan').text("Enter SPARQL query here"); + $("section#headerBar").text("SPARQL Query Results - "); + } + $("section#nonClassGroup").show(); + $("section#headerBar").show(); + $('select#selectClassGroup option').eq(0).attr('selected', 'selected'); + $("section#classesInSelectedGroup").addClass('hidden'); + $("input#moreContent").show(); + } + if ( $("#typeSelect").val() == "" ) { + $("section#classGroup").hide(); + $("section#nonClassGroup").hide(); + $("input#moreContent").hide(); + $('select#selectClassGroup option').eq(0).attr('selected', 'selected'); + $("section#classesInSelectedGroup").addClass('hidden'); + $("section#headerBar").hide(); + $("section#headerBar").text(""); + } + pageManagementUtils.adjustSaveButtonHeight(); + }); + + }, + //Clone content area + cloneContentArea: function(contentType, contentTypeLabel) { + var ctr = pageManagementUtils.counter; + var counter = pageManagementUtils.counter; + var varOrClas; + + + if ( contentType == "fixedHTML" || contentType == "sparqlResults" ) { + + var $newContentObj = $('section#nonClassGroup').clone(); + $newContentObj.addClass("pageContent"); + varOrClass = $newContentObj.find('input').val(); + $newContentObj.show(); + //Save content type + $newContentObj.attr("contentType", contentType); + $newContentObj.attr("id", contentType + counter); + $newContentObj.find('input#variable').attr("id","variable" + counter); + $newContentObj.find('textarea#textArea').attr("id","textArea" + counter); + $newContentObj.find('input#variable').attr("name","variable" + counter); + $newContentObj.find('textarea#textArea').attr("name","textArea" + counter); + $newContentObj.find('label#variableLabel').attr("id","variableLabel" + counter); + $newContentObj.find('label#taLabel').attr("id","taLabel" + counter); + // There's a jquery bug when cloning textareas: the value doesn't + // get cloned. So + // copy the value "manually." + var taValue = $('textarea#textArea').val(); + $newContentObj.find('textarea').val(taValue); + } + else if ( contentType == "browseClassGroup" ) { + + var $newContentObj = $('section#classGroup').clone(); + + $newContentObj.addClass("pageContent"); + $newContentObj.show(); + $newContentObj.attr("contentType", contentType); + $newContentObj.attr("id", "classGroup" + counter); + $newContentObj.find('section#selectContentType').attr("id", "selectContentType" + counter); + $newContentObj.find('select#selectClassGroup').val(groupValue); + $newContentObj.find('select#selectClassGroup').attr("id","selectClassGroup" + counter); + $newContentObj.find('select#selectClassGroup' + counter).attr("name","selectClassGroup" + counter); + $newContentObj.find('section#classesInSelectedGroup').attr("id","classesInSelectedGroup" + counter); + $newContentObj.find('section#classesInSelectedGroup' + counter).removeClass('hidden'); + $newContentObj.find('p#selectClassesMessage').attr("id","selectClassesMessage" + counter); + // Will need to uncomment this and find a way to apply the css style +// $newContentObj.find('section#internal-class').attr("id","internal-class" + +// counter); + $newContentObj.find("input[name='display-internalClass']").attr("name","display-internalClass" + counter); + $newContentObj.find('ul#selectedClasses').attr("id","selectedClasses" + counter); + $newContentObj.find('ul#selectedClasses' + counter).attr("name","selectedClasses" + counter); + + $newContentObj.find('ul#selectedClasses' + counter).children("li").each( function(i,abc) { + var $theCheckbox = $(this).find('input'); + $theCheckbox.attr("name", $theCheckbox.attr("name") + counter); + }); + + varOrClass = $newContentObj.find('select#selectClassGroup' + counter + ' option:selected').text(); + } + + //Create the container for the new content + + $newDivContainer = $("
", { + id: "divContainer" + counter, + "class": "pageContentContainer", + html: "" + contentTypeLabel + " - " + varOrClass + + "
" + }); + var $clickableSpan = $newDivContainer.children('span#clickable' + counter); + var $innerDiv = $newDivContainer.children('div#innerContainer' + counter); + $innerDiv.hide(); + //Expand/collapse toggle + $clickableSpan.click(function() { + if ( $innerDiv.is(':visible') ) { + $innerDiv.slideUp(222); + //$clickableSpan.find('img').attr("src","arrow-down.gif"); + var arrowDiv = $clickableSpan.find('div.arrow'); + arrowDiv.removeClass("collapseArrow"); + arrowDiv.addClass("expandArrow"); + } + else { + $innerDiv.slideDown(222); + //$clickableSpan.find('img').attr("src","arrow-up.gif"); + var arrowDiv = $clickableSpan.find('div.arrow'); + arrowDiv.removeClass("expandArrow"); + arrowDiv.addClass("collapseArrow"); + } + window.setTimeout('pageManagementUtils.adjustSaveButtonHeight()', 223); + }); + $newRemoveButton = $innerDiv.find('input#remove' + counter); + // this will have to disable submitted fields as well as hide them. + $newRemoveButton.click(function() { + $innerDiv.parent("div").css("display","none"); + pageManagementUtils.adjustSaveButtonHeight(); + }); + + $newDivContainer.appendTo($('section#contentDivs')); + $newContentObj.prependTo($innerDiv); + counter = counter + 10; + }, + resetClassGroupSection:function() { + $('select#selectClassGroup option').eq(0).attr('selected', 'selected'); + $("section#classesInSelectedGroup").addClass('hidden'); + }, + //finalize later, but basically use same attribute across page content and use attribute instead of id + //Attribute would be what keeps track of content, so contentCounter or something like that + toggleArrow:function() { + + + }, + //Adjust save button height + adjustSaveButtonHeight:function() { + if ( $("div#leftSide").css("height") != undefined ) { + $("div#leftSide").css("height",""); + if ( $("div#leftSide").height() < $("div#rightSide").height() ) { + $("div#leftSide").css("height",$("div#rightSide").height() + "px"); + } + } + } + +}; + +$(document).ready(function() { + pageManagementUtils.onLoad(); +}); \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/pagemanagement/page-pageList.ftl b/webapp/web/templates/freemarker/body/pagemanagement/page-pageList.ftl new file mode 100644 index 000000000..8553f4816 --- /dev/null +++ b/webapp/web/templates/freemarker/body/pagemanagement/page-pageList.ftl @@ -0,0 +1,32 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +
+ +<#if pages?has_content > + + + + <#list pages as pagex> + + + <#if pagex.pageUri??> + + <#else> + + + + +
TitleURI
${(pagex.title)!'-untitled-'}${pagex.pageUri}URI for page not defined
+ +<#else> +

There are no pages defined yet.

+ + +
+ + + + +
+ +
\ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/pagemanagement/pageList.ftl b/webapp/web/templates/freemarker/body/pagemanagement/pageList.ftl new file mode 100644 index 000000000..1230695fb --- /dev/null +++ b/webapp/web/templates/freemarker/body/pagemanagement/pageList.ftl @@ -0,0 +1,63 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +
+
+

Page Management

+
+
+ + +<#if pages?has_content > + + + + + + + + + + + + + + <#list pages as pagex> + + + + + + + + + + + +
Page Management
TitleURLTemplateMenu Page
+ <#if pagex.pageUri?has_content> + ${(pagex.title)!'-untitled-'} + <#else> + No URI defined for page. + + ${pagex.urlMapping}${(pagex.template)!''} + <#if pagex.menuItem?has_content> + + +
+ +<#else> +

There are no pages defined yet.

+ + +
+ + + + +
+

Use Menu Management to set the order of menu items.

+
+ + +${stylesheets.add('')} + diff --git a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl index 4f96db431..db2e20f98 100644 --- a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl +++ b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl @@ -13,7 +13,11 @@ <#if siteConfig.manageProxies?has_content>
  • Manage profile editing
  • - + + + <#if siteConfig.pageManagement?has_content> +
  • Page management
  • + <#if siteConfig.menuManagement?has_content>
  • Menu management
  • diff --git a/webapp/web/templates/freemarker/edit/forms/pageManagement.ftl b/webapp/web/templates/freemarker/edit/forms/pageManagement.ftl new file mode 100644 index 000000000..c8d6a68e0 --- /dev/null +++ b/webapp/web/templates/freemarker/edit/forms/pageManagement.ftl @@ -0,0 +1,157 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> +<#--Set up variables--> +<#assign pageData = editConfiguration.pageData /> +<#assign menuAction = pageData.menuAction /> +<#assign classGroup = pageData.classGroup /> +<#assign classGroups = pageData.classGroups /> + +<#assign selectedTemplateType = "default" /> +<#assign menuItem = ""/> +<#assign menuName = ""/> +<#assign prettyUrl = ""/> +<#assign associatedPage = ""/> +<#assign associatedPageURI = ""/> + +<#assign isClassGroupPage = false/> +<#assign includeAllClasses = false/> + + +<#-- some additional processing here which shows or hides the class group selection and classes based on initial action--> +<#assign existingClassGroupStyle = " " /> +<#assign selectClassGroupStyle = 'class="hidden"' /> +<#-- Reveal the class group and hide the class selects if adding a new menu item or editing an existing menu item with an empty class group (no classes)--> +<#if menuAction == "Add" || !classGroup?has_content> + <#assign existingClassGroupStyle = 'class="hidden"' /> + <#assign selectClassGroupStyle = " " /> + + + +<#--class group section has associated page uri, but that depends on editing a current page or if one is selected later--> +
    +

    Add Page

    +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    + + +
    +
    + <#-- Select classes in a class group --> +

    Select content to display *

    + + <#include "pageManagement--classIntersections.ftl"> + + +
    +
    +
    + + + + +
    + +
    +
    +
    +
    + + + + +

    Must begin with a leading forward slash: / (e.g., /people)

    +

    Template *

    + checked role="radio" /> + +
    + checked role="input" /> + +
    class="hidden" role="region"> + * +
    +

    This is a menu page

    + +
    +
    +
    +
    + or + Cancel +
    +

    * required fields

    +
    +
    + + + + +${stylesheets.add('')} +${stylesheets.add('')} +${stylesheets.add('')} + +${scripts.add('')} +${scripts.add('')} +${scripts.add('')} +${scripts.add('')} +