diff --git a/webapp/web/config/listViewConfig-hasElement.xml b/webapp/web/config/listViewConfig-hasElement.xml new file mode 100644 index 000000000..0ef5f399a --- /dev/null +++ b/webapp/web/config/listViewConfig-hasElement.xml @@ -0,0 +1,37 @@ + + + + + + + + PREFIX display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#> + PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#> + + SELECT ?menuItem + (afn:localname(?menuItem) AS ?menuItemName) + ?linkText + ?menuPosition WHERE { + ?subject ?property ?menuItem + OPTIONAL { ?menuItem display:linkText ?linkText } + OPTIONAL { ?menuItem display:menuPosition ?menuPosition } + } ORDER BY ?menuPosition + + + + CONSTRUCT { + ?subject ?property ?menuItem . + ?menuItem ?menuItemProp ?menuItemObj + } WHERE { + { ?subject ?property ?menuItem } + UNION { + ?subject ?property ?menuItem . + ?menuItem ?menuItemProp ?menuItemObj + } + } + + + + \ No newline at end of file diff --git a/webapp/web/css/individual/menuManagement.css b/webapp/web/css/individual/menuManagement.css new file mode 100644 index 000000000..0db52ece1 --- /dev/null +++ b/webapp/web/css/individual/menuManagement.css @@ -0,0 +1,20 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +/* MENU ITEMS------> */ +ul.menuItems { + width: 35%; + margin-bottom: 1.5em; +} +ul.menuItems li { + margin: .2em 0; + padding: .5em; + background: #f3f3f0; +} +ul.menuItems.dragNdrop li { + padding-left: 1em; + background: url("../../edit/forms/images/sortable_icon.png") no-repeat .4em center #f3f3f0; + cursor: move; +} +span.controls { + float: right; +} \ No newline at end of file diff --git a/webapp/web/js/individual/menuManagement.js b/webapp/web/js/individual/menuManagement.js new file mode 100644 index 000000000..5fd2362e1 --- /dev/null +++ b/webapp/web/js/individual/menuManagement.js @@ -0,0 +1,150 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +var menuManagement = { + + // Initial page setup + onLoad: function() { + this.mergeFromTemplate(); + this.initMenuItemData(); + this.initObjects(); + this.initMenuItemsDD(); + }, + + // Add variables from menupage template + mergeFromTemplate: function() { + $.extend(this, menuManagementData); + }, + + // Create references to frequently used elements for convenience + initObjects: function() { + this.menuItemsList = $('ul.menuItems'); + }, + + // Drag-and-drop + initMenuItemsDD: function() { + var menuItems = this.menuItemsList.children('li'); + + if (menuItems.length < 2) { + return; + } + + this.menuItemsList.addClass('dragNdrop'); + + menuItems.attr('title', 'Drag and drop to reorder menu items'); + + this.menuItemsList.sortable({ + cursor: 'move', + update: function(event, ui) { + alert("Congrats! You just reordered a menu item. (not really)"); + // Once we figure out how the editing will work, we'll call reorderMenuItems + // and get rid of the debug alert. + // menuManagement.reorderMenutItems(event, ui); + } + }); + }, + + // Reorder menu items. Called after menu item drag-and-drop + // This is all make-believe at the moment. Just an example to demonstrate to Huda how this could work. + reorderMenuItems: function(event, ui) { + var menuItems = $('li.menuItem').map(function(index, el) { + return $(this).data('menuItemUri'); + }).get(); + + $.ajax({ + url: menuManagement.reorderUrl, + data: { + predicate: menuManagement.positionPredicate, + individuals: menuItems + }, + traditional: true, // serialize the array of individuals for the server + dataType: 'json', + type: 'POST', + success: function(data, status, request) { + var pos; + $('.menuItem').each(function(index){ + pos = index + 1; + // Set the new position for this element. The only function of this value + // is so we can reset an element to its original position in case reordering fails. + menuManagement.setPosition(this, pos); + }); + // Set the form rank field value. + $('#rank').val(pos + 1); + }, + error: function(request, status, error) { + // ui is undefined after removal of a menu item. + if (ui) { + // Put the moved item back to its original position. + // Seems we need to do this by hand. Can't see any way to do it with jQuery UI. ?? + var pos = menuManagement.getPosition(ui.item), + nextpos = pos + 1, + menuItems = menuManagement.menuItemsList, + next = menuManagement.findMenuItem('position', nextpos); + + if (next.length) { + ui.item.insertBefore(next); + } + else { + ui.item.appendTo(menuItems); + } + + alert('Reordering of menu items failed.'); + } + } + }); + }, + + // On page load, associate data with each menu item list element. Then we don't + // have to keep retrieving data from or modifying the DOM as we manipulate the + // menu items. + initMenuItemData: function() { + $('.menuItem').each(function(index) { + $(this).data(menuItemData[index]); + + // RY We might still need position to put back an element after reordering + // failure. Position might already have been reset? Check. + // We also may need position to implement undo links: we want the removed menu item + // to show up in the list, but it has no position. + $(this).data('position', index+1); + }); + }, + + getPosition: function(menuItem) { + return $(menuItem).data('position'); + }, + + setPosition: function(menuItem, pos) { + $(menuItem).data('position', pos); + }, + + findMenuItem: function(key, value) { + var matchingMenuItem = $(); // if we don't find one, return an empty jQuery set + + $('.menuItem').each(function() { + var menuItem = $(this); + if ( menuItem.data(key) === value ) { + matchingMenuItem = menuItem; + return false; // stop the loop + } + }); + + return matchingMenuItem; + }, + + // Event listeners + + // Disable drag-n-drop and associated cues if only one menu item remains + // Good chance we won't need this if Huda's able to hook into standard delete for n3 editing (loads confirmation in separate page) + disableMenuItemsDD: function() { + var menuItems = this.menuItemsList.children('li'); + + this.menuItemsList.sortable({ disable: true } ); + + this.menuItemsList.removeClass('dragNdrop'); + + menuItems.removeAttr('title'); + } +}; + +$(document).ready(function() { + menuManagement.onLoad(); +}); \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/individual/individual-menu.ftl b/webapp/web/templates/freemarker/body/individual/individual-menu.ftl index 5770ae720..f9f26a641 100644 --- a/webapp/web/templates/freemarker/body/individual/individual-menu.ftl +++ b/webapp/web/templates/freemarker/body/individual/individual-menu.ftl @@ -4,16 +4,20 @@ <#include "individual-setup.ftl"> + +

