diff options
Diffstat (limited to 'winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates')
6 files changed, 1735 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp new file mode 100644 index 0000000..aadec72 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp @@ -0,0 +1,1080 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Tobias Binz - communication with the nested iframe + *******************************************************************************/ +--%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="w" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="b" tagdir="/WEB-INF/tags/servicetemplates/boundarydefinitions"%> +<%@taglib prefix="pol" tagdir="/WEB-INF/tags/common/policies" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> +<%@taglib prefix="wr" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%@page import="org.eclipse.winery.common.ModelUtilities"%> + +<pol:policydiag allPolicyTypes="${it.allPolicyTypes}" repositoryURL="${it.repositoryURL}" /> + +<b:browseForServiceTemplatePropertyReqOrCap definedPropertiesAsJSONString="${it.definedPropertiesAsJSONString}" /> + +<div class="modal fade" id="propertyMappingDiag"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title">Add property mapping</h4> + </div> + <div class="modal-body"> + <form id="propertyMappingForm" enctype="multipart/form-data"> + <fieldset> + <div class="form-group"> + <label for="serviceTemplatePropertyRef">Service Template Property</label> + <div class="row"> + <div class="col-xs-10"> + <input name="serviceTemplatePropertyRef" id="serviceTemplatePropertyRef" class="form-control" type="text" required="required"> + </div> + <div class="col-xs-2"> + <button type="button" class="btn btn-default btn-sm" onclick="browseForServiceTemplateProperty($('#serviceTemplatePropertyRef'));">Browse</button> + </div> + </div> + </div> + + <div class="form-group"> + <label for="targetObjectRef">Target: Node Template, Requirement, Capability, or Relationship Template</label> + <div class="row"> + <div class="col-xs-4"> + <input name="targetObjectRef" id="targetObjectRef" class="form-control" type="text" required="required"> + </div> + <div class="col-xs-2"> + <button type="button" class="btn btn-default btn-sm" onclick="browseForTemplateAndProperty();">Browse</button> + </div> + </div> + </div> + + <div class="form-group"> + <label for="targetPropertyRef">Target Property</label> + <input name="targetPropertyRef" id="targetPropertyRef" class="form-control" type="text" required="required"/> + </div> + </fieldset> + </form> + </div> + + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button id="addPropertyMapping" type="button" class="btn btn-primary" onclick="addPropertyMapping()">Add</button> + <button id="updatePropertyMapping" type="button" class="btn btn-primary" onclick="updatePropertyMapping()">Update</button> + </div> + </div> + </div> +</div> + +<div class="modal fade" id="propertyConstraintDiag"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title">Add property constraint</h4> + </div> + <div class="modal-body"> + <form id="propertyMappingForm" enctype="multipart/form-data"> + <fieldset> + <div class="form-group"> + <label for="serviceTemplatePropertyRef">Service Template Property</label> + <div class="row"> + <div class="col-xs-10"> + <input name="serviceTemplatePropertyRef" id="serviceTemplatePropertyRefForConstraint" class="form-control" type="text" /> + </div> + <div class="col-xs-2"> + <button type="button" class="btn btn-default btn-sm" onclick="browseForServiceTemplateProperty($('#serviceTemplatePropertyRefForConstraint'));">Browse</button> + </div> + </div> + </div> + + <w:typeswithshortnameasselect label="Constraint Type" selectname="constraintType" type="constrainttype" typesWithShortNames="${it.constraintTypes}"/> + + <div class="form-group"> + ... constraint fragment ... + </div> + </fieldset> + </form> + </div> + + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button id="addPropertyConstraint" type="button" class="btn btn-primary" onclick="addPropertyMapping()">Add</button> + <button id="updatePropertyConstraint" type="button" class="btn btn-primary" onclick="updatePropertyMapping()">Update</button> + </div> + </div> + </div> +</div> + + + +<div id="alltabswithcontent"> +<ul class="nav nav-tabs" id="myTab"> + <li class="active"><a href="#properties">Properties</a></li> + <li><a href="#propertymappings">Property Mappings</a></li> + <li><a href="#propertyconstraints">Property Constraints</a></li> + <li><a href="#requirements">Requirements</a></li> + <li><a href="#capabilities">Capabilities</a></li> + <li><a href="#policies">Policies</a></li> + <li><a href="#interfaces">Interfaces</a></li> + <li><a href="#xml">XML</a></li> +</ul> + +<div class="tab-content"> + + <div class="tab-pane active" id="properties"> + <%-- reloadAfterSuccess is necessary as the XMLtree has to be changed --%> + <o:orioneditorarea areaid="XMLtextarea" url="boundarydefinitions/properties" reloadAfterSuccess="true">${it.definedPropertiesAsEscapedHTML}</o:orioneditorarea> + </div> + + <div class="tab-pane" id="propertymappings"> + <c:choose> + <c:when test="${empty it.definedPropertiesAsEscapedHTML}"> + <p>No properties available. Thus, no properties can be mapped. Please define properties.</p> + </c:when> + <c:otherwise> + <button id="deleteRequirement" class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(propertyMappingsTableInfo, 'Property Mapping', 'boundarydefinitions/propertymappings/');">Remove</button> + <button class="rightbutton btn btn-xs btn-info" onclick="openAddPropertyMappingDiag();">Add</button> + <button class="rightbutton btn btn-xs btn-primary" onclick="openUpdatePropertyMappingDiag();">Edit</button> + <table id="propertyMappingsTable"> + <thead> + <tr> + <th>Service Template Property</th> + <th>Target</th> + <th>Target Property</th> + </tr> + </thead> + <tbody> + <c:if test="${not empty it.defs.properties and not empty it.defs.properties.propertyMappings and not empty it.defs.properties.propertyMappings.propertyMapping}"> + <c:forEach items="${it.defs.properties.propertyMappings.propertyMapping}" var="propertyMapping"> + <tr> + <td>${propertyMapping.serviceTemplatePropertyRef}</td> + <td>${propertyMapping.targetObjectRef.id}</td> <%-- .name cannot be used as it is not an Id. Future work: Store the id in a seperate field and show the name to the user --%> + <td>${propertyMapping.targetPropertyRef}</td> + </tr> + </c:forEach> + </c:if> + </tbody> + </table> + </c:otherwise> + </c:choose> + </div> + + <%-- TODO: provide this as .tag. The property constraint resource should also be provided as tag --%> + <div class="tab-pane" id="propertyconstraints"> + <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(propertyConstraintsTableInfo, 'Property Constraint', 'propertyconstraints/');">Remove</button> + <button class="rightbutton btn btn-xs btn-info" onclick="openAddPropertyConstraintDiag();">Add</button> + <button class="rightbutton btn btn-xs btn-primary" onclick="openUpdatePropertyConstraintDiag();">Edit</button> + <table id="propertyconstraintstable"> + <thead> + <tr> + <th>(internal id)</th> + <th>Service Template Property</th> + <th>Constraint Type</th> + <th>Constraint</th> + </tr> + </thead> + <tbody> + <tr> + <td>example</td> + <td>/demo</td> + <td>http://www.example.com/accessrestrictions</td> + <td>(not yet implemented)</td> + </tr> + </tbody> + </table> + </div> + + <div class="tab-pane" id="requirements"> + <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(requirementsTableInfo, 'Requirement', 'boundarydefinitions/requirements/');">Remove</button> + <button class="rightbutton btn btn-xs btn-info" onclick="openReqEditor(false);">Add</button> + <button class="rightbutton btn btn-xs btn-primary" onclick="openReqEditor(true);">Edit</button> + <table id="requirementstable"> + <thead> + <tr> + <th>(Id)</th><%-- of the boundary requirement, also used as the id of this element--%> + <th>Name</th> + <th>Reference</th> + </tr> + </thead> + <tbody> + <c:forEach var="item" items="${it.defs.requirements.requirement}"> + <tr> + <td>${wr:determineIdUsingHashCode(item)}</td> + <td>${item.name}</td> + <td>${item.ref.id}</td> + </tr> + </c:forEach> + </tbody> + </table> + </div> + + <div class="tab-pane" id="capabilities"> + <%-- mirrored from requirements --%> + <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(capabilitiesTableInfo, 'Capability', 'boundarydefinitions/capabilities/');">Remove</button> + <button class="rightbutton btn btn-xs btn-info" onclick="openCapEditor(false);">Add</button> + <button class="rightbutton btn btn-xs btn-primary" onclick="openCapEditor(true);">Edit</button> + <table id="capabilitiestable"> + <thead> + <tr> + <th>(Id)</th><%-- of the boundary requirement, also used as the id of this element--%> + <th>Name</th> + <th>Reference</th> + </tr> + </thead> + <tbody> + <c:forEach var="item" items="${it.defs.capabilities.capability}"> + <tr> + <td>${wr:determineIdUsingHashCode(item)}</td> + <td>${item.name}</td> + <td>${item.ref.id}</td> + </tr> + </c:forEach> + </tbody> + </table> + </div> + + <div class="tab-pane" id="policies"> + <pol:policies list="${it.defs.policies.policy}" repositoryURL="${it.repositoryURL}" /> + <br /> + <button class="btn btn-default btn-sm btn-primary" onclick="savePolicies();">Save</button> + </div> + <script> + // work around for topology modeler's policy usage + $(".addnewpolicy").show(); + + // required for the policy addition dialog + winery.repositoryURL = "${it.repositoryURL}"; + + function savePolicies() { + require(["winery-support-common", "XMLWriter"], function(wsc) { + var xmlw = new XMLWriter("utf-8"); + xmlw.writeStartDocument(); + + wsc.writeCollectionDefinedByATextArea(xmlw, + $("div.policiesContainer").children("div.content").children("div.policy"), + "Policies"); + + xmlw.writeEndDocument(); + + var data = xmlw.flush(); + + $.ajax({ + url: "boundarydefinitions/policies", + data: data, + type: "PUT", + contentType: "application/xml", + }).done(function (result) { + vShowSuccess("Sucessfully saved policies"); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not save policies", jqXHR, errorThrown); + }); + }); + } + </script> + + <b:browseForX XLong="node template" XShort="NodeTemplate"/> + <script> + /** + * called from browseForX + */ + function setNodeTemplateRef() { + var newRef = $("#NodeTemplateReferenceField").val(); + $("#nodeTemplateRefForOperation").val(newRef); + storeNewReference(newRef); + updateTargetInterfaceAndOperation(true); + $("#browseForNodeTemplateDiag").modal("hide"); + } + + function browseForNodeTemplate() { + $("#NodeTemplateReferenceField").val($("#nodeTemplateRefForOperation").val()); + $("#browseForNodeTemplateDiag").modal("show"); + } + </script> + + <b:browseForX XLong="relationship template" XShort="RelationshipTemplate"/> + <script> + /** + * called from browseForX + */ + function setRelationshipTemplateRef() { + var newRef = $("#RelationshipTemplateReferenceField").val(); + $("#relationshipTemplateRefForOperation").val(newRef); + storeNewReference(newRef); + updateTargetInterfaceAndOperation(false); + $("#browseForRelationshipTemplateDiag").modal("hide"); + } + + function browseForRelationshipTemplate() { + $("#RelationshipTemplateReferenceField").val($("#relationshipTemplateRefForOperation").val()); + $("#browseForRelationshipTemplateDiag").modal("show"); + } + </script> + + <script> + function browseForPlan() { + vShowError("not yet implemented."); + } + </script> + + <div class="tab-pane" id="interfaces"> + <h4>Provided Interface and Operation</h4> + + <form class="form-horizontal"> + <div class="form-group"> + <label for="interface" class="col-sm-1 control-label">Interface</label> + <div class="col-sm-8"> + <input id="interface" class="form-control" placeholder="NCName or URI"> + </div> + <button type="button" class="btn btn-danger btn-sm col-sm-1" onclick="deleteCurrentlySelectedInterface();">Delete</button> + </div> + <div class="form-group"> + <label for="operation" class="col-sm-1 control-label">Operation</label> + <div class="col-sm-8"> + <input id="operation" class="form-control" placeholder="NCName"> + </div> + <button type="button" class="btn btn-danger btn-sm col-sm-1" onclick="deleteCurrentlySelectedOperation();">Delete</button> + </div> + </form> + + <h4>Target</h4> + + <form id="reftargettypeForm"> + <label> + <input id="nodeRadio" type="radio" name="reftargettype" value="node" checked="checked"> + Node Template + </label> + <label> + <input id="relationshipRadio" type="radio" name="reftargettype" value="relationship"> + Relationship Template + </label> + <label> + <input id="planRadio" type="radio" name="reftargettype" value="plan"> + Plan + </label> + </form> + + <form class="form-horizontal"> + <div class="form-group" id="selectNodeTemplateDiv"> + <label for="nodeTemplateRefForOperation" class="col-sm-1 control-label">Reference</label> + <div class="col-sm-8"> + <input id="nodeTemplateRefForOperation" class="form-control"> + </div> + <button type="button" class="btn btn-default btn-sm col-sm-1" onclick="browseForNodeTemplate();">Browse</button> + </div> + + <div class="form-group" id="selectRelationshipTemplateDiv" style="display:none;"> + <label for="relationshipTemplateRefForOperation" class="col-sm-1 control-label">Reference</label> + <div class="col-sm-8"> + <input id="relationshipTemplateRefForOperation" class="form-control"> + </div> + <button type="button" class="btn btn-default btn-sm col-sm-1" onclick="browseForRelationshipTemplate();">Browse</button> + </div> + + <div class="form-group" id="selectPlanDiv" style="display:none;"> + <label for="planRefForOperation" class="col-sm-1 control-label">Reference</label> + <div class="col-sm-8"> + <c:choose> + <c:when test="${empty it.listOfAllPlans}"> + <p>No plans available> + </c:when> + <c:otherwise> + <a id="planRefForOperation" href="#"></a> + </c:otherwise> + </c:choose> + </div> + </div> + </form> + + <h4>Target Interface and Operation</h4> + <form class="form-horizontal"> + <div class="form-group" id="selectInterfaceNameDiv"> + <label for="TargetInterface" class="col-sm-1 control-label">Interface</label> + <div class="col-sm-8"> + <input id="TargetInterface" class="form-control"> + </div> + </div> + + <div class="form-group" id="selectOperationNameDiv"> + <label for="TargetOperation" class="col-sm-1 control-label">Operation</label> + <div class="col-sm-8"> + <input id="TargetOperation" class="form-control"> + </div> + </div> + </form> + + <div id="notApplicableDiv" style="display:none;"> + <p>not applicable in the case of plans</p> + </div> + + </div> + + <script> + // initialize interface selection + require(["winery-support-common"], function(wsc) { + wsc.fetchSelect2DataAndInitSelect2("interface", "boundarydefinitions/interfaces/?select2", function() { + $("#interface").on("change", function() { + updateOperationsField(); + }); + if ($("#interface").select2("val") != "") { + updateOperationsField(); + } + }, true); + }); + + function getInterfacesAndInterfaceURLs() { + var iface = $("#interface").select2("val"); + iface = encodeID(iface); + + var ifacesURL = "boundarydefinitions/interfaces/"; + var ifaceURL = ifacesURL + iface + "/"; + return { + ifacesURL: ifacesURL, + ifaceURL: ifaceURL + } + } + + function getOperationsAndOperationURLs() { + var ifaceURL = getInterfacesAndInterfaceURLs().ifaceURL; + var operation = $("#operation").select2("val"); + operation = encodeID(operation); + + var operationsURL = ifaceURL + "exportedoperations/"; + var operationURL = operationsURL + operation + "/"; + return { + operationsURL: operationsURL, + operationURL: operationURL + } + } + + /** + * Updates the field of the exported operation + */ + function updateOperationsField() { + var iface = $("#interface").select2("val"); + var urls = getInterfacesAndInterfaceURLs(); + + $.ajax({ + url: urls.ifaceURL, + type: "HEAD", + async: false, + error: function(jqXHR, textStatus, errorThrown) { + if (jqXHR.status == 404) { + // everything allright -> user entered a new interface + $.ajax({ + url: urls.ifacesURL, + async: false, + type: "POST", + data: JSON.stringify({name: iface}), + contentType: "application/json" + }).done(function (result) { + vShowSuccess("Sucessfully created interface"); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not create interface", jqXHR, errorThrown); + }); + } else { + vShowAJAXError("Could not check for interface existance", jqXHR, errorThrown); + } + } + }); + + var url = urls.ifaceURL + "exportedoperations/?select2"; + require("winery-support-common").fetchSelect2DataAndInitSelect2("operation", url, function(){ + updateTarget(); + }, true); + } + + $("#operation").on("change", function() { + var operation = $("#operation").select2("val"); + var urls = getOperationsAndOperationURLs(); + $.ajax({ + url: urls.operationURL, + type: "HEAD", + async: false, + error: function(jqXHR, textStatus, errorThrown) { + if (jqXHR.status == 404) { + // everything allright -> user entered a new operation + $.ajax({ + url: urls.operationsURL, + async: false, + type: "POST", + data: JSON.stringify({name: operation}), + contentType: "application/json" + }).done(function (result) { + vShowSuccess("Sucessfully created operation"); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not create interface", jqXHR, errorThrown); + }); + } else { + vShowAJAXError("Could not check for interface operation", jqXHR, errorThrown); + } + } + }); + + updateTarget(); + }) + + /** + * Updates the content at "Target": Reference and Target Interface/Operation + */ + function updateTarget() { + var operation = $("#operation").select2("val"); + if (operation != "") { + var urls = getOperationsAndOperationURLs(); + // At the beginning of the usage, there is no operation selected + // Just fill the data if an operation is chosen + var url = urls.operationURL; + + // store URL for later use - this avoids global JavaScript variables + $("#operation").data("url", url); + + $.ajax({ + url: url, + dataType: "json" + }).done(function (data) { + if ((data.type == "NodeOperation") || (data.type == "RelationshipOperation")) { + if (data.type == "NodeOperation") { + $("#nodeRadio").prop("checked", true); + $("#nodeTemplateRefForOperation").val(data.ref); + updateTargetInterfaceAndOperation(true, data.interfacename, data.operationname); + } else { + $("#relationshipRadio").prop("checked", true); + $("#relationshipTemplateRefForOperation").val(data.ref); + updateTargetInterfaceAndOperation(false, data.interfacename, data.operationname); + } + } else if (data.type == "Plan") { + $("#planRadio").prop("checked", true); + $("#planRefForOperation").editable("setValue", data.ref); + } else if (data.type == null) { + // nothing set yet; set node as type + putType("NodeOperation"); + $("#nodeRadio").prop("checked", true); + // no reference is set if no type is set -> clear field + $("#nodeTemplateRefForOperation").val(""); + } else { + vShowError("Unexpected type '" + data.type + "'."); + return; + } + adaptVisibilityOfDivsAccordingToReferenceType(); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch data of exported operation from " + url, jqXHR, errorThrown); + }); + } + + } + + function adaptVisibilityOfDivsAccordingToReferenceType() { + var checked = $('input[name=reftargettype]:checked').val(); + if (checked == "node") { + $("#selectNodeTemplateDiv").show(); + $("#selectRelationshipTemplateDiv").hide(); + $("#selectPlanDiv").hide(); + $("#selectInterfaceNameDiv").show(); + $("#selectOperationNameDiv").show(); + $("#notApplicableDiv").hide(); + } else if (checked == "relationship") { + $("#selectNodeTemplateDiv").hide(); + $("#selectRelationshipTemplateDiv").show(); + $("#selectPlanDiv").hide(); + $("#selectInterfaceNameDiv").show(); + $("#selectOperationNameDiv").show(); + $("#notApplicableDiv").hide(); + } else if (checked == "plan") { + $("#selectNodeTemplateDiv").hide(); + $("#selectRelationshipTemplateDiv").hide(); + $("#selectPlanDiv").show(); + $("#selectInterfaceNameDiv").hide(); + $("#selectOperationNameDiv").hide(); + $("#notApplicableDiv").show(); + } else { + vShowError("UI in inconsistent state: wrong branch in adaptVisibilityOfDivsAccordingToReferenceType"); + } + } + </script> + + <div class="tab-pane" id="xml"> + <o:orioneditorarea areaid="XML" url="boundarydefinitions/" reloadAfterSuccess="true">${it.boundaryDefinitionsAsXMLStringEncoded}</o:orioneditorarea> + </div> +</div> +</div> + +<script> +$('#myTab a').click(function (e) { + e.preventDefault(); + $(this).tab('show'); +}); + +function openPropertyConstraintEditor() { + vShowError("not yet implemented"); + // TODO: fill diag with the values of the table + // $('#addPropertyConstraintDiag').modal('show'); +} + + +var propertyConstraintsTableInfo = { + id: '#propertyconstraintstable' +}; +var requirementsTableInfo = { + id: '#requirementstable' +}; +var capabilitiesTableInfo = { + id: '#capabilitiestable' +}; +var interfacesTableInfo = { + id: '#interfacestable' +}; +var propertyMappingsTableInfo = { + id: '#propertyMappingsTable' + }; + +require(["winery-support"], function(ws) { + var firstColumnIsHidden = { + aoColumnDefs: [ + { "bSearchable": false, "bVisible": false, "aTargets": [ 0 ] } + ] + }; + + ws.initTable(propertyConstraintsTableInfo, firstColumnIsHidden); + ws.initTable(requirementsTableInfo, firstColumnIsHidden); + ws.initTable(capabilitiesTableInfo, firstColumnIsHidden); + + ws.initTable(interfacesTableInfo); + ws.initTable(propertyMappingsTableInfo); +}); + +<%-- === BEGIN: Property Constraints === --%> + +function openUpdatePropertyConstraintDiag() { + if (propertyConstraintsTableInfo.selectedRow) { + require(["winery-support"], function(ws) { + if (ws.isEmptyTable(propertyConstraintsTableInfo)) { + vShowError("No property constraints available"); + return; + } + + $("#addPropertyConstraint").hide(); + $("#updatePropertyConstraint").show(); + + // put value in fields + var children = $(propertyMappingsTableInfo.selectedRow).children("td"); + $("#serviceTemplatePropertyRefForConstraint").val($(children[1]).text()); + $("#constraintType").val($(children[2]).text()); + // TODO: value of the constraint + + $('#propertyConstraintDiag').modal('show'); + + vShowError("Not yet implemented."); + }); + } else { + vShowError("No property constraint selected"); + } +} + +function openAddPropertyConstraintDiag() { + $("#addPropertyConstraint").show(); + $("#updatePropertyConstraint").hide(); + + // reset all fields + $("#serviceTemplatePropertyRefForConstraint").val(""); + // TODO: value of the constraint + + $('#propertyConstraintDiag').modal('show'); + + vShowError("Not yet implemented."); +} + +<%-- === END: Property Constraints === --%> + + +<%-- === BEGIN: Property Mapping === --%> + +function openUpdatePropertyMappingDiag() { + if (propertyMappingsTableInfo.selectedRow) { + require(["winery-support"], function(ws) { + if (ws.isEmptyTable(propertyMappingsTableInfo)) { + vShowError("No property mappings available"); + return; + } + + $("#addPropertyMapping").hide(); + $("#updatePropertyMapping").show(); + + // put value in fields + var children = $(propertyMappingsTableInfo.selectedRow).children("td"); + $("#serviceTemplatePropertyRef").val($(children[0]).text()); + $("#targetObjectRef").val($(children[1]).text()); + $("#targetPropertyRef").val($(children[2]).text()); + + $('#propertyMappingDiag').modal('show'); + }); + } else { + vShowError("No property mapping selected"); + } +} + +function openAddPropertyMappingDiag() { + $("#addPropertyMapping").show(); + $("#updatePropertyMapping").hide(); + + // reset all fields + $("#serviceTemplatePropertyRef").val(""); + $("#targetObjectRef").val(""); + $("#targetPropertyRef").val(""); + + $('#propertyMappingDiag').modal('show'); +} + +function addOrUpdatePropertyMapping(add) { + var serviceTemplatePropertyRef = $("#serviceTemplatePropertyRef").val(); + var targetObjectRef = $("#targetObjectRef").val(); + var targetPropertyRef = $("#targetPropertyRef").val(); + + $.ajax({ + url: "boundarydefinitions/propertymappings", + type: "POST", + async: false, + data: { + serviceTemplatePropertyRef: serviceTemplatePropertyRef, + targetObjectRef: targetObjectRef, + targetPropertyRef: targetPropertyRef + }, + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not POST property mapping", jqXHR, errorThrown); + }, + success: function(data, textSTatus, jqXHR) { + // put value from fields into table + if (add) { + propertyMappingsTableInfo.table.fnAddData([serviceTemplatePropertyRef, targetObjectRef, targetPropertyRef]); + } else { + var children = $(propertyMappingsTableInfo.selectedRow).children("td"); + $(children[0]).text(serviceTemplatePropertyRef); + $(children[1]).text(targetObjectRef); + $(children[2]).text(targetPropertyRef); + } + + $('#propertyMappingDiag').modal('hide'); + + vShowSuccess("Successfully posted property mapping."); + } + }); +} + +function addPropertyMapping() { + addOrUpdatePropertyMapping(true); +} + +function updatePropertyMapping() { + addOrUpdatePropertyMapping(false); +} + +<%-- === END: Property Mapping === --%> + + +//window.addEventListener('message', function(event){var v = document.getElementById('%s');if(v){v=v.firstChild; if(v && v.contentWindow === event.source){%s}}}) +window.addEventListener('message', function(event) { + if (event.data) { + if (event.data.targetObjectRef) { + // current API expects both fields + $(".newObjectRef").val(event.data.targetObjectRef); + $("#newObjectPropertyRef").val(event.data.targetPropertyRef); + } else if (event.data.reqRef) { + $("#ReqReferenceField").val(event.data.reqRef); + } else if (event.data.capRef) { + $("#CapReferenceField").val(event.data.capRef); + } else if (event.data.targetRelationshipTemplateRef) { + $("#RelationshipTemplateReferenceField").val(event.data.targetRelationshipTemplateRef); + } + } +}); + +function storeNewReference(ref) { + var url = $("#operation").data("url") + "/ref"; + $.ajax({ + url: url, + data: ref, + type: "PUT", + contentType: "text/plain", + }).done(function (result) { + vShowSuccess("Sucessfully saved reference"); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not set reference", jqXHR, errorThrown); + }); +} + +<c:if test="${not empty it.listOfAllPlans}"> +$("#planRefForOperation").editable({ + type: "select", + source: [ + <c:forEach var="item" items="${it.listOfAllPlans}"> + {value: "${item.id}", + text: "${item.text}"}, + </c:forEach> + ] +}).on("save", function(e, params) { + var newRef = params.newValue; + storeNewReference(newRef) +}); +</c:if> + +function putType(type) { + var url = $("#operation").data("url") + "/type"; + $.ajax({ + url: url, + data: type, + type: "PUT", + contentType: "text/plain", + }).done(function (result) { + vShowSuccess("Sucessfully changed reference type"); + adaptVisibilityOfDivsAccordingToReferenceType(); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not set new reference type", jqXHR, errorThrown); + }); +} + +function getInterfaceDataFromURL(ifaceURL) { + var select2data = null; + $.ajax({ + url: ifaceURL + "?select2", + async: false, + type: "GET", + dataType: "json", + success: function (data) { + select2data = data; + }, + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not get interface data", jqXHR, errorThrown); + } + }); + return select2data; +} + +function getDataForUpdateTargetOperation(url, showError) { + var select2data = null; + $.ajax({ + url: url + "?select2", + async: false, + type: "GET", + dataType: "json", + success: function (data) { + select2data = data; + }, + error: function(jqXHR, textStatus, errorThrown) { + if (showError) { + vShowAJAXError("Could not get operation data", jqXHR, errorThrown); + } + } + }); + return select2data; +} + +function updateTargetOperation(operationNameToSelect) { + var ifaceURL = $("#TargetInterface").data("url2"); + var select2data = null; + var operationsURL; + + // we don't store the interface-URL at #TargetInterface, but do a quick hack here + if (ifaceURL != null) { + operationsURL = ifaceURL + "/" + encodeID($("#TargetInterface").val()) + "/operations/"; + select2data = getDataForUpdateTargetOperation(operationsURL, false); + } + + // either only one URL or nothing found at second URL --> try first URL + if (select2data == null) { + ifaceURL = $("#TargetInterface").data("url1"); + operationsURL = ifaceURL + "/" + encodeID($("#TargetInterface").val()) + "/operations/"; + select2data = getDataForUpdateTargetOperation(operationsURL, true); + } + + if (select2data != null) { + $("#TargetOperation").select2({ + data:select2data + }); + var valueToSelect = null; + if ((typeof operationNameToSelect !== "undefined") && (operationNameToSelect != null)) { + valueToSelect = operationNameToSelect; + } else { + // called without existing data --> insert pseudo data and store it at the backend to ensure consistency + if (select2data.length > 0) { + valueToSelect = select2data[0].id; + storeTargetOperation(valueToSelect); + } + } + if (valueToSelect != null) { + $("#TargetOperation").select2('val', valueToSelect); + } + } + +} + +function updateTargetInterfaceAndOperationFromInterfaceURL(ifaceURL, interfaceNameToSelect, operationNameToSelect) { + var select2data; + if (typeof ifaceURL === "string") { + select2data = getInterfaceDataFromURL(ifaceURL); + $("#TargetInterface").data("url1", ifaceURL); + $("#TargetInterface").data("url2", null); + } else { + // TODO: instead of hacking with two urls (especially at other places in the code), we should prefix the entries with S| at the source interface and T| at the target interface + select2data = getInterfaceDataFromURL(ifaceURL[0]); + var select2data2 = getInterfaceDataFromURL(ifaceURL[1]); + $.merge(select2data, select2data2); + $("#TargetInterface").data("url1", ifaceURL[0]); + $("#TargetInterface").data("url2", ifaceURL[1]); + } + $("#TargetInterface").select2({data:select2data}); + + var valueToSelect = null; + if ((typeof interfaceNameToSelect !== "undefined") && (interfaceNameToSelect != null)) { + valueToSelect = interfaceNameToSelect; + } else { + // called without existing data --> insert pseudo data and store it at the backend to ensure consistency + if (select2data.length > 0) { + valueToSelect = select2data[0].id; + storeTargetInterface(valueToSelect); + } + } + if (valueToSelect != null) { + $("#TargetInterface").select2('val', valueToSelect); + } + + updateTargetOperation(operationNameToSelect); +} + +function updateTargetInterfaceAndOperation(isNodeTemplate, interfaceNameToSelect, operationNameToSelect) { + var url = "topologytemplate/"; + url = url + (isNodeTemplate ? "nodetemplates" : "relationshiptemplates" + "/"); + var templateId = isNodeTemplate ? $("#nodeTemplateRefForOperation").val() : $("#relationshipTemplateRefForOperation").val(); + if (templateId == "") { + // if no template is provided, we just return + return; + } + url = url + "/" + templateId + "/type"; + $.ajax({ + url: url, + type: "GET", + dataType: "text" + }).done(function (typeQName) { + require(["winery-support-common"], function(wsc) { + var urlDetermination = isNodeTemplate ? wsc.makeNodeTypeURLFromQName : wsc.makeRelationshipTypeURLFromQName; + var typeURL = urlDetermination("${it.repositoryURL}", typeQName) + if (isNodeTemplate) { + updateTargetInterfaceAndOperationFromInterfaceURL(typeURL + "/interfaces", interfaceNameToSelect, operationNameToSelect); + } else { + updateTargetInterfaceAndOperationFromInterfaceURL([typeURL + "/sourceinterfaces/", typeURL + "/targetinterfaces/"], interfaceNameToSelect, operationNameToSelect); + } + }); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not get type of node / relationship", jqXHR, errorThrown); + }); + +} + +$("#nodeRadio").on("change", function() { + putType("NodeOperation"); + updateTargetInterfaceAndOperation(true); +}); +$("#relationshipRadio").on("change", function() { + putType("RelationshipOperation"); + updateTargetInterfaceAndOperation(false); +}); +$("#planRadio").on("change", function() { + putType("Plan"); +}); + +$("#nodeTemplateRefForOperation").on("change", function() { + updateTargetInterfaceAndOperation(true); +}); + +$("#relationshipTemplateRefForOperation").on("change", function() { + updateTargetInterfaceAndOperation(false); +}); + +function storeTargetInterface(val) { + val = val || $("#TargetInterface").select2("val"); + var url = $("#operation").data("url") + "interfacename"; + // when selecting a new operation, both targetinterface and targetoperation are updated; this leads to race conditions at the backend and one chang would be lost. Therefore, we do the calls synchronously + $.ajax({ + url: url, + data: val, + type: "PUT", + contentType: "text/plain", + async:false + }).done(function (result) { + vShowSuccess("Sucessfully saved interface name"); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not set interface name", jqXHR, errorThrown); + }); +} + +function storeTargetOperation(val) { + val = val || $("#TargetOperation").select2("val"); + var url = $("#operation").data("url") + "operationname"; + // when selecting a new operation, both targetinterface and targetoperation are updated; this leads to race conditions at the backend and one chang would be lost. Therefore, we do the calls synchronously + $.ajax({ + url: url, + data: val, + type: "PUT", + contentType: "text/plain", + async:false + }).done(function (result) { + vShowSuccess("Sucessfully saved operation name"); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not set operation name", jqXHR, errorThrown); + }); +} + +$("#TargetInterface").on("change", function() { + storeTargetInterface(); + updateTargetOperation(); +}); + +$("#TargetOperation").on("change", function() { + storeTargetOperation(); +}); + +function deleteCurrentlySelectedInterface() { + vConfirmYesNo("Do you really want to delete this interface?", function() { + var url = getInterfacesAndInterfaceURLs().ifaceURL; + $.ajax({ + url: url, + type: "DELETE" + }).done(function () { + require(["winery-support-common"], function (wsc) { + wsc.removeItemFromSelect2Field($("#interface"), $("#interface").select2("data").id); + vShowSuccess("Successfully deleted interface"); + }); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not delete interface", jqXHR, errorThrown); + }); + }); +} + +function deleteCurrentlySelectedOperation() { + vConfirmYesNo("Do you really want to delete this operation?", function() { + var url = getOperationsAndOperationURLs().operationURL; + $.ajax({ + url: url, + type: "DELETE" + }).done(function () { + require(["winery-support-common"], function (wsc) { + wsc.removeItemFromSelect2Field($("#operation"), $("#operation").select2("data").id); + vShowSuccess("Successfully deleted operation"); + }); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not delete operation", jqXHR, errorThrown); + }); + }); +} + +</script> diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp new file mode 100644 index 0000000..ca50be4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp @@ -0,0 +1,266 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<script> + +var embeddedPlansTableInfo = { + id: '#embeddedPlansTable' +}; + +var linkedPlansTableInfo = { + id: '#linkedPlansTable' +}; + +$(function() { + require(["winery-support"], function(ws) { + ws.initTable(embeddedPlansTableInfo, { + "aoColumns": [ + { "bVisible": false, "bSearchable": false}, // ID column + { "sTitle": "Precondition" }, + { "sTitle": "Name" }, + { "sTitle": "Type" }, + { "sTitle": "Language" } + ], + "aaData" : ${it.embeddedPlansTableData} + }); + + ws.initTable(linkedPlansTableInfo, { + "aoColumns": [ + { "bVisible": false, "bSearchable": false}, // ID column + { "sTitle": "Precondition" }, + { "sTitle": "Name" }, + { "sTitle": "Type" }, + { "sTitle": "Language" }, + { "sTitle": "Reference" } + ], + "aaData" : ${it.linkedPlansTableData} + }); + }); +}); + +function editIOParameters() { + if (embeddedPlansTableInfo.selectedRow) { + require(["winery-support"], function(ws) { + if (ws.isEmptyTable(embeddedPlansTableInfo)) { + vShowError("No plans available"); + return; + } + updateInputAndOutputParameters(getPlanURL()); + $("#editParametersDiag").modal("show"); + }); + } else { + vShowError("No plan selected"); + } +} + function createPlan(data) { + if (highlightRequiredFields()) { + vShowError("Please fill out all required fields"); + return; + } + data.submit(); + } + + function getPlanURL() { + var id = embeddedPlansTableInfo.table.fnGetData(embeddedPlansTableInfo.selectedRow, 0); + return "plans/" + encodeURIComponent(id) + "/"; + } + + function openPlanEditor() { + if (embeddedPlansTableInfo.selectedRow) { + var isEmptyTable = embeddedPlansTableInfo.table.children("tbody").children("tr").first().children("td").hasClass("dataTables_empty"); + if (isEmptyTable) { + vShowError("No plans available"); + return; + } + window.open(getPlanURL() + "?edit", "_blank"); + } else { + vShowError("No plan selected"); + } + } + + function letUserChooseAPlan() { + $('#planFileInput').trigger('click'); + $('#planChooseBtn').focus(); + } + + requirejs(["jquery.fileupload"], function(){ + $('#addPlanForm').fileupload().bind("fileuploadadd", function(e, data) { + $.each(data.files, function (index, file) { + $("#planFileText").val(file.name); + }); + $("#addPlanBtnFUP").off("click"); + $("#addPlanBtnFUP").on("click", function() { + createPlan(data); + }); + }).bind("fileuploadstart", function(e) { + $("#addPlanBtnFUP").button("loading"); + }).bind('fileuploadfail', function(e, data) { + vShowAJAXError("Could not add plan", data.jqXHR, data.errorThrown); + $("#addPlanBtnFUP").button("reset"); + }).bind('fileuploaddone', function(e, data) { + vShowSuccess("Plan created successfully"); + + // reset the add button + $("#addPlanBtnFUP").button("reset"); + // do not allow submission of the old files on a click if the dialog is opened another time + $("#addPlanBtnFUP").off("click"); + + // TODO: if id is already present in table, delete row in table + + embeddedPlansTableInfo.table.fnAddData(data.result.tableData); + + $('#addPlanDiag').modal('hide'); + }); + }); +</script> + +<div class="modal fade" id="addPlanDiag"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title">Add Plan</h4> + </div> + <div class="modal-body"> + <form id="addPlanForm" enctype="multipart/form-data" action="plans/" method="post"> + <div class="form-group"> + <label class="control-label">Name</label> + <input name="planName" id="planName" type="text" class="form-control" required="required"> + </div> + + <t:typeswithshortnameasselect label="Type" type="plantype" selectname="planType" typesWithShortNames="${it.planTypes}"> + </t:typeswithshortnameasselect> + + <t:typeswithshortnameasselect label="Language" type="planlanguage" selectname="planLanguage" typesWithShortNames="${it.planLanguages}"> + </t:typeswithshortnameasselect> + + <div class="form-group" id="fileDiv"> + <label class="control-label" for="planFileDiv">Archive</label> + <div style="display: block; width: 100%" id="planFileDiv"> + <input id="planFileInput" name="file" type="file" style="display:none"> + <input name="fileText" id="planFileText" type="text" class="form-control" style="width:300px; display:inline;" onclick="letUserChooseAPlan();" required="required"> + <button type="button" id="planChooseBtn" class="btn btn-default btn-xs" onclick="letUserChooseAPlan();">Choose</button> + </div> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-primary" data-loading-text="Uploading..." id="addPlanBtnFUP">Add</button> + <button type="button" class="btn btn-primary" style="display:none;" id="addPlanBtnBPMN4TOSCA">Add</button> + </div> + </div> + </div> +</div> + +<script> +$("#planLanguage").on("change", function(e) { + var lang = $("#planLanguage").val(); + if (lang == "http://www.opentosca.org/bpmn4tosca") { + $("#fileDiv").hide(); + $("#addPlanBtnFUP").hide(); + $("#addPlanBtnBPMN4TOSCA").show(); + } else { + $("#fileDiv").show(); + $("#addPlanBtnFUP").show(); + $("#addPlanBtnBPMN4TOSCA").hide(); + } +}); + +$("#addPlanBtnBPMN4TOSCA").on("click", function() { + var data = new FormData(); + data.append("planName", $("#planName").val()); + data.append("planType", $("#planType").val()); + data.append("planLanguage", $("#planLanguage").val()); + + $.ajax({ + url: "plans/", + type: "POST", + async: false, + contentType: false, // jQuery automatically sets multipart/form-data; boundary=... + data: data, + processData: false, + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not add BPMN4TOSCSA plan", jqXHR, errorThrown); + }, + success: function(data, textStatus, jqXHR) { + //typesTableInfo.table.fnAddData([$('#shortname').val(), $('#type').val()]); + $('#addPlanDiag').modal('hide'); + vShowSuccess("Successfully added plan. Please refresh the page."); + } + }); + +}); +</script> + +<p:parametersJS></p:parametersJS> + +<div class="modal fade" id="editParametersDiag"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title">Edit Parameters</h4> + </div> + <div class="modal-body"> + <p:parametersInput baseURL="getPlanURL()"></p:parametersInput> + <p:parametersOutput baseURL="getPlanURL()"></p:parametersOutput> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> +</div> + + <div id="managementPlans"> + <h4>Embedded Plans</h4> + <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(embeddedPlansTableInfo, 'Plan', 'plans/', 0, 2);">Remove</button> + <button class="rightbutton btn btn-xs btn-info" onclick="$('#addPlanDiag').modal('show');">Add</button> + <button class="rightbutton btn btn-xs btn-default" onclick="editIOParameters();">I/O Parameters</button> + <button class="rightbutton btn btn-xs btn-primary" onclick="openPlanEditor();">Edit</button> +<% +if (org.eclipse.winery.repository.Prefs.INSTANCE.isPlanBuilderAvailable()) { +%> + <script> + function generateBuildPlan() { + $("#btnGenerateBuildPlan").button('loading'); + $.ajax({ + url: 'topologytemplate/', + // targeting method triggerGenerateBuildPlan in TopologyTemplateResource.java + dataType: "text" + }).fail(function(jqXHR, textStatus, errorThrown) { + $("#btnGenerateBuildPlan").button('reset'); + vShowAJAXError("Could not trigger plan generation.", jqXHR, errorThrown); + }).done(function(data, textStatus, jqXHR) { + $("#btnGenerateBuildPlan").button('reset'); + var resultText = "Successfully generated build plan. Please refresh the page."; + vShowSuccess(resultText); + }); + } + </script> + <button id="btnGenerateBuildPlan" class="btn btn-xs btn-default" data-loading-text="Generating..." onclick="generateBuildPlan();">Generate Build Plan</button> +<% +} +%> + <table cellpadding="0" cellspacing="0" border="0" class="display" id="embeddedPlansTable"></table> + + <br /><br /> + <h4>Linked Plans</h4> + <table cellpadding="0" cellspacing="0" border="0" class="display" id="linkedPlansTable"></table> + </div> diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp new file mode 100644 index 0000000..d4d9233 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp @@ -0,0 +1,256 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%-- Upload functionality inspired by plans.jsp. That code could be generalized somehow in a .tag file --%> + +<ul class="nav nav-tabs" id="myTab"> + <li class="active"><a href="#description">Description</a></li> + <li><a href="#images">Images</a></li> + <li><a href="#options">Options</a></li> + <li><a href="#xml" id="showXMLTab">XML</a></li> +</ul> + +<div class="tab-content"> + + <div class="tab-pane active" id="description"> + <div class="form-group"> + <label class="label-form">Name</label> + <a href="#" class="form-control" data-send="always" id="displayName" data-url="selfserviceportal/displayname" data-tile="Enter Display Name">${it.application.displayName}</a> + </div> + + <div class="form-group"> + <label class="label-form">Description</label> + <div class="form-control" id="applicationDescriptionDiv">${it.application.description}</div> + </div> + </div> + + <div class="tab-pane" id="images"> + + <t:imageUpload + label="Icon" + URL="selfserviceportal/icon.jpg" + id="upIcon" + width="16px" + accept="image/*"/> + + <t:imageUpload + label="Preview" + URL="selfserviceportal/image.jpg" + id="upImage" + width="100px" + accept="image/*"/> + + </div> + + <div class="tab-pane" id="options"> + <button class="rightbutton btn btn-xs btn-danger" name="remove" onclick="deleteOnServerAndInTable(optionsTableInfo, 'Option', 'selfserviceportal/options/', 0, 1);">Remove</button> + <button class="rightbutton btn btn-xs btn-info" name="add" onclick="$('#addOptionDiag').modal('show');">Add</button> + <!-- <button class="rightbutton btn btn-xs btn-default" name="edit" onclick="openOptionEditor();">Edit</button> --> + + <table id="optionsTable"> + <thead> + <tr> + <th>Id</th> + <th>Name</th> + <th>Icon</th> + <th>Plan Service Name</th> + </tr> + </thead> + <tbody> + <c:if test="${not empty it.application}"> + <c:forEach var="option" items="${it.application.options.option}"> + <tr> + <td>${option.id}</td> + <td>${option.name}</td> + <td><img src="selfserviceportal/options/${w:URLencode(option.id)}/icon.jpg" style="width:50px;"></td> + <td>${option.planServiceName}</td> + </tr> + </c:forEach> + </c:if> + </tbody> + </table> + </div> + + <div class="tab-pane" id="xml"> + <o:orioneditorarea areaid="XML" url="selfserviceportal/" reloadAfterSuccess="true">${it.applicationAsXMLStringEncoded}</o:orioneditorarea> + </div> + +</div> + +<script> +function letUserChooseAFile() { + $('#fileInput').trigger('click'); + $('#chooseBtn').focus(); +} + +$('#showXMLTab').on('shown.bs.tab', function (e) { + window.winery.orionareas['XML'].fixEditorHeight(); +}); +</script> + +<div class="modal fade" id="addOptionDiag"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title">Add Option</h4> + </div> + <div class="modal-body"> + <form id="addOptionForm" enctype="multipart/form-data" action="selfserviceportal/options/" method="post"> + <div class="form-group"> + <label class="control-label">Name</label> + <input name="name" type="text" class="form-control" required="required"> + </div> + + <div class="form-group"> + <label class="control-label">Description</label> + <textarea id="optionDescription" name="description" class="form-control" required="required"></textarea> + </div> + + <div class="form-group"> + <label class="control-label" for="fileDiv">Icon</label> + <div style="display: block; width: 100%" id="iconDiv"> + <input id="fileInput" name="file" type="file" style="display:none" accept="image/*"> + <input name="fileText" id="fileText" type="text" class="form-control" style="width:300px; display:inline;" onclick="letUserChooseAFile();" required="required"> + <button type="button" id="chooseBtn" class="btn btn-default btn-xs" onclick="letUserChooseAFile();">Choose</button> + </div> + </div> + + <div class="form-group"> + <label class="control-label">Plan Service Name</label> + <input name="planServiceName" type="text" class="form-control" required="required"> + </div> + + <div class="form-group"> + <label class="control-label">Plan Input Message</label> + <textarea name="planInputMessage" class="form-control" required="required" rows="20"><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> +<soapenv:Header/> +<soapenv:Body> +</soapenv:Body> +</soapenv:Envelope></textarea> + </div> + + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-primary" data-loading-text="Uploading..." id="addOptionBtn">Add</button> + </div> + </div> + </div> +</div> + + +<script> +$("#displayName").editable({ + ajaxOptions: {type: "PUT"}, + success: function() { + vShowSuccess("Successfully updated display name"); + }, + error: function(response) { + vShowError("Could not update display name: " + response.status + " " + response.responseText); + } +}); + +$("#applicationDescriptionDiv").editable({ + type: "wysihtml5", + send: "always", + url: "selfserviceportal/description", + ajaxOptions: {type: "PUT"}, + success: function() { + vShowSuccess("Successfully updated description"); + }, + error: function(response) { + vShowError("Could not update description: " + response.status + " " + response.responseText); + } +}); + +$("#optionDescription").wysihtml5(); + +var optionsTableInfo = { + id: '#optionsTable' +}; + +$('#myTab a').click(function (e) { + e.preventDefault(); + $(this).tab('show'); +}); + +$(function() { + // initialize table and hide first column + require(["winery-support"], function(ws) { + ws.initTable(optionsTableInfo, { + "aoColumnDefs": [ + { "bSearchable": false, "bVisible": false, "aTargets": [ 0 ] } + ] + }); + }); + + $("#addOptionDiag").on("hidden.bs.modal", function() { + // we currently do not send data back from the server + // we emulate the AJAX refresh by a reaload + doTheTabSelection(function() { + $('#myTab a[href="#options"]').tab('show'); + }); + }); +}); + +function createOption(data) { + if (highlightRequiredFields()) { + vShowError("Please fill out all required fields"); + return; + } + data.submit(); +} + +requirejs(["jquery.fileupload"], function(){ + $('#addOptionForm').fileupload({ + // dropping should only be available in the addOptionDialog. This, however, does not work correctly + dropZone: $("#addOptionDiag") + }).bind("fileuploadadd", function(e, data) { + $.each(data.files, function (index, file) { + $("#fileText").val(file.name); + }); + $("#addOptionBtn").off("click"); + $("#addOptionBtn").on("click", function() { + createOption(data); + }); + }).bind("fileuploadstart", function(e) { + $("#addOptionBtn").button("loading"); + }).bind('fileuploadfail', function(e, data) { + vShowAJAXError("Could not add option", data.jqXHR, data.errorThrown); + $("#addOptionBtn").button("reset"); + }).bind('fileuploaddone', function(e, data) { + vShowSuccess("Option created successfully."); + + // reset the add button + $("#addOptionBtn").button("reset"); + // do not allow submission of the old files on a click if the dialog is opened another time + $("#addOptionBtn").off("click"); + + // TODO: add data + //embeddedPlansTableInfo.table.fnAddData(data.result.tableData); + // current workaround: event on hidden.bs.modal + + $('#addOptionDiag').modal('hide'); + }); +}); + +</script> diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp new file mode 100644 index 0000000..b5349d6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp @@ -0,0 +1,43 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013, 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%-- add submenus after the submenus defined for the type --%> +<% +java.util.List<SubMenuData> subMenus = new java.util.ArrayList<SubMenuData>(5); + +SubMenuData data; + +data = new SubMenuData("#topologytemplate", "Topology Template"); +subMenus.add(data); + +data = new SubMenuData("#plans", "Plans"); +subMenus.add(data); + +data = new SubMenuData("#selfserviceportal", "Self-service Portal"); +subMenus.add(data); + +data = new SubMenuData("#boundarydefinitions", "Boundary Definitions"); +subMenus.add(data); + +//Tags are currently not implemented -> Don't confuse users by showing the tab +//has to be enabled again, when tags are implemented +//data = new SubMenuData("#tags", "Tags"); +//subMenus.add(data); +%> + +<t:componentinstance cssClass="serviceTemplate" selected="ServiceTemplate" subMenus="<%=subMenus%>"> +</t:componentinstance> diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp new file mode 100644 index 0000000..b5424ae --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp @@ -0,0 +1,23 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> + +<div> + <a class="btn btn-primary" id="newtab" style="cursor:pointer;" href="${it.location}" target="_blank" >Open Editor</a> + <a class="btn btn-info" href="topologytemplate/?view" target="_blank" >Open View</a> + <br> + <br> + <div id="loading" class="topologyTemplatePreviewSizing" style="position:absolute; background-color: white; z-index:5;">Loading preview...</div> + <iframe id="topologyTemplatePreview" class="topologyTemplatePreviewSizing" src="topologytemplate/?view=small" onload="$('#loading').hide(1000);"></iframe> +</div> diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp new file mode 100644 index 0000000..789c174 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp @@ -0,0 +1,67 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@page buffer="none" %> + +<%@page import="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@page import="org.eclipse.winery.repository.Prefs" %> +<%@page import="org.eclipse.winery.repository.client.WineryRepositoryClientFactory"%> +<%@page import="org.eclipse.winery.repository.client.IWineryRepositoryClient"%> +<%@page import="org.eclipse.winery.repository.client.WineryRepositoryClient"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<html> +<head> + <meta name="application-name" content="Winery" /> + <meta charset="UTF-8"> + <link rel="icon" href="${w:topologyModelerURI()}/favicon.png" type="image/png"> + + <link rel="stylesheet" href="${pageContext.request.contextPath}/components/bootstrap/dist/css/bootstrap.css" /> + <link rel="stylesheet" href="${pageContext.request.contextPath}/components/bootstrap/dist/css/bootstrap-theme.css" /> + + <script type='text/javascript' src='${pageContext.request.contextPath}/components/requirejs/require.js'></script> + + <!-- jquery and jquery UI have to be loaded using the old fashioned way to avoid incompatibilities with bootstrap v3 --> + <script type='text/javascript' src='${pageContext.request.contextPath}/components/jquery/jquery.js'></script> + <script type='text/javascript' src='${pageContext.request.contextPath}/3rdparty/jquery-ui/js/jquery-ui.js'></script> + <script type='text/javascript' src='${pageContext.request.contextPath}/components/bootstrap/dist/js/bootstrap.js'></script> + <script> + require.config({ + baseUrl: "${pageContext.request.contextPath}/js", + paths: { + "datatables": "../components/datatables/media/js/jquery.dataTables", + "jquery": "../components/jquery/jquery", + + // required for jsplumb + "jquery.ui": "../3rdparty/jquery-ui/js/jquery-ui", + + "jsplumb": "../components/jsPlumb/dist/js/jquery.jsPlumb-1.5.4", + + "winery-sugiyamaLayouter": "${w:topologyModelerURI()}/js/winery-sugiyamaLayouter" + } + }); + </script> + <c:if test="${not empty it.additionalScript}"> + <script type='text/javascript' src='${it.additionalScript}'></script> + </c:if> +</head> +<body> + +<t:topologyTemplateRenderer topology="${it.topologyTemplate}" repositoryURL="<%=Prefs.INSTANCE.getResourcePath()%>" client="${it.client}" fullscreen="true" additonalCSS="${it.additonalCSS}" autoLayoutOnLoad="${it.autoLayoutOnLoad}"/> + +</body> +</html> |