o Added resource type list to the add node dialog
o Allowing to submit the dialog only if the search dialogs are closed.
o Tests adapted.
o Added initial grunt-node-inspector config for debugging Karma tests.
o Added work in progress for saving properties and showing its error messages
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1694052 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/frontend/Gruntfile.js b/frontend/Gruntfile.js
index e5c1718..f4bf0a4 100644
--- a/frontend/Gruntfile.js
+++ b/frontend/Gruntfile.js
@@ -14,6 +14,15 @@
SLING_PORT: (typeof process.env.SLING_PORT === 'undefined' || process.env.SLING_PORT === null || '' === process.env.SLING_PORT) ? port : process.env.SLING_PORT
}
},
+ 'node-inspector': {
+ custom: {
+ options: {
+ 'web-port': 5050,
+ 'web-host': 'localhost',
+ 'debug-port': 5857
+ }
+ }
+ },
less: {
compileCore: {
options: {
diff --git a/frontend/debug_karma.cmd b/frontend/debug_karma.cmd
new file mode 100755
index 0000000..a654ae0
--- /dev/null
+++ b/frontend/debug_karma.cmd
@@ -0,0 +1,6 @@
+#!/bin/sh
+export PATH=$PATH:./node
+export PHANTOMJS_BIN="node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/bin/phantomjs"
+./grunt node-inspector &
+node --debug-brk ./node_modules/karma/bin/karma start
+echo "visit http://localhost:5050/?ws=localhost:5050&port=5858 and http://localhost:9876/"
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index 6966d1e..1ed44a2 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -31,7 +31,8 @@
"karma-ie-launcher": "0.1.5",
"webdriver-manager": "3.0.0",
"grunt-webdriver": "0.4.8",
- "nlf": "1.1.0"
+ "nlf": "1.1.0",
+ "grunt-node-inspector": "0.2.0"
},
"scripts": {
"postinstall": "node_modules/.bin/webdriver-manager update --standalone"
diff --git a/pom.xml b/pom.xml
index e75dd64..2779afb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,7 +93,7 @@
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
- <version>0.0.23</version>
+ <version>0.0.24</version>
<configuration>
<workingDirectory>frontend</workingDirectory>
</configuration>
@@ -177,6 +177,12 @@
<artifactId>org.apache.felix.scr.annotations</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -184,10 +190,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <distributionManagement>
- <repository>
- <id>www.jcrbrowser.org</id>
- <url>dav:http://www.jcrbrowser.org/sling/obr</url>
- </repository>
- </distributionManagement>
</project>
diff --git a/src/main/java/org/apache/sling/reseditor/DownloadBinaryProperty.java b/src/main/java/org/apache/sling/reseditor/DownloadBinaryProperty.java
index 150c426..032e42e 100644
--- a/src/main/java/org/apache/sling/reseditor/DownloadBinaryProperty.java
+++ b/src/main/java/org/apache/sling/reseditor/DownloadBinaryProperty.java
@@ -121,4 +121,4 @@
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/reseditor/ResourceTypeList.java b/src/main/java/org/apache/sling/reseditor/ResourceTypeList.java
new file mode 100644
index 0000000..8ef2a86
--- /dev/null
+++ b/src/main/java/org/apache/sling/reseditor/ResourceTypeList.java
@@ -0,0 +1,90 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.sling.reseditor;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Streams the content of the property specified by the request parameter
+ * 'property' to the response of the request.
+ */
+@Component
+@Service(Servlet.class)
+@Properties({
+ @Property(name = "service.description", value = "List the Resource Types available in the repository."),
+ @Property(name = "service.vendor", value = "The Apache Software Foundation"),
+ @Property(name = "sling.servlet.extensions", value = "json"),
+ @Property(name = "sling.servlet.resourceTypes", value = "sling/resource-editor/resource-type-list")
+
+})
+public class ResourceTypeList extends SlingSafeMethodsServlet {
+
+ private static final long serialVersionUID = -1L;
+
+ /** default log */
+ private final Logger log = LoggerFactory
+ .getLogger(ResourceTypeList.class);
+
+ @Override
+ protected void doGet(SlingHttpServletRequest request,
+ SlingHttpServletResponse response) throws ServletException,
+ IOException {
+ PrintWriter responseWriter = null;
+ Set<String> resourceTypes = new HashSet<String>();
+ try {
+ Iterator<Resource> resources = request.getResourceResolver().findResources("//*[@sling:resourceType]", "xpath");
+ while (resources.hasNext()) {
+ Resource resource = (Resource) resources.next();
+ String resourceTypeString = StringEscapeUtils.escapeHtml(resource.getResourceType());
+ resourceTypeString = "\""+resourceTypeString+"\"";
+ resourceTypes.add(resourceTypeString);
+ }
+ List<String> resourceTypeList = new LinkedList<String>(resourceTypes);
+ Collections.sort(resourceTypeList);
+ responseWriter = response.getWriter();
+ responseWriter.write(resourceTypeList.toString());
+ } finally {
+ responseWriter.close();
+ }
+
+ }
+}
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/MainController.js b/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/MainController.js
index 538cbbe..ac6e8b9 100644
--- a/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/MainController.js
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/MainController.js
@@ -44,6 +44,10 @@
$('#alertMsg #Message').remove();
});
})
+ var hasError = typeof thisMainController.settings.errorMessage != "undefined" && thisMainController.settings.errorMessage != "" && thisMainController.settings.errorMessage != null;
+ if (hasError){
+ thisMainController.displayAlertHtml("Status "+thisMainController.settings.errorStatus+". "+thisMainController.settings.errorMessage);
+ }
});
};
@@ -167,13 +171,18 @@
var encodedTitle = this.encodeToHTML(errorJson.title);
var encodedMsg = this.encodeToHTML(errorJson["status.message"]);
var errorMsg = encodedTitle+" ("+"Status "+errorJson["status.code"]+") "+encodedMsg;
- $('#alertMsg').append($("<div id='Message'>").append((resourcePath) ? "'"+resourcePath+"': "+errorMsg : errorMsg));
+ this.displayAlertHtml((resourcePath) ? "'"+resourcePath+"': "+errorMsg : errorMsg);
+ }
+
+ MainController.prototype.displayAlertHtml = function(html){
+ var thisMainController = this;
+ $('#alertMsg').append($("<div id='Message'>").append(html));
$("#alert").slideDown(function() {
thisMainController.adjust_height();
});
+
}
-
MainController.prototype.getNTFromLi = function(li){
var nt_name = $(li).children("a").find("span span.node-type").text();
return this.ntManager.getNodeType(nt_name);
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/properties/PropertyController.js b/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/properties/PropertyController.js
index ebddeab..19df319 100644
--- a/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/properties/PropertyController.js
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/properties/PropertyController.js
@@ -147,13 +147,13 @@
PropertyController.prototype.saveProperty = function(key, value){
var thisPropertyController = this;
var data = {};
- data[key] = value;
+ data[key] = [value,value];
data["_charset_"] = "utf-8";
$.ajax({
type: 'POST',
- url: location.href,
- dataType: "json",
- data: data
+ url: location.href+"?"+key+"="+value,
+ dataType: "json"
+// ,data: data
})
.done(function() {
$.notify({
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/tree/AddNodeController.js b/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/tree/AddNodeController.js
index e5f0231..ef3976a 100644
--- a/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/tree/AddNodeController.js
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor-static-content/js/tree/AddNodeController.js
@@ -38,8 +38,8 @@
this.showAllNodeTypes = false;
this.nodeTypeObjects = [];
this.nodeType="";
- this.latestEnteredNodeName="";
- this.latestEnteredResType="";
+ this.nodeNameSubmitable=false; // initially open
+ this.resourceTypeSubmitable=true;
var thatAddNodeController = this;
$(document).ready(function() {
@@ -76,45 +76,48 @@
AddNodeController.prototype.addNode = function() {
var thatAddNodeController = this;
- var nodeName = this.latestEnteredNodeName;
- var nodeType = $("#nodeType").select2("val");
- var resourceType = this.latestEnteredResType;
-
- var data = {"_charset_": "utf-8"};
- if ("" != nodeType){
- data["jcr:primaryType"] = nodeType;
+ var dialogSubmitable = this.resourceTypeSubmitable && this.nodeNameSubmitable;
+ if (dialogSubmitable) {
+ var nodeName = $("#nodeName").select2("val");
+ var nodeType = $("#nodeType").select2("val");
+ var resourceType = $("#resourceType").select2("val");
+
+
+ var data = {"_charset_": "utf-8"};
+ if ("" != nodeType){
+ data["jcr:primaryType"] = nodeType;
+ }
+ var canAddResourceType = nodeType == "" ? true : this.mainController.ntManager.getNodeType(nodeType).canAddProperty("sling:resourceType", "String");
+ if ("" != resourceType && canAddResourceType){
+ data["sling:resourceType"] = resourceType;
+ }
+ var targetURL = (this.lastAddNodeURL=="/") ? "/" : this.lastAddNodeURL+"/";
+ targetURL = this.mainController.decodeFromHTML(targetURL);
+ if ("" != nodeName) {
+ targetURL += nodeName;
+ }
+ if (targetURL=="/"){
+ //adding a node without a specified name to the root node
+ targetURL = "/*";
+ }
+ var encodedTargetURL = this.mainController.encodeURL(targetURL);
+
+ $.ajax({
+ type: 'POST',
+ url: encodedTargetURL,
+ dataType: "json",
+ data: data
+ })
+ .done(function() {
+ $('#addNodeDialog').modal("hide");
+ var htmlDecodedLastAddNodeURL = thatAddNodeController.mainController.decodeFromHTML(thatAddNodeController.lastAddNodeURL);
+ thatAddNodeController.mainController.redirectTo(htmlDecodedLastAddNodeURL);
+ })
+ .fail(function(errorJson) {
+ $('#addNodeDialog').modal("hide");
+ thatAddNodeController.mainController.displayAlert(errorJson);
+ });
}
- var canAddResourceType = nodeType == "" ? true : this.mainController.ntManager.getNodeType(nodeType).canAddProperty("sling:resourceType", "String");
- if ("" != resourceType && canAddResourceType){
- data["sling:resourceType"] = resourceType;
- }
- var targetURL = (this.lastAddNodeURL=="/") ? "/" : this.lastAddNodeURL+"/";
- targetURL = this.mainController.decodeFromHTML(targetURL);
- if ("" != nodeName) {
- targetURL += nodeName;
- }
- if (targetURL=="/"){
- //adding a node without a specified name to the root node
- targetURL = "/*";
- }
- var encodedTargetURL = this.mainController.encodeURL(targetURL);
-
- $.ajax({
- type: 'POST',
- url: encodedTargetURL,
- dataType: "json",
- data: data
- })
- .done(function() {
- $('#addNodeDialog').modal("hide");
- var htmlDecodedLastAddNodeURL = thatAddNodeController.mainController.decodeFromHTML(thatAddNodeController.lastAddNodeURL);
- thatAddNodeController.mainController.redirectTo(htmlDecodedLastAddNodeURL);
- })
- .fail(function(errorJson) {
- $('#addNodeDialog').modal("hide");
- thatAddNodeController.mainController.displayAlert(errorJson);
- });
-
}
AddNodeController.prototype.toggleApplicableNodeTypes = function() {
@@ -198,6 +201,7 @@
nodeHelpElement.show();
}
nodeNameListStar.sort();
+ nodeNameListStar.unshift("");
var nodeNameObjects = jQuery.map(nodeNameListStar, function( nt, i ) {
return {id: nt, text: nt};
});
@@ -205,6 +209,7 @@
$("#nodeName").select2({
placeholder: "Enter or select a node name",
allowClear: true,
+ selectOnBlur: true,
dropdownCssClass: "node_name_dd_container",
data: nodeNameObjects,
createSearchChoice: function(searchTerm){
@@ -212,7 +217,13 @@
return {id:searchTerm, text:searchTerm};
}
});
-
+ $("#nodeName").on("select2-open", function(e) {
+ thatAddNodeController.nodeNameSubmitable=false;
+ });
+ $("#nodeName").on("select2-close", function(e) {
+ thatAddNodeController.nodeNameSubmitable=true;
+ });
+
var nodeNameList = Object.keys(appliCnTypesByNodeName);
nodeNameList.sort();
thatAddNodeController.nodeTypeObjects = getNodeTypesByDependenyState.call(thatAddNodeController, nodeNameList, appliCnTypesByNodeName, thatAddNodeController.nodeTypeObjects);
@@ -251,12 +262,12 @@
$('#resourceType').select2('data', null);
var contextPath = this.mainController.getContextPath();
contextPath = "/" === contextPath ? "" : contextPath;
- var url = contextPath+"/libs/sling/resource-editor/servlet-nodes/resource-types.json";
+ var url = contextPath+"/libs/sling/resource-editor/content-nodes/resource-types.json";
$.getJSON(url, function( origData ) {
var data = jQuery.map( origData, function( n, i ) {
- return ( {id:i, text:n} );
+ return ( {id:n, text:n} );
});
-
+ data.unshift({id:"",text:""});
var select2 = $("#resourceType").select2({
placeholder: "Enter or select a resource type",
allowClear: true,
@@ -268,6 +279,13 @@
return {id:searchTerm, text:searchTerm};
}
}).data("select2");
+
+ $("#resourceType").on("select2-open", function(e) {
+ thatAddNodeController.resourceTypeSubmitable=false;
+ });
+ $("#resourceType").on("select2-close", function(e) {
+ thatAddNodeController.resourceTypeSubmitable=true;
+ });
$('#addNodeDialog').modal('show');
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/500.jsp b/src/main/resources/SLING-INF/libs/sling/resource-editor/500.jsp
new file mode 100644
index 0000000..e832aa0
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor/500.jsp
@@ -0,0 +1,30 @@
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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.
+-->
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<!-- simple JSP rendering test -->
+<%@page session="false"%>
+
+<%
+// request.setAttribute("error.msg",response.getStatus()+"");
+request.setAttribute("error.msg", "500: "+request.getAttribute("javax.servlet.error.exception"));
+// request.setAttribute("error.msg", "500: "+request.getAttribute("javax.servlet.error.message"));
+%>
+
+<%@ include file="html.jsp" %>
\ No newline at end of file
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/Throwable.jsp b/src/main/resources/SLING-INF/libs/sling/resource-editor/Throwable.jsp
new file mode 100644
index 0000000..6f443ba
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor/Throwable.jsp
@@ -0,0 +1,29 @@
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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.
+-->
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<!-- simple JSP rendering test -->
+<%@page session="false"%>
+
+<%
+// request.setAttribute("error.msg",response.getStatus()+"");
+ //request.setAttribute("error.msg", request.getAttribute("javax.servlet.error.message"));
+%>
+
+<%@ include file="html.jsp" %>
\ No newline at end of file
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/content-nodes.json b/src/main/resources/SLING-INF/libs/sling/resource-editor/content-nodes.json
new file mode 100644
index 0000000..e845da2
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor/content-nodes.json
@@ -0,0 +1,7 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "resource-types" : {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType" : "sling/resource-editor/resource-type-list"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/html.jsp b/src/main/resources/SLING-INF/libs/sling/resource-editor/html.jsp
index 86c0d50..3d00033 100644
--- a/src/main/resources/SLING-INF/libs/sling/resource-editor/html.jsp
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor/html.jsp
@@ -92,7 +92,9 @@
var mainControllerSettings = {
contextPath: "<%= request.getContextPath() %>",
- nodeTypes: ntManager.getNodeTypeNames()
+ nodeTypes: ntManager.getNodeTypeNames(),
+ errorStatus: '${requestScope["javax.servlet.error.status_code"]}',
+ errorMessage: '<%=request.getAttribute("javax.servlet.error.message") == null ? "" : request.getAttribute("javax.servlet.error.message") %>'
};
var mainController = new org.apache.sling.reseditor.MainController(mainControllerSettings, ntManager);
@@ -241,6 +243,7 @@
<button type="button" class="close"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h3>Cheat Sheet</h3>
<h4>Shortcuts</h4>
+ <p>Submitting the dialog is only allowed if no search dialog is open and the fields are set.</p>
<p>You can use the</p>
<ul>
<li><kbd>c</kbd> key on a node when the tree has the focus for opening the dialog to add a child node.</li>
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/properties.jsp b/src/main/resources/SLING-INF/libs/sling/resource-editor/properties.jsp
index 6b75ad5..1cb60fb 100644
--- a/src/main/resources/SLING-INF/libs/sling/resource-editor/properties.jsp
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor/properties.jsp
@@ -62,52 +62,30 @@
<label class="proplabel" for='${property.name}'>${property.name} [<%=PropertyType.nameFromValue(property.getType())%>${property.multiple ? ' multiple' : ''}]</label>
</div>
<div class="col-sm-7 property-col">
+<!-- geschachteltes div mit Zeilen pro multi value property -->
+<!-- dann passen auch die Abstände (innerhalb des Properties und zwischen den Properties) -->
+<%-- ${property.values} --%>
<c:choose>
<c:when test="${property.multiple}" >
- <fieldset class="propmultival_fieldset">
- <div> </div>
- <c:forEach var="value" items="<%=property.getValues()%>">
- <c:choose>
- <c:when test="${property.type == PropertyType.BINARY}" >
- <p>I'm a binary property</p>
- </c:when>
- <c:when test="${property.type == PropertyType.STRING}" >
- <re:string-editor></re:string-editor>
- </c:when>
- <c:otherwise>
- <input class="propinputmultival form-control" value="${value.string}"/>
- </c:otherwise>
- </c:choose>
+<!-- <fieldset class="propmultival_fieldset"> -->
+ <c:forEach var="value" items="<%=property.getValues()%>" varStatus="multiPropertyLoopStatus">
+ <div id="property-${propertyLoopStatus.index}-${multiPropertyLoopStatus.index}" class="row" data-property-name="${fn:escapeXml(property.name)}-${multiPropertyLoopStatus.index}" >
+ <fieldset>
+ <div class="col-sm-12">
+ <%@ include file="property-editor.jsp" %>
+ </div>
+ </fieldset>
+ </div>
</c:forEach>
- </fieldset>
+<!-- </fieldset> -->
</c:when>
<c:otherwise>
- <c:choose>
- <c:when test="<%=property.getType() == PropertyType.BINARY%>" >
- <c:choose>
- <c:when test='<%=currentNode.getParent().isNodeType("nt:file") %>'>
- <a class="propinput" href="<%= request.getContextPath() %>${resource.parent.path}">Download</a>
- </c:when>
- <c:otherwise>
- <a class="propinput" href="<%= request.getContextPath() %>${resource.path}.property.download?property=${property.name}">View (choose "Save as..." to download)</a>
- </c:otherwise>
- </c:choose>
- </c:when>
- <c:when test="<%=property.getType() == PropertyType.STRING%>" >
- <re:string-editor property_name="${fn:escapeXml(property.name)}-editor" value="${property.string}"></re:string-editor>
- </c:when>
- <c:when test="<%=property.getType() == PropertyType.PATH%>" >
- <re:path-editor value="${property.string}" component_id="property-${propertyLoopStatus.index}-path-editor"></re:path-editor>
- <re:path-viewer value="${property.string}" component_id="property-${propertyLoopStatus.index}-path-viewer" editor_component_id="property-${propertyLoopStatus.index}-path-editor"></re:path-viewer>
- </c:when>
- <c:otherwise>
- <input class="propinput form-control" id="${property.name}" name="${property.name}" value="${property.string}"/>
- </c:otherwise>
- </c:choose>
+ <%@ include file="property-editor.jsp" %>
</c:otherwise>
</c:choose>
</div>
<div class="col-sm-2">
+ <span class="icon property-icon glyphicon glyphicon-plus" aria-hidden="true"></span>
<span class="icon property-icon glyphicon glyphicon-save" aria-hidden="true"></span>
<span class="icon property-icon glyphicon glyphicon-remove" aria-hidden="true"></span>
</div>
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/property-editor.jsp b/src/main/resources/SLING-INF/libs/sling/resource-editor/property-editor.jsp
new file mode 100644
index 0000000..1f4151c
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/resource-editor/property-editor.jsp
@@ -0,0 +1,27 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+<%@ taglib prefix="re" uri="http://sling.apache.org/resource-editor"%>
+
+<sling:defineObjects />
+
+ <c:choose>
+ <c:when test="<%=property.getType() == PropertyType.BINARY%>" >
+ <c:choose>
+ <c:when test='<%=currentNode.getParent().isNodeType("nt:file") %>'>
+ <a class="propinput" href="<%= request.getContextPath() %>${resource.parent.path}">Download</a>
+ </c:when>
+ <c:otherwise>
+ <a class="propinput" href="<%= request.getContextPath() %>${resource.path}.property.download?property=${property.name}">View (choose "Save as..." to download)</a>
+ </c:otherwise>
+ </c:choose>
+ </c:when>
+ <c:when test="<%=property.getType() == PropertyType.STRING%>" >
+ <re:string-editor property_name="${fn:escapeXml(property.name)}-editor" value="${property.multiple ? value.string : property.string}"></re:string-editor>
+ </c:when>
+ <c:when test="<%=property.getType() == PropertyType.PATH%>" >
+ <re:path-editor value="${property.multiple ? value.string : property.string}" component_id="property-${propertyLoopStatus.index}-path-editor"></re:path-editor>
+ <re:path-viewer value="${property.multiple ? value.string : property.string}" component_id="property-${propertyLoopStatus.index}-path-viewer" editor_component_id="property-${propertyLoopStatus.index}-path-editor"></re:path-viewer>
+ </c:when>
+ <c:otherwise>
+ <input class="propinput form-control" id="${property.name}" name="${property.name}" value="${property.multiple ? value.string : property.string}"/>
+ </c:otherwise>
+ </c:choose>
\ No newline at end of file
diff --git a/src/main/resources/SLING-INF/libs/sling/resource-editor/servlet-nodes.json b/src/main/resources/SLING-INF/libs/sling/resource-editor/servlet-nodes.json
deleted file mode 100644
index 1e5c3ed..0000000
--- a/src/main/resources/SLING-INF/libs/sling/resource-editor/servlet-nodes.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "primaryNodeType": "nt:unstructured",
- "resource-types" : {
- "primaryNodeType": "nt:unstructured",
- "sling:resourceType" : "resource-editor/resource-type-list"
- }
-}
\ No newline at end of file
diff --git a/src/test/javascript/e2e/spec/e2e_spec.js b/src/test/javascript/e2e/spec/e2e_spec.js
index 984cf83..90957ea 100644
--- a/src/test/javascript/e2e/spec/e2e_spec.js
+++ b/src/test/javascript/e2e/spec/e2e_spec.js
@@ -171,7 +171,7 @@
client = client.url(homeURL);
client
.waitForExist('#last-element').click("#root li[nodename=\"aTestNode\"] i.add-icon")
- .waitForVisible('#addNodeDialog.add-node-finished', 1000).click('#addNodeDialog .btn.btn-primary.submit')
+ .waitForVisible('#addNodeDialog.add-node-finished', 1000).addValue('#select2-drop .select2-input', 'Return').click('#addNodeDialog .btn.btn-primary.submit')
// The open node animation will take longer than 500ms thus setting 2000ms as max.
.waitForExist('#root li[nodename="aTestNode"].opened', 2000).elements('#root li[nodename="aTestNode"].opened li a .jstree-themeicon', function(err, res) {
client
@@ -200,7 +200,7 @@
client.keys('Delete')
.waitForVisible(confirmationOkBtn)
.click(confirmationOkBtn)
- .waitForVisible(openTestNodeIcon)
+ .waitForVisible(openTestNodeIcon, 1000)
.click(openTestNodeIcon)
.waitForExist('#last-element').elements('#root li[nodename="aTestNode"] li a .jstree-themeicon', function(err, res) {
assert(typeof err === "undefined" || err === null);
diff --git a/src/test/javascript/spec/resource_editor_spec.js b/src/test/javascript/spec/resource_editor_spec.js
index 5b45c9a..7e92434 100644
--- a/src/test/javascript/spec/resource_editor_spec.js
+++ b/src/test/javascript/spec/resource_editor_spec.js
@@ -241,7 +241,7 @@
spyOn(mainController, "encodeURL").and.returnValue("/testnode");
spyOn($.fn, "select2").and.returnValue("nt:unstructured");
-
+
spyOn($, 'ajax').and.callFake(function (req) {
var d = $.Deferred();
d.resolve({});
@@ -249,9 +249,11 @@
});
spyOn(mainController,"redirectTo").and.returnValue(null);
-
- addNodeController.addNode();
+ addNodeController.nodeNameSubmitable=true;
+ addNodeController.resourceTypeSubmitable=true;
+ addNodeController.addNode();
+
expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/testnode");
expect($.ajax.calls.mostRecent().args[0]["data"]["_charset_"]).toEqual("utf-8");
expect($.ajax.calls.mostRecent().args[0]["data"]["jcr:primaryType"]).toEqual("nt:unstructured");