diff options
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/projectconf.html | 649 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 1 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 106 |
3 files changed, 730 insertions, 26 deletions
diff --git a/bitbake/lib/toaster/toastergui/templates/projectconf.html b/bitbake/lib/toaster/toastergui/templates/projectconf.html index e8b0c39f25..edcad1821f 100644 --- a/bitbake/lib/toaster/toastergui/templates/projectconf.html +++ b/bitbake/lib/toaster/toastergui/templates/projectconf.html @@ -3,60 +3,659 @@ {% load humanize %} {% block localbreadcrumb %} -<li>Project configuration</li> +<li>Configuration variables</li> {% endblock %} {% block projectinfomain %} <div class="page-header"> - <h1>Configuration Variables</h1> + <h1>Configuration variables</h1> </div> <div style="padding-left:19px;"> <dl class="dl-vertical"> - {% for c in configvars %} <dt> - {{c.name}} - <i class="icon-question-sign get-help" title="{{c.desc}}"></i> + <span class="js-config-var-name js-config-var-managed-name">DISTRO</span> + <i class="icon-question-sign get-help" title="The short name of the distribution. If the variable is blank, meta/conf/distro/defaultsetup.conf will be used. <br /><a href='http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-DISTRO' target='_blank'>Read more in the manual</a>"></i> </dt> <dd class="lead"> - <span id="distro">{{c.value}}</span> + <span id="distro">{{distro}}</span> <i class="icon-pencil" id="change-distro-icon"></i> <form id="change-distro-form" style="display:none;"> <div class="input-append"> - <input type="text" id="new-distro" value="poky tiny"> + <input type="text" id="new-distro" value="{{distro}}"> <button id="apply-change-distro" class="btn" type="button">Save</button> <button id="cancel-change-distro" type="button" class="btn btn-link">Cancel</button> </div> </form> </dd> - {% endfor %} + <dt> + <span class="js-config-var-name js-config-var-managed-name">IMAGE_FSTYPES</span> + <i class="icon-question-sign get-help" title="Formats of root file system images that you want to have created <br /><a href='http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-IMAGE_FSTYPES' target='_blank'>Read more in the manual</a>"></i> + </dt> + <dd class="lead"> + <span id="image_fstypes">{{fstypes}}</span> + <i class="icon-pencil" id="change-image_fstypes-icon"></i> + <form id="change-image_fstypes-form" style="display:none;"> + <input id="filter-image_fstypes" type="text" placeholder="Search image types" class="span4"> + <div id="all-image_fstypes" class="scrolling"> + </div> + <button id="apply-change-image_fstypes" type="button" class="btn">Save</button> + <button id="cancel-change-image_fstypes" type="button" class="btn btn-link">Cancel</button> + </form> + </dd> + <dt> + <span class="js-config-var-name js-config-var-managed-name">IMAGE_INSTALL_append</span> + <i class="icon-question-sign get-help" title="Specifies additional packages to install into an image. If your build creates more than one image, the packages will be installed in <strong>all of them</strong> <br /><a href='http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-IMAGE_INSTALL' target='_blank'>Read more in the manual</a>"></i> + </dt> + <dd class="lead muted"> + <span id="image_install">{% if image_install_append %}{{image_install_append}}{%else%}Not set{%endif%}</span> + <i class="icon-pencil" id="change-image_install-icon"></i> + <i class="icon-trash" id="delete-image_install-icon" style="display:none;"></i> + <form id="change-image_install-form" style="display:none;"> + <div class="row-fluid"> + <span class="help-block span4">To set IMAGE_INSTALL_append to more than one package, type the package names separated by a space.</span> + </div> + <div class="input-append"> + <input type="text" class="input-xlarge" id="new-image_install" placeholder="Type one or more package names"> + <button id="apply-change-image_install" class="btn" type="button">Save</button> + <button id="cancel-change-image_install" type="button" class="btn btn-link">Cancel</button> + </div> + </form> + </dd> + <dt> + <span class="js-config-var-name js-config-var-managed-name">PACKAGE_CLASSES</span> + <i class="icon-question-sign get-help" title="Specifies the package manager to use when packaging data <br /><a href='http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-PACKAGE_CLASSES' target='_blank'>Read more in the manual</a>"></i> + </dt> + <dd class="lead"> + <span id="package_classes">{{package_classes}}</span> + <i id="change-package_classes-icon" class="icon-pencil"></i> + <form id="change-package_classes-form" style="display:none;"> + <label> + Root file system package format + <i class="icon-question-sign get-help" title="The package format used to generate the root file system. Options are <code>dev</code>, <code>ipk</code> and <code>rpm</code>"></i> + </label> + <select id="package_classes-select"> + <option>package_dev</option> + <option>package_ipk</option> + <option>package_rpm</option> + </select> + <label> + Additional package formats + <i class="icon-question-sign get-help" title="Extra package formats to build"></i> + </label> + <label class="checkbox" id="package_class_1"> + <input type="checkbox" id="package_class_1_input"> package_dev + </label> + <label class="checkbox" id="package_class_2"> + <input type="checkbox" id="package_class_2_input"> package_ipk + </label> + <div style="padding-top:10px;"> + <button id="apply-change-package_classes" type="button" class="btn">Save</button> + <button id="cancel-change-package_classes" type="button" class="btn btn-link">Cancel</button> + </div> + </form> + </dd> + <dt> + <span class="js-config-var-name js-config-var-managed-name">SDKMACHINE</span> + <i class="icon-question-sign get-help" title="Specifies the architecture (i.e. i686 or x86_64) for which to build SDK and ADT items <br /><a href='http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-SDKMACHINE' target='_blank'>Read more in the manual</a>"></i> + </dt> + <dd class="lead"> + <span id="sdkmachine">{{sdk_machine}}</span> + <i id="change-sdkmachine-icon" class="icon-pencil"></i> + <form id="change-sdkmachine-form" style="display:none;"> + <label class="radio"> + <input type="radio" name="sdkmachine" value="i686"> + i686 + </label> + <label class="radio"> + <input type="radio" name="sdkmachine" value="x86_64"> + x86_64 + </label> + <div style="padding-top:10px;"> + <button id="apply-change-sdkmachine" type="button" class="btn">Save</button> + <button id="cancel-change-sdkmachine" type="button" class="btn btn-link">Cancel</button> + </div> + </form> + </dd> + </dl> + <!-- <ul class="unstyled configuration-list" id="configvar-list"> --> + <dl id="configvar-list"> + <!-- the added configuration variables are inserted here --> </dl> - <form id="variable-form"> + + <!-- pass the fstypes list, black list, and externally managed variables here --> + {% for fstype in vars_fstypes %} + <input type="hidden" class="js-checkbox-fstypes-list" value="{{fstype}}"> + {% endfor %} + {% for b in vars_blacklist %} + <input type="hidden" class="js-config-blacklist-name" value="{{b}}"> + {% endfor %} + {% for b in vars_managed %} + <input type="hidden" class="js-config-var-managed-name" value="{{b}}"> + {% endfor %} + + <div class="row-fluid"> + <form id="variable-form"> <fieldset style="padding-left:0px;"> <legend>Add variable</legend> - <label> - Variable - <i class="icon-question-sign get-help" title="Variable names are case sensitive, cannot have spaces, and can only include letters, numbers, underscores and dashes"></i> - </label> - <input id="variable" type="text" placeholder="Type variable name"> - <label>Value</label> - <input id="value" type="text" placeholder="Type variable value"> - <div style="display:block;margin-top:10px;"> - <a href="#" class="btn save" disabled> - Add variable - </a> + <div class="span3" style="margin-left:0px;"> + <span id="add-configvar-name-div" class="control-group"> + <label> + Variable + <i title="" class="icon-question-sign get-help" + data-original-title="Variable names are case sensitive, + cannot have spaces, and can only include letters, numbers, underscores + and dashes"></i> + </label> + <input type="text" placeholder="Type variable name" id="variable"> + <span class="help-block error" id="new-variable-error-message"></span> + </span> + <label>Value</label> + <input id="value" type="text" placeholder="Type variable value"><p> + <div class="input-append" style="display:block;margin-top:10px;"> + <button id="add-configvar-button" class="btn save" type="button" disabled>Add variable</button> + </div> + </div> + <div class="span5 help-block"> + <h5>Some variables are reserved from Toaster</h5> + <p>Toaster cannot set any variables that impact 1) the configuration of the build servers, + or 2) where artifacts produced by the build are stored. Such variables include: </p> + <p> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-BB_DISKMON_DIRS" target="_blank">BB_DISKMON_DIRS</a></code> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-BB_NUMBER_THREADS" target="_blank">BB_NUMBER_THREADS</a></code> + <code>CVS_PROXY_HOST</code> + <code>CVS_PROXY_PORT</code> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-DL_DIR" target="_blank">DL_DIR</a></code> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-PARALLEL_MAKE" target="_blank">PARALLEL_MAKE</a></code> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-SSTATE_DIR" target="_blank">SSTATE_DIR</a></code> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-SSTATE_MIRRORS" target="_blank">SSTATE_MIRRORS</a></code> + <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-TMPDIR" target="_blank">TMPDIR</a></code></p> + <p>Plus the following standard shell environment variables:</p> + <p><code>http_proxy</code> <code>ftp_proxy</code> <code>https_proxy</code> <code>all_proxy</code></p> </div> </fieldset> - </form> - <!--button id="add-variable" class="btn air"> - <i class="icon-plus"></i> - Add variable - </button--> + </form> + </div> </div> + <script> + + // validate new variable name + function validate_new_variable_name() { + var variable = $("input#variable")[0].value; + var value = $("input#value")[0].value; + + // presumed innocence + $('#new-variable-error-message').html(""); + var error_msg = "" + + var existing_configvars = document.getElementsByClassName('js-config-var-name'); + for (var i = 0, length = existing_configvars.length; i < length; i++) { + if (existing_configvars[i].innerHTML == variable) { + error_msg = "This variable is already set in this page, edit its value instead"; + } + } + + var blacklist_configvars = document.getElementsByClassName('js-config-blacklist-name'); + for (var i = 0, length = blacklist_configvars.length; i < length; i++) { + if (blacklist_configvars[i].value == variable) { + error_msg = "You cannot edit this variable in Toaster because it is set by the build servers"; + } + } + + var bad_chars = /[^a-zA-Z0-9\-_]/.test(variable); + var has_spaces = (0 <= variable.indexOf(" ")); + var only_spaces = (0 < variable.length) && (0 == variable.trim().length); + + if (only_spaces) { + error_msg = "A valid variable name cannot include spaces"; + } else if (bad_chars && has_spaces) { + error_msg = "A valid variable name can only include letters, numbers, underscores, dashes, and cannot include spaces"; + } else if (bad_chars) { + error_msg = "A valid variable name can only include letters, numbers, underscores, and dashes"; + } + + if ("" != error_msg) { + $('#new-variable-error-message').html(error_msg); + $(".save").attr("disabled","disabled"); + + var d = document.getElementById("add-configvar-name-div"); + d.className = d.className + " control-group error"; + + return false; + } + + var d = document.getElementById("add-configvar-name-div"); + d.className = d.className.replace(" control-group error",""); + return true; + } + + // Preset or reset the Package Class checkbox labels + function updatePackageClassCheckboxes() { + if ($('select').val() == 'package_dev') { + $('#package_class_1').html('<input type="checkbox" id="package_class_1_input"> package_ipk'); + $('#package_class_2').html('<input type="checkbox" id="package_class_2_input"> package_rpm'); + } + if ($('select').val() == 'package_ipk') { + $('#package_class_1').html('<input type="checkbox" id="package_class_1_input"> package_dev'); + $('#package_class_2').html('<input type="checkbox" id="package_class_2_input"> package_rpm'); + } + if ($('select').val() == 'package_rpm') { + $('#package_class_1').html('<input type="checkbox" id="package_class_1_input"> package_dev'); + $('#package_class_2').html('<input type="checkbox" id="package_class_2_input"> package_ipk'); + } + } + + // Re-assert handlers when the page is served and/or refreshed via Ajax + function setEventHandlersForDynamicElements() { + + // change variable value + $('.js-icon-pencil-config_var').click(function (evt) { + var pk = evt.target.attributes["x-data"].value; + var current_val = $("span#config_var_"+pk).html(); + $('.js-icon-pencil-config_var, .js-icon-trash-config_var, #config_var_'+pk).hide(); + $("#change-config_var-form_"+pk).slideDown(); + $("input#new-config_var_"+pk)[0].value = current_val; + }); + + $('.js-cancel-change-config_var').click(function (evt) { + var pk = evt.target.attributes["x-data"].value; + $("#change-config_var-form_"+pk).slideUp(function() { + $('.js-icon-pencil-config_var, .js-icon-trash-config_var, #config_var_'+pk).show(); + }); + }); + + $(".js-new-config_var").keyup(function(){ + if ($(this).val().length == 0) { + $(".js-apply-change-config_var").attr("disabled","disabled"); + } + else { + $(".js-apply-change-config_var").removeAttr("disabled"); + } + }); + + $('.js-apply-change-config_var').click(function (evt) { + var xdata = evt.target.attributes["x-data"].value.split(":"); + var pk = xdata[0]; + var variable = xdata[1]; + var val = $('#new-config_var_'+pk).val(); + postEditAjaxRequest({"configvarChange" : variable+':'+val}); + $('#config_var_'+pk).parent().removeClass('muted'); + $("#change-config_var-form_"+pk).slideUp(function() { + $('.js-icon-pencil-config_var, .js-icon-trash-config_var, #config_var_'+pk).show(); + }); + }); + + // delete variable + $(".js-icon-trash-config_var").click(function (evt) { + var xdata = evt.target.attributes["x-data"].value.split(":"); + var pk = xdata[0]; + $('#config_var_entry_'+pk).slideUp(function() { + //$('#config_var_entry_'+pk).show(); + }); + postEditAjaxRequest({"configvarDel": evt.target.attributes["x-data"].value}); + }); + + } + + function onEditPageUpdate(data) { + // update targets + var i; var orightml = ""; + + var configvars_sorted = data.configvars.sort(function(a, b){return a[0] > b[0]}); + + var managed_configvars = document.getElementsByClassName('js-config-var-managed-name'); + + for (i = 0; i < configvars_sorted.length; i++) { + // skip if the variable name has a special context (not user defined) + var var_context=undefined; + for (var j = 0, length = managed_configvars.length; j < length; j++) { + if ((managed_configvars[j].innerHTML == configvars_sorted[i][0]) || + (managed_configvars[j].value == configvars_sorted[i][0]) ) { + var_context='m'; + } + } + if (var_context == undefined) { + orightml += '<dt id="config_var_entry_'+configvars_sorted[i][2]+'"><span class="js-config-var-name">'+configvars_sorted[i][0]+'</span><i class="icon-trash js-icon-trash-config_var" x-data="'+configvars_sorted[i][2]+'"></i> </dt>' + orightml += '<dd class="lead">' + orightml += ' <span id="config_var_'+configvars_sorted[i][2]+'">'+configvars_sorted[i][1]+'</span>' + orightml += ' <i class="icon-pencil js-icon-pencil-config_var" x-data="'+configvars_sorted[i][2]+'"></i>' + orightml += ' <form id="change-config_var-form_'+configvars_sorted[i][2]+'" style="display:none;">' + orightml += ' <div class="input-append">' + orightml += ' <input type="text" class="input-xlarge js-new-config_var" id="new-config_var_'+configvars_sorted[i][2]+'" value="">' + orightml += ' <button class="btn js-apply-change-config_var" type="button" x-data="'+configvars_sorted[i][2]+':'+configvars_sorted[i][0]+'" disabled>Save</button>' + orightml += ' <button type="button" class="btn btn-link js-cancel-change-config_var" x-data="'+configvars_sorted[i][2]+'">Cancel</button>' + orightml += ' </div>' + orightml += ' </form>' + orightml += '</dd>' + } + } + + // update configvars list + $("dl#configvar-list").html(orightml); + + // re-assert these event handlers + setEventHandlersForDynamicElements(); + } + + function onEditAjaxSuccess(data, textstatus) { + // console.log("XHR returned:", data, "(" + textstatus + ")"); + if (data.error != "ok") { + alert("error on request:\n" + data.error); + return; + } + onEditPageUpdate(data); + } + + function onEditAjaxError(jqXHR, textstatus, error) { + alert("XHR errored:\n" + error + "\n(" + textstatus + ")"); + // re-assert the event handlers + } + + function postEditAjaxRequest(reqdata) { + var ajax = $.ajax({ + type:"POST", + data: $.param(reqdata), + url:"{% url 'xhr_configvaredit' project.id%}", + headers: { 'X-CSRFToken': $.cookie("csrftoken")}, + success: onEditAjaxSuccess, + error: onEditAjaxError, + }) + } + + + $(document).ready(function() { + + // + // Register handlers for static elements + // + + // change distro variable + $('#change-distro-icon').click(function() { + $('#change-distro-icon, #distro').hide(); + $("#change-distro-form").slideDown(); + }); + + $('#cancel-change-distro').click(function(){ + $("#change-distro-form").slideUp(function() { + $('#distro, #change-distro-icon').show(); + }); + }); + + $("#new-distro").keyup(function(){ + if ($(this).val().length == 0) { + $("#apply-change-distro").attr("disabled","disabled"); + } + else { + $("#apply-change-distro").removeAttr("disabled"); + } + }); + + $('#apply-change-distro').click(function(){ + //$('#repo').parent().removeClass('highlight-go'); + var name = $('#new-distro').val(); + postEditAjaxRequest({"configvarChange" : 'DISTRO:'+name}); + $('#distro').html(name); + $("#change-distro-form").slideUp(function () { + $('#distro, #change-distro-icon').show(); + }); + }); + + + // change IMAGE_FSTYPES variable + $('#change-image_fstypes-icon').click(function() { + $('#change-image_fstypes-icon, #image_fstypes').hide(); + $("#change-image_fstypes-form").slideDown(); + // avoid false substring matches by including space separators + var html = ""; + var fstypes = " " + document.getElementById("image_fstypes").innerHTML + " "; + var fstypes_list = document.getElementsByClassName('js-checkbox-fstypes-list'); + // Add the checked boxes first + if (" " != fstypes) { + for (var i = 0, length = fstypes_list.length; i < length; i++) { + if (0 <= fstypes.indexOf(" "+fstypes_list[i].value+" ")) { + html += '<label class="checkbox"><input type="checkbox" class="fs-checkbox-fstypes" value="'+fstypes_list[i].value+'" checked="checked">'+fstypes_list[i].value+'</label>\n'; + } + } + } + // Add the un-checked boxes second + for (var i = 0, length = fstypes_list.length; i < length; i++) { + if (0 > fstypes.indexOf(" "+fstypes_list[i].value+" ")) { + html += '<label class="checkbox"><input type="checkbox" class="fs-checkbox-fstypes" value="'+fstypes_list[i].value+'">'+fstypes_list[i].value+'</label>\n'; + } + } + document.getElementById("all-image_fstypes").innerHTML = html; + }); + + $('#cancel-change-image_fstypes').click(function(){ + $("#change-image_fstypes-form").slideUp(function() { + $('#image_fstypes, #change-image_fstypes-icon').show(); + }); + }); + + $('#apply-change-image_fstypes').click(function(){ + var fstypes = ''; + var checkboxes = document.getElementsByClassName('fs-checkbox-fstypes'); + for (var i = 0, length = checkboxes.length; i < length; i++) { + if (checkboxes[i].checked) { + fstypes += checkboxes[i].value + ' '; + } + } + fstypes = fstypes.trim(); + + postEditAjaxRequest({"configvarChange" : 'IMAGE_FSTYPES:'+fstypes}); + $('#image_fstypes').html(fstypes); + $('#image_fstypes').parent().removeClass('muted'); + + $("#change-image_fstypes-form").slideUp(function() { + $('#image_fstypes, #change-image_fstypes-icon').show(); + }); + }); + + + // change IMAGE_INSTALL_append variable + $('#change-image_install-icon').click(function() { + $('#change-image_install-icon, #delete-image_install-icon, #image_install').hide(); + $("#change-image_install-form").slideDown(); + }); + + $('#cancel-change-image_install').click(function(){ + $("#change-image_install-form").slideUp(function() { + $('#image_install, #change-image_install-icon').show(); + }); + }); + + $("#new-image_install").keyup(function(){ + if ($(this).val().length == 0) { + $("#apply-change-image_install").attr("disabled","disabled"); + } + else { + $("#apply-change-image_install").removeAttr("disabled"); + } + }); + + $('#apply-change-image_install').click(function(){ + var name = $('#new-image_install').val(); + postEditAjaxRequest({"configvarChange" : 'IMAGE_INSTALL_append:'+name}); + $('#image_install').html(name); + $('#image_install').parent().removeClass('muted'); + $("#change-image_install-form").slideUp(function () { + $('#image_install, #change-image_install-icon').show(); + if (name.length > -1) { + $('#delete-image_install-icon').show(); + } + }); + }); + + // delete IMAGE_INSTALL_append variable value + $('#delete-image_install-icon').click(function(){ + $(this).tooltip('hide'); + postEditAjaxRequest({"configvarChange" : 'IMAGE_INSTALL_append:'+''}); + $('#image_install').parent().fadeOut(1000, function(){ + $('#image_install').parent().addClass('muted'); + $('#image_install').html('Not set'); + $('#delete-image_install-icon').hide(); + $('#image_install').parent().fadeIn(1000); + }); + }); + + + // change PACKAGE_CLASSES variable + $('#change-package_classes-icon').click(function() { + $('#change-package_classes-icon, #package_classes').hide(); + $("#change-package_classes-form").slideDown(); + + // initialize the pulldown and checkboxes + var value = document.getElementById("package_classes").innerHTML; + if (0 == value.indexOf("package_dev")) { + $('select').selectedIndex = 0; + updatePackageClassCheckboxes(); + if (0 < value.indexOf("package_ipk")) {document.getElementById("package_class_1_input").checked = true}; + if (0 < value.indexOf("package_rpm")) {document.getElementById("package_class_2_input").checked = true}; + } + if (0 == value.indexOf("package_ipk")) { + $('select').selectedIndex = 1; + updatePackageClassCheckboxes(); + if (0 < value.indexOf("package_dev")) {document.getElementById("package_class_1_input").checked = true;}; + if (0 < value.indexOf("package_rpm")) {document.getElementById("package_class_2_input").checked = true;}; + } + if (0 == value.indexOf("package_rpm")) { + $('select').selectedIndex = 2; + updatePackageClassCheckboxes(); + if (0 < value.indexOf("package_dev")) {document.getElementById("#package_class_1_input").checked = true;}; + if (0 < value.indexOf("package_ipk")) {document.getElementById("#package_class_2_input").checked = true;}; + } + }); + + $('#cancel-change-package_classes').click(function(){ + $("#change-package_classes-form").slideUp(function() { + $('#package_classes, #change-package_classes-icon').show(); + }); + }); + + $('select').change(function() { + updatePackageClassCheckboxes(); + }); + + $('#apply-change-package_classes').click(function(){ + var e = document.getElementById("package_classes-select"); + var val = e.options[e.selectedIndex].text; + + pc1_checked = document.getElementById("package_class_1_input").checked; + pc2_checked = document.getElementById("package_class_2_input").checked; + if (val == "package_dev") { + if (pc1_checked) val = val + " package_ipk"; + if (pc2_checked) val = val + " package_rpm"; + } + if (val == "package_ipk") { + if (pc1_checked) val = val + " package_dev"; + if (pc2_checked) val = val + " package_rpm"; + } + if (val == "package_rpm") { + if (pc1_checked) val = val + " package_dev"; + if (pc2_checked) val = val + " package_ipk"; + } + + $('#package_classes').html(val); + //$('#package_classes').parent().removeClass('muted'); + postEditAjaxRequest({"configvarChange" : 'PACKAGE_CLASSES:'+val}); + $("#change-package_classes-form").slideUp(function() { + $('#package_classes, #change-package_classes-icon').show(); + }); + }); + + + // change SDKMACHINE variable + $('#change-sdkmachine-icon').click(function() { + var current_value = document.getElementById("sdkmachine").innerHTML; + var radios = document.getElementsByName('sdkmachine'); + for (var i = 0, length = radios.length; i < length; i++) { + radios[i].checked = false; + if (radios[i].value == current_value) { + radios[i].checked = true; + } + } + $('#change-sdkmachine-icon, #sdkmachine').hide(); + $("#change-sdkmachine-form").slideDown(); + }); + + $('#cancel-change-sdkmachine').click(function(){ + $("#change-sdkmachine-form").slideUp(function() { + $('#sdkmachine, #change-sdkmachine-icon').show(); + }); + }); + + $('#apply-change-sdkmachine').click(function(){ + var value=""; + var radios = document.getElementsByName('sdkmachine'); + for (var i = 0, length = radios.length; i < length; i++) { + if (radios[i].checked) { + // do whatever you want with the checked radio + value=radios[i].value; + break; + } + } + postEditAjaxRequest({"configvarChange" : 'SDKMACHINE:'+value}); + $('#sdkmachine').html(value); + $("#change-sdkmachine-form").slideUp(function() { + $('#sdkmachine, #change-sdkmachine-icon').show(); + }); + + }); + + + // add new variable + $("button#add-configvar-button").click( function (evt) { + var variable = $("input#variable")[0].value; + var value = $("input#value")[0].value; + + if (validate_new_variable_name()) { + postEditAjaxRequest({"configvarAdd" : variable+':'+value}); + + // clear the previous values + $("input#variable")[0].value = ""; + $("input#value")[0].value = ""; + + } + }); + + // validate new variable name + $("input#variable").focusout( function (evt) { + validate_new_variable_name(); + }); + + //activate / deactivate save added variable button + $("#variable, #value").keyup(function() { + if ( $("#variable").val().length > 0 && $("#value").val().trim().length > 0 ) { + $(".save").removeAttr("disabled"); + } + else { + $(".save").attr("disabled","disabled"); + } + }); + + // + // draw and register the dynamic configuration variables and handlers + // + + var data = { + configvars : [] + }; + {% for c in configvars %} + data.configvars.push([ "{{c.name}}","{{c.value}}","{{c.pk}}" ]); + {% if '' != vars_context|get_dict_value:c.name %} + data.vars_context[ "{{c.name}}" ] = "{{vars_context|get_dict_value:c.name }}"; + {% endif %} + {% endfor %} + + // draw these elements and assert their event handlers + onEditPageUpdate(data); + }); + + </script> {% endblock %} diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 5c969f814c..c74c7a651b 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py @@ -91,6 +91,7 @@ urlpatterns = patterns('toastergui.views', url(r'^xhr_projectbuild/(?P<pid>\d+)/$', 'xhr_projectbuild', name='xhr_projectbuild'), url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'), url(r'^xhr_projectedit/(?P<pid>\d+)/$', 'xhr_projectedit', name='xhr_projectedit'), + url(r'^xhr_configvaredit/(?P<pid>\d+)/$', 'xhr_configvaredit', name='xhr_configvaredit'), url(r'^xhr_datatypeahead/$', 'xhr_datatypeahead', name='xhr_datatypeahead'), url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 4fae70b48b..5fcad63e45 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -2270,6 +2270,55 @@ if toastermain.settings.MANAGED: return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") + def xhr_configvaredit(request, pid): + try: + prj = Project.objects.get(id = pid) + # add conf variables + if 'configvarAdd' in request.POST: + t=request.POST['configvarAdd'].strip() + if ":" in t: + variable, value = t.split(":") + else: + variable = t + value = "" + + pt, created = ProjectVariable.objects.get_or_create(project = prj, name = variable, value = value) + # change conf variables + if 'configvarChange' in request.POST: + t=request.POST['configvarChange'].strip() + if ":" in t: + variable, value = t.split(":") + else: + variable = t + value = "" + + try: + pt = ProjectVariable.objects.get(project = prj, name = variable) + pt.value=value + pt.save() + except ObjectDoesNotExist: + print("the entry doesn't exist.") + # remove conf variables + if 'configvarDel' in request.POST: + t=request.POST['configvarDel'].strip() + pt = ProjectVariable.objects.get(pk = int(t)).delete() + + # return all project settings + vars_managed,vars_fstypes,vars_blacklist = get_project_configvars_context() + return HttpResponse(json.dumps( { + "error": "ok", + 'configvars' : map(lambda x: (x.name, x.value, x.pk), ProjectVariable.objects.filter(project_id = pid).all()), + 'distro' : ProjectVariable.objects.get(project = prj, name = "DISTRO").value, + 'fstypes' : ProjectVariable.objects.get(project = prj, name = "IMAGE_FSTYPES").value, + 'image_install_append': ProjectVariable.objects.get(project = prj, name = "IMAGE_INSTALL_append").value, + 'package_classes': ProjectVariable.objects.get(project = prj, name = "PACKAGE_CLASSES").value, + 'sdk_machine' : ProjectVariable.objects.get(project = prj, name = "SDKMACHINE").value, + }), content_type = "application/json") + + except Exception as e: + return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") + + def xhr_importlayer(request): if (not request.POST.has_key('vcs_url') or not request.POST.has_key('name') or @@ -2737,11 +2786,66 @@ if toastermain.settings.MANAGED: return render(request, template, context) + + def get_project_configvars_context(): + # Vars managed outside of this view + vars_managed = { + 'MACHINE' + } + + vars_blacklist = { + 'DL_DR','PARALLEL_MAKE','BB_NUMBER_THREADS','SSTATE_DIR', + 'BB_DISKMON_DIRS','BB_NUMBER_THREADS','CVS_PROXY_HOST','CVS_PROXY_PORT', + 'DL_DIR','PARALLEL_MAKE','SSTATE_DIR','SSTATE_DIR','SSTATE_MIRRORS','TMPDIR', + 'all_proxy','ftp_proxy','http_proxy ','https_proxy' + } + + vars_fstypes = { + 'btrfs','cpio','cpio.gz','cpio.lz4','cpio.lzma','cpio.xz','cramfs', + 'elf','ext2','ext2.bz2','ext2.gz','ext2.lzma' 'ext3','ext3.gz','hddimg', + 'iso','jffs2','jffs2.sum','squashfs','squashfs-lzo','squashfs-xz','tar.bz2', + 'tar.lz4','tar.xz','tartar.gz','ubi','ubifs','vmdk' + } + + return(vars_managed,sorted(vars_fstypes),vars_blacklist) + def projectconf(request, pid): template = "projectconf.html" + + try: + prj = Project.objects.get(id = pid) + except Project.DoesNotExist: + return HttpResponseNotFound("<h1>Project id " + pid + " is unavailable</h1>") + + vars_managed,vars_fstypes,vars_blacklist = get_project_configvars_context() context = { - 'configvars': ProjectVariable.objects.filter(project_id = pid), + 'configvars': ProjectVariable.objects.filter(project_id = pid).all(), + 'vars_managed': vars_managed, + 'vars_fstypes': vars_fstypes, + 'vars_blacklist': vars_blacklist, } + + try: + context['distro'] = ProjectVariable.objects.get(project = prj, name = "DISTRO").value + except ProjectVariable.DoesNotExist: + pass + try: + context['fstypes'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_FSTYPES").value + except ProjectVariable.DoesNotExist: + pass + try: + context['image_install_append'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_INSTALL_append").value + except ProjectVariable.DoesNotExist: + pass + try: + context['package_classes'] = ProjectVariable.objects.get(project = prj, name = "PACKAGE_CLASSES").value + except ProjectVariable.DoesNotExist: + pass + try: + context['sdk_machine'] = ProjectVariable.objects.get(project = prj, name = "SDKMACHINE").value + except ProjectVariable.DoesNotExist: + pass + return render(request, template, context) def projectbuilds(request, pid): |