diff options
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates')
3 files changed, 574 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag new file mode 100644 index 0000000..238e34a --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag @@ -0,0 +1,147 @@ +<%-- +/******************************************************************************* + * 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: + * Uwe Breitenbücher - initial API and implementation and/or initial documentation + * Oliver Kopp - improvements to fit updated index.jsp + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> + +<%@tag language="java" pageEncoding="UTF-8" description="Renders the properies of one node tempate on the right"%> + +<%@attribute name="repositoryURL" required="true" type="java.lang.String" description="The repository URL"%> + +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %> + + +<link rel="stylesheet" href="css/propertiesview.css" /> + +<div id="NTPropertiesView" class="propertiesView" style="display: none;"> + + <div id="nodeTemplateInformationSection"> + <%-- + If this is layouted strangely, maybe a <form> wrapper has to be added + Be aware that nested buttons then trigger a submission of the form (-> ct:spinnerwithinphty) + --%> + <fieldset> + <div class="form-group"> + <label for="nodetemplateid">Id</label> + <input id="nodetemplateid" disabled="disabled" class="form-control"></input> + </div> + <div class="form-group"> + <label for="nodetemplatename" class="control-label">Name</label> + <input id="nodetemplatename" name="name" class="form-control"/> + </div> + <div class="form-group"> + <label for="nodetemplateType">Type</label> + <%-- filled by fillInformationSection --%> + <a id="nodetemplateType" target="_blank" href="#" class="form-control"></a> + </div> + <ct:spinnerwithinphty min="0" width="10" changedfunction="minInstancesChanged" label="min" id="minInstances" /> + <ct:spinnerwithinphty min="1" width="10" changedfunction="maxInstancesChanged" label="max" id="maxInstances" withinphty="true" /> + </fieldset> + </div> + +</div> + +<script> + function minInstancesChanged(event, ui) { + var val; + if (ui === undefined) { + val = $("#minInstances").val(); + } else { + val = ui.value; + } + ntMin.html(val); + } + + function maxInstancesChanged(event, ui) { + var val; + if (ui === undefined) { + val = $("#maxInstances").val(); + } else { + val = ui.value; + } + ntMax.html(val); + } + + // the name input field of the properties section + var nameInput = $("#nodetemplatename"); + + // the min/max fields of the currently selected node template + var ntMin; + var ntMax; + + function fillInformationSection(nodeTemplate) { + require(["winery-support-common"], function(wsc) { + // currently doesn't help for a delayed update + //informationSection.slideDown(); + + $("#nodetemplateid").val(nodeTemplate.attr("id")); + + var headerContainer = nodeTemplate.children("div.headerContainer"); + + // copy name + var nameField = headerContainer.children("div.name"); + var name = nameField.text(); + nameInput.val(name); + + // copy type + var typeQName = headerContainer.children("span.typeQName").text(); + var href = wsc.makeNodeTypeURLFromQName("${repositoryURL}", typeQName); + var type = headerContainer.children("div.type").text(); + $("#nodetemplateType").attr("href", href).text(type); + + // we could use jQuery-typing, but it is not possible to replace key events there + nameInput.off("keyup"); + nameInput.on("keyup", function() { + nameField.text($(this).val()); + }); + + // handling of min and max + ntMin = nodeTemplate.children(".headerContainer").children(".minMaxInstances").children(".minInstances"); + $("#minInstances").val(ntMin.text()); + ntMax = nodeTemplate.children(".headerContainer").children(".minMaxInstances").children(".maxInstances"); + $("#maxInstances").val(ntMax.text()); + }); + } + + function showViewOnTheRight() { + $("#NTPropertiesView").fadeIn(); + } + + function hideViewOnTheRight() { + $("#NTPropertiesView").fadeOut(); + } + +$(function() { + winery.events.register( + winery.events.name.SELECTION_CHANGED, + function() { + // min/max instances do not lost focus if other shape is clicked + // workaround + if ($("#minInstances").is(":focus")) { + minInstancesChanged(); + } + if ($("#maxInstances").is(":focus")) { + maxInstancesChanged(); + } + var nodeTemplate = $("div.NodeTemplateShape.selected"); + var numSelected = nodeTemplate.length; + if (numSelected == 1) { + fillInformationSection(nodeTemplate); + showViewOnTheRight(); + } else { + hideViewOnTheRight(); + } + } + ); +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag new file mode 100644 index 0000000..0ec6f5d --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag @@ -0,0 +1,248 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag description="Dialog to change a req or cap. Offers function showEditDiagFor${shortName}(id)" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="w" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> + +<%@attribute name="headerLabel" required="true"%> +<%@attribute name="shortName" required="true" description="Used for diag id, function name suffix, Req|Cap"%> +<%@attribute name="requirementOrCapability" required="true" description="requirement|capability"%> +<%@attribute name="cssClassPrefix" required="true"%> +<%@attribute name="allTypes" required="true" type="java.util.Collection" description="Collection<QName> of all available types" %> +<%@attribute name="clazz" required="true" type="java.lang.Class" description="TRequirement.class or TCapability.class" %> +<%@attribute name="repositoryURL" required="true" %> + +<div class="modal fade" id="AddOrUpdate${shortName}Diag"> + <div class="modal-dialog"> + <div class="modal-content" style="width:660px;"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><span id="headerAddOrUpdate"></span> ${headerLabel}</h4> + </div> + <div class="modal-body"> + <form id="add${shortName}Form" enctype="multipart/form-data"> + <fieldset> + <w:idInput inputFieldId="${shortName}Id"/> + + <div class="form-group"> + <label for="${shortName}NameChooser" class="control-label">Definition Name:</label> + <input id="${shortName}NameChooser" class="form-control" type="text" required="required" /> + </div> + + <div class="form-group"> + <label for="${shortName}TypeDisplay" class="control-label">${shortName} Type:</label> + <input id="${shortName}TypeDisplay" class="form-control" type="text" required="required" disabled="disabled"/> + </div> + + <div id="${shortName}PropertiesContainer"> + </div> + </fieldset> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <button type="button" id="add${shortName}btn" class="btn btn-primary" onclick="addOrUpdate${shortName}(false);">Add</button> + <button type="button" id="delete${shortName}btn" class="btn btn-danger" onclick="deleteCurrent${shortName}();">Delete</button> + <button type="button" id="update${shortName}btn" class="btn btn-primary" onclick="addOrUpdate${shortName}(true);">Change</button> + </div> + </div> + </div> +</div> + +<script> + +/* + * The following variables are declared twice due to double inclusion of this .tag flie + * Due to JavaScript magic, it works nevertheless + */ +var selectedNodeTemplateForReqCapAddition; + +//global variable set by editPropertiesXML and read by save${shortName}Edits +var nodeTemplateEditedReqOrCap; + + +function deleteCurrent${shortName}() { + nodeTemplateEditedReqOrCap.remove(); + $("#AddOrUpdate${shortName}Diag").modal("hide"); +} + +function update${shortName}PropertiesContainerWithClone(propertiesContainerToClone) { + var clone = propertiesContainerToClone.clone(); + $("#${shortName}PropertiesContainer").empty().append(clone); + clone.find(".KVPropertyValue").editable({mode: "inline"}); +} + +function update${shortName}PropertiesFromSelectedType() { + var data = $("#${shortName}NameChooser").select2("data"); + var name = data.text; + var type = data.id; + + // fill in type + // TODO: use qname2href and store QName in data-qname for later consumption -- possibly qname2href should always store the qname in data-qname + $("#${shortName}TypeDisplay").val(type); + + // fill in properties (derived from type) + var propertiesContainer= $(".skelettonPropertyEditorFor${shortName} > span:contains('" + type + "')").parent().children("div"); + update${shortName}PropertiesContainerWithClone(propertiesContainer); +} + +$("#${shortName}NameChooser").on("change", function(e) { + update${shortName}PropertiesFromSelectedType(); +}); + +/** + * Called when a req/cap should be added or updated + * Update mode is triggered if reqOrCapIdtoUpdate is given + * + * @param nodeTemplateId the node template id to add a req/cap to. undefined in update mode + * @param reqOrCapIdtoUpdate + */ +function showAddOrUpdateDiagFor${shortName}(nodeTemplateId, reqOrCapIdToUpdate) { + var update = (typeof reqOrCapIdToUpdate !== "undefined"); + + if (update) { + nodeTemplateEditedReqOrCap = $("#" + reqOrCapIdToUpdate); + // in update mode, nodeTemplateId is not provided, we have to search for the right shape + selectedNodeTemplateForReqCapAddition = nodeTemplateEditedReqOrCap.closest(".NodeTemplateShape"); + } else { + selectedNodeTemplateForReqCapAddition = $("#" + nodeTemplateId); + } + + require(["winery-support-common"], function(wsc) { + var typeQName = selectedNodeTemplateForReqCapAddition.children("div.headerContainer").children("span.typeQName").text(); + var urlFragment = wsc.getURLFragmentOutOfFullQName(typeQName); + var url = "${repositoryURL}/nodetypes/" + urlFragment + "/${requirementOrCapability}definitions/"; + $.ajax({ + url: url, + dataType: "json" + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch ${requirementOrCapability} definitions", jqXHR, errorThrown); + }).done(function(data) { + // now, we have all available requirement definitions + // we have to ask each of it for the type + // we use the type as key for the option and the name as displayed text + // select2 perfectly handles duplicate keys + + var select2Data = []; + + $.each(data, function(i,e) { + var rqDefURL = url + e + "/type"; + $.ajax({ + url: rqDefURL, + async: false, + dataType: "text" + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch type for " + e, jqXHR, errorThrown); + }).done(function(data) { + var item = { + id: data, + text: e + }; + select2Data.push(item); + }); + }); + + $("#${shortName}NameChooser").select2({ + placeholder: "Select name", + data: select2Data + }); + + if (update) { + $("#add${shortName}btn").hide(); + $("#update${shortName}btn").show(); + $("#delete${shortName}btn").show(); + $("#headerAddOrUpdate").text("Change"); + + // collect existing data in variables + var id = nodeTemplateEditedReqOrCap.children(".id").text(); + var name = nodeTemplateEditedReqOrCap.children(".name").text(); + var type = nodeTemplateEditedReqOrCap.children(".type").children("a").data("qname"); + var propertiesContainer = nodeTemplateEditedReqOrCap.children(".propertiesContainer"); + + // update displays + + // id + $("#${shortName}Id").val(id); + + // name + // we use the type as key at NameChooser. We hope that there are no duplicates. Otherwise, update won't work. + $("#${shortName}NameChooser").select2("val", type); + // make consistency check + var data = $("#${shortName}NameChooser").select2("data"); + if (data == null) { + vShowError("type " + type + " could not be selected.") + } else if (name != (data.text)) { + vShowError("There are two names for different types. That case is not handled in the UI."); + } + + // type + $("#${shortName}TypeDisplay").val(type); + + // properties + update${shortName}PropertiesContainerWithClone(propertiesContainer); + } else { + $("#add${shortName}btn").show(); + $("#update${shortName}btn").hide(); + $("#delete${shortName}btn").hide(); + $("#headerAddOrUpdate").text("Add"); + + // QUICK HACK if dialog has been shown before -> show properties of selected type + if ($("#${shortName}NameChooser").select2("data") != null) { + update${shortName}PropertiesFromSelectedType(); + } + } + + $("#AddOrUpdate${shortName}Diag").modal("show"); + }); + }); +} + +/** + * Called at click on button "Add" or "Change" + */ +function addOrUpdate${shortName}(update) { + if (highlightRequiredFields()) { + vShowError("Please fill in all required fields"); + return; + } + require(["tmpl"], function(tmpl) { + // Generate skeletton div + var sel2data = $("#${shortName}NameChooser").select2("data"); + var data = { + id: $("#${shortName}Id").val(), + name: sel2data.text, + type: sel2data.id + } + // tmpl-${shortName} is defined in reqsorcaps.tag + var div = tmpl("tmpl-${shortName}", data); + + // Add the div to the node template + if (update) { + nodeTemplateEditedReqOrCap.replaceWith(div); + } else { + selectedNodeTemplateForReqCapAddition.children(".${cssClassPrefix}Container").children(".content").children(".addnewreqorcap").before(div); + } + + // Put properties at the right place + $("#toBeReplacedByProperties").replaceWith($("#${shortName}PropertiesContainer").children()); + + $("#AddOrUpdate${shortName}Diag").modal("hide"); + }); +} + +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag new file mode 100644 index 0000000..8c63dca --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag @@ -0,0 +1,179 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag language="java" pageEncoding="UTF-8" description="Renders the properies of one relationship tempate on the right"%> + +<%@attribute name="relationshipTypes" required="true" type="java.util.Collection" %> +<%@attribute name="repositoryURL" required="true" type="java.lang.String" description="The repository URL"%> + +<link rel="stylesheet" href="css/propertiesview.css" /> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="props" tagdir="/WEB-INF/tags/common/templates" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions" %> + +<div id="RTPropertiesView" class="propertiesView" style="display: none;"> + + <div id="relationshipTemplateInformationSection"> + <fieldset> + <div class="form-group"> + <label for="relationshiptemplateid">Id</label> + <input id="relationshiptemplateid" disabled="disabled" class="form-control"></input> + </div> + <div class="form-group"> + <label for="relationshiptemplatename" class="control-label">Name</label> + <a href="#" id="relationshiptemplatename" data-title="Name" data-type="text" class="form-control"></a> + </div> + <div class="form-group"> + <label for="relationshipType">Type</label> + <%-- filled by showRTViewOnTheRight --%> + <a id="relationshipType" target="_blank" href="#" class="form-control"></a> + </div> + <div class="form-group"> + <label for="RTreq" class="control-label">Requirement</label> + <select id="RTreq" class="form-control"> + </select> + </div> + <div class="form-group"> + <label for="RTcap" class="control-label">Capability</label> + <select id="RTcap" class="form-control"> + </select> + </div> + </fieldset> + </div> + +</div> + +<script> + + var currentlySelectedConn = null; + + /** + * Fills the requirement and capabilities dropdowns with the available reqs and caps (which are defined at the source/target node template) + * + * @param conn the connection itself + * @param dataField = "req"|"cap" + * @param sourceDivClass = requirementsContainer | capabilitiesContainer + */ + function fillReqOrCap(conn, dataField, nodetemplateId, sourceDivClass, targetSelect) { + var nt = $("#" + nodetemplateId); + var reqsOrCaps = nt.children("." + sourceDivClass).children(".content").children(".reqorcap"); + var connReqCap = winery.connections[conn.id][dataField]; + + targetSelect.empty(); + + var optData = { + value: "__NONE__", + text: "(none)" + }; + if (!connReqCap) { + selected: true + } + require(["tmpl"], function(tmpl) { + var newOption = tmpl("tmpl-option", optData); + targetSelect.append(newOption); + + reqsOrCaps.each(function(i,e) { + optData.value = $(e).children(".id").children("span.id").text(); + optData.text = $(e).children(".name").children("span.name").text(); + optData.selected = (optData.value == connReqCap); + newOption = tmpl("tmpl-option", optData); + targetSelect.append(newOption); + }); + }); + + targetSelect.off("change"); + targetSelect.on("change", function(e) { + var val = targetSelect.val(); + if (val == "__NONE__") { + delete(winery.connections[conn.id][dataField]); + } else { + winery.connections[conn.id][dataField] = val; + } + }); + } + + function fillType(nsAndLocalName) { + require(["winery-support-common"], function(wsc) { + var href = wsc.makeRelationshipTypeURLFromNSAndLocalName("${repositoryURL}", nsAndLocalName); + // localname is always the name of the relationship type because the specification requires a "name" attribute only and does not foresee an "id" attribute + $("#relationshipType").attr("href", href).text(nsAndLocalName.localname); + }) + } + + function displayProperties(connData) { + $("#RTPropertiesView").append(connData.propertiesContainer); + } + + /** + * @param conn the jsPlumb connection + */ + function showRTViewOnTheRight(conn) { + currentlySelectedConn = conn; + + $("#RTPropertiesView").fadeIn(); + + $("#relationshiptemplateid").val(winery.connections[conn.id].id); + $("#relationshiptemplatename").editable('setValue', winery.connections[conn.id].name); + fillReqOrCap(conn, "req", conn.sourceId, "requirementsContainer", $("#RTreq")); + fillReqOrCap(conn, "cap", conn.targetId, "capabilitiesContainer", $("#RTcap")); + fillType(winery.connections[conn.id].nsAndLocalName); + displayProperties(winery.connections[conn.id]); + } + + function hideRTViewOnTheRight() { + if (currentlySelectedConn == null) { + // nothing to do if no relationship template is selected + return; + } + + $("#RTPropertiesView").fadeOut(); + + // user will see some flickering here, but we don't want to set timers -> could lead to race conditions + $("#skelettonContainerForRelationshipTemplates").append(winery.connections[currentlySelectedConn.id].propertiesContainer); + currentlySelectedConn = null; + } + + function storeUpdatedName(newName) { + currentlySelectedConn.name = newName; + } + + $(function() { + $("#relationshiptemplatename").editable({ + success: function(response, newValue) { + currentlySelectedConn.name = newValue; + } + }); + }); + + function unselectAllConnections() { + jsPlumb.select().each(function(connection) { + connection.removeType("selected"); + }); + } + + winery.events.register( + winery.events.name.SELECTION_CHANGED, + function() { + var nodeTemplate = $("div.NodeTemplateShape.selected"); + var numSelected = nodeTemplate.length; + if (numSelected != 0) { + // if node templates are selected, no RT properties should be shown + hideRTViewOnTheRight(); + + unselectAllConnections(); + } + } + ); + +</script> |