[bitbake-devel] [PATCH 2/2] toaster: project configuration variables page

Alex DAMIAN alexandru.damian at intel.com
Fri Jan 16 16:42:41 UTC 2015


From: David Reyna <David.Reyna at windriver.com>

Implement the project configuration variables page.

AlexD made whitespace changes and a minor fix.

[YOCTO #6588]

Signed-off-by: David Reyna <David.Reyna at windriver.com>
Signed-off-by: Alexandru DAMIAN <alexandru.damian at intel.com>
---
 lib/toaster/toastergui/templates/projectconf.html | 649 +++++++++++++++++++++-
 lib/toaster/toastergui/urls.py                    |   1 +
 lib/toaster/toastergui/views.py                   | 106 +++-
 3 files changed, 730 insertions(+), 26 deletions(-)

diff --git a/lib/toaster/toastergui/templates/projectconf.html b/lib/toaster/toastergui/templates/projectconf.html
index e8b0c39..edcad18 100644
--- a/lib/toaster/toastergui/templates/projectconf.html
+++ b/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/lib/toaster/toastergui/urls.py b/lib/toaster/toastergui/urls.py
index 5c969f8..c74c7a6 100644
--- a/lib/toaster/toastergui/urls.py
+++ b/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/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 4fae70b..5fcad63 100755
--- a/lib/toaster/toastergui/views.py
+++ b/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):
-- 
1.9.1




More information about the bitbake-devel mailing list