2 /*******************************************************************************
3 * Copyright (c) 2012-2014 University of Stuttgart.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * and the Apache License 2.0 which both accompany this distribution,
7 * and are available at http://www.eclipse.org/legal/epl-v10.html
8 * and http://www.apache.org/licenses/LICENSE-2.0
11 * Oliver Kopp - initial API and implementation and/or initial documentation
12 * Yves Schubert - switch to bootstrap 3, integration with spinnerwithinphty
13 *******************************************************************************/
15 <%@tag description="Models Requirement and Capability Definitions" pageEncoding="UTF-8"%>
17 <%@attribute name="labelForSingleItem" required="true" %>
18 <%@attribute name="url" required="true"%>
19 <%@attribute name="allSubResources" required="true" type="java.util.List" description="All available req-/cap-defs" %>
20 <%@attribute name="allTypes" required="true" type="java.util.Collection" description="All available types of req-/cap-def" %>
21 <%@attribute name="typeClass" required="true" type="java.lang.Class" description="The class of the type" %>
23 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
24 <%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %>
25 <%@taglib prefix="con" tagdir="/WEB-INF/tags/constraints" %>
26 <%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%>
27 <%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
28 <%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%>
29 <%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%>
31 <button class="rightbutton btn btn-danger btn-xs" type="button" onclick="deleteOnServerAndInTable(reqCapTableInfo, '${labelForSingleItem}', '${url}');">Remove</button>
32 <button class="rightbutton btn btn-primary btn-xs" type="button" onclick="$('#addReqOrCapDefDiag').modal('show');">Add</button>
34 <div class="modal fade" id="addReqOrCapDefDiag">
35 <div class="modal-dialog">
36 <div class="modal-content" style="width:660px;">
37 <div class="modal-header">
38 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
39 <h4 class="modal-title">Add ${labelForSingleItem}</h4>
41 <div class="modal-body">
42 <form id="addReqOrCapDefForm" enctype="multipart/form-data"><fieldset>
43 <div class="form-group">
44 <label for="reqorcapname">Name</label>
45 <input class="form-control" name="name" id="reqorcapname" type="text" required="required" />
47 <ct:QNameChooser allQNames="${allTypes}" idOfSelectField="type" labelOfSelectField="Type" />
48 <ct:spinnerwithinphty label="Lower Bound" id="lowerbound" min="0" value="1" />
49 <ct:spinnerwithinphty label="Upper Bound" id="upperbound" min="1" value="1" withinphty="true" />
52 <div class="modal-footer">
53 <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
54 <button type="button" class="btn btn-primary" onclick="createReqOrCapDef();">Add</button>
60 <table id="reqorcapdefs">
74 <c:forEach var="r" items="${allSubResources}">
76 <td>${r.def.name}</td>
77 <td>${wc:qname2href(pageContext.request.contextPath, typeClass, r.type)}</td>
78 <td>${w:renderMinInstances(r.def.lowerBound)}</td>
79 <td>${w:renderMaxInstances(r.def.upperBound)}</td>
80 <td><button class="btn btn-xs" onclick="editConstraints('${r.def.name}');">Constraints...</button></td>
88 <%-- Editing a set of constraints --%>
90 <div class="modal fade" id="constraints-dialog">
91 <div class="modal-dialog">
92 <div class="modal-content">
93 <div class="modal-header">
94 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
95 <h4 class="modal-title">Constraints</h4>
97 <div class="modal-body">
98 <div id="noconstraintsexisting" style="display:none;">No constraints defined</div>
99 <ol id="constraintlist" style="display:none;">
102 <div class="modal-footer">
103 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
104 <button type="button" class="btn btn-primary" onclick="editConstraint();">Add new</button>
111 function deleteConstraint(id) {
113 url: "${url}" + currentReqCapName + "/constraints/" + id,
115 error: function(jqXHR, textStatus, errorThrown) {
116 vShowAJAXError("Could not delete constraint", jqXHR, errorThrown);
118 success: function(data, textStatus, jqXHR) {
122 var constraintListIsEmpty = $("#constraintlist").children().length == 0;
123 if (constraintListIsEmpty) {
124 // last item was removed -> show empty message
125 $("#noconstraintsexisting").show();
126 $("#constraintlist").hide();
132 function getLiForConstraint(id) {
133 return '<li id="' + id + '"><span onclick="editConstraint(\'' + id + '\');">constraint</span> <button class="btn btn-danger btn-xs" style="margin-left:10px;" onclick="deleteConstraint(\'' + id + '\')">Delete</button></li>';
136 * @param id the id of the constraint
138 function addConstraintToList(id) {
139 var constraintList = $("#constraintlist");
141 var li = getLiForConstraint(id);
142 constraintList.append(li);
144 // ensure that "no constraints existing" is hidden and the list is shown
145 $("#noconstraintsexisting").hide();
146 constraintList.show();
149 var currentReqCapName;
151 function editConstraints(reqCapName) {
152 currentReqCapName = reqCapName;
154 url: "${url}" + currentReqCapName + "/constraints/",
156 error: function(jqXHR, textStatus, errorThrown) {
157 vShowAJAXError("Could not fetch constraints data", jqXHR, errorThrown);
159 success: function(data, textStatus, jqXHR) {
160 if (data.length == 0) {
161 $("#noconstraintsexisting").show();
162 $("#constraintlist").hide();
164 $("#noconstraintsexisting").hide();
165 var constraintList = $("#constraintlist");
166 constraintList.empty();
167 $(data).each(function(i,id) {
168 addConstraintToList(id);
170 $("#constraintlist").show();
172 $("#constraints-dialog").modal("show");
179 <%-- Editing a single constraint --%>
184 var currentConstraintId;
187 * @param constraintId (optional) If not given, enable editing of a newly created constraint
189 function editConstraint(constraintId) {
190 currentConstraintId = constraintId;
192 // Adjust Create/Update button
193 if (currentConstraintId === undefined) {
194 $("#createConstraintBtn").show();
195 $("#updateConstraintBtn").hide();
197 $("#createConstraintBtn").off("click");
198 $("#createConstraintBtn").on("click", function() {
199 getXMLOfConstraint(function(xmlString) {
202 url: "${url}" + currentReqCapName + "/constraints/",
203 contentType: "text/xml",
207 error: function(jqXHR, textStatus, errorThrown) {
208 vShowAJAXError("Could not add constraint", jqXHR, errorThrown);
210 success: function(resData, textStatus, jqXHR) {
211 addConstraintToList(resData);
212 $("#constraint-dialog").modal("hide");
218 // updating an existing constraint
219 $("#createConstraintBtn").hide();
220 $("#updateConstraintBtn").show();
222 $("#updateConstraintBtn").off("click");
223 $("#updateConstraintBtn").on("click", function() {
224 getXMLOfConstraint(function(xmlString) {
227 url: "${url}" + currentReqCapName + "/constraints/" + currentConstraintId + "/",
228 contentType: "text/xml",
232 error: function(jqXHR, textStatus, errorThrown) {
233 vShowAJAXError("Could not update constraint", jqXHR, errorThrown);
235 success: function(newId, textStatus, jqXHR) {
236 $("#constraint-dialog").modal("hide");
237 var newLi = getLiForConstraint(newId);
238 var oldLi = $("#" + currentConstraintId);
248 if (currentConstraintId === undefined) {
249 $("#constraint-dialog").modal("show");
250 // setting content only works if dialog is fully shown
251 window.setTimeout(function() {
252 window.winery.orionareas["constrainttextarea"].editor.setText($("#emptyconstraint").val());
253 }, window.winery.BOOTSTRAP_ANIMATION_DURATION);
257 url: "${url}" + currentReqCapName + "/constraints/" + currentConstraintId + "/",
260 error: function(jqXHR, textStatus, errorThrown) {
261 vShowAJAXError("Could get constraint information", jqXHR, errorThrown);
263 success: function(xmlData, textStatus, jqXHR) {
264 // xmlDoc contains an XML document and not just a string
265 // We let jQuery parse the XML as we need to parse the type attribute
267 // *move* type information to input field
268 var type = xmlData.documentElement.getAttribute("constraintType");
269 $("#typenameinput").val(type);
270 xmlData.documentElement.removeAttribute("constraintType");
272 $("#constraint-dialog").modal("show");
274 // the XML document cannot be put directly as content. It has to be converted to a String
275 // TODO: add nice formatting
276 var xmlString = (new XMLSerializer()).serializeToString(xmlData);
277 window.setTimeout(function() {
278 window.winery.orionareas["constrainttextarea"].editor.setText(xmlString);
279 }, window.winery.BOOTSTRAP_ANIMATION_DURATION);
288 // TODO: this variable is available after switching tabs.
289 // One could cache this information without requiring reloading all the content
290 var reqCapTableInfo = {
294 require(["winery-support"], function(ws) {
295 ws.initTable(reqCapTableInfo);
298 function createReqOrCapDef() {
299 if (highlightRequiredFields()) {
300 vShowError("Please fill out all required fields.");
304 var data = $('#addReqOrCapDefForm').serialize();
306 // replace &inphty; by TOSCA's "unbounded"
307 data = data.replace("∞", "unbounded");
308 // %E2%88%9E is the HTML encoding of &inphty;
309 data = data.replace("%E2%88%9E", "unbounded");
316 error: function(jqXHR, textStatus, errorThrown) {
317 vShowError("Could not add ${labelForSingleItem}: " + errorThrown + "<br/>" + jqXHR.responseText);
319 success: function(data, textStatus, jqXHR) {
320 // Data has been validated at the server
321 // We can just add the local data
322 var name = $('#reqorcapname').val();
323 var type = $('#type').select2("data").text; // TODO: make href to be consistent with other lines
324 var lbound = $('#lowerbound').val();
325 var ubound = $('#upperbound').val();
326 var constraints = "<button class=\"btn btn-xs\" onclick=\"editConstraints('" + name + "');\">Constraints...</button>";
327 var dataToAdd = [name, type, lbound, ubound, constraints];
328 reqCapTableInfo.table.fnAddData(dataToAdd);
329 $('#addReqOrCapDefDiag').modal('hide');