Menu management

<#assign hasElement = propertyGroups.pullProperty("${namespaces.display}hasElement")> <#-- List the menu items --> -<#list hasElement.statements as statement> - Position | <#include "${hasElement.template}"> | <@p.editingLinks "hasElement" statement editable />
- - -
<#-- remove this once styles are applied --> + <#-- Link to add a new menu item --> <#if editable> @@ -23,6 +27,23 @@ -${stylesheets.add('')} +${stylesheets.add('', + '')} -${scripts.add('')} \ No newline at end of file +${headScripts.add('')} + +<#assign positionPredicate = "${namespaces.display}menuPosition" /> + + + +<#-- Since the individual page can currently be viewed by anonymous users, only invoke sortable if logged in for now + Jim is working on this (see NIHVIVO-2749) --> +<#if editable> + ${scripts.add('')} + \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/partials/individual/propStatement-hasElement.ftl b/webapp/web/templates/freemarker/body/partials/individual/propStatement-hasElement.ftl new file mode 100644 index 000000000..bbff0e3a7 --- /dev/null +++ b/webapp/web/templates/freemarker/body/partials/individual/propStatement-hasElement.ftl @@ -0,0 +1,16 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#-- Template for display:hasElement (used for menu system). + + This template must be self-contained and not rely on other variables set for the individual page, because it + is also used to generate the property statement during a deletion. + --> + +<#-- Anchor is here for convenience during development. Should be removed before release --> +${statement.linkText} + + \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl index 4a45fc1a5..ec45cfaee 100644 --- a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl +++ b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl @@ -14,11 +14,13 @@ <#if siteConfig.urls.menuN3Editor??> -
  • Menu management
  • + <#-- once new menu management is ready to go, we'll want to add a url for this to siteConfig.urls and remove menu.n3 editor --> +
  • Menu Management (in development)
  • +
  • menu.n3 editor
  • <#if siteConfig.urls.userList??> -
  • User accounts
  • +
  • User accounts