summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/lib/toaster/bldcontrol/localhostbecontroller.py13
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/base.js229
-rw-r--r--bitbake/lib/toaster/toastergui/templates/base.html133
-rw-r--r--bitbake/lib/toaster/toastergui/templates/projecttopbar.html18
4 files changed, 61 insertions, 332 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
index b5cf5591fd..854a6bbfe2 100644
--- a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
+++ b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
@@ -48,7 +48,6 @@ class LocalhostBEController(BuildEnvironmentController):
48 48
49 def __init__(self, be): 49 def __init__(self, be):
50 super(LocalhostBEController, self).__init__(be) 50 super(LocalhostBEController, self).__init__(be)
51 self.dburl = settings.getDATABASE_URL()
52 self.pokydirname = None 51 self.pokydirname = None
53 self.islayerset = False 52 self.islayerset = False
54 53
@@ -126,9 +125,17 @@ class LocalhostBEController(BuildEnvironmentController):
126 port = i.split(" ")[-1] 125 port = i.split(" ")[-1]
127 logger.debug("localhostbecontroller: Found bitbake server port %s" % port) 126 logger.debug("localhostbecontroller: Found bitbake server port %s" % port)
128 127
129 cmd = "bash -c \"source %s/oe-init-build-env-memres -1 %s && DATABASE_URL=%s %s --observe-only -u toasterui --remote-server=0.0.0.0:-1 -t xmlrpc\"" % (self.pokydirname, self.be.builddir, self.dburl, own_bitbake) 128 cmd = "bash -c \"source %s/oe-init-build-env-memres -1 %s && %s --observe-only -u toasterui --remote-server=0.0.0.0:-1 -t xmlrpc\"" % \
129 (self.pokydirname, self.be.builddir, own_bitbake)
130
131 # Use a copy of the current environment and add the DATABASE_URL
132 # for the bitbake observer process.
133 env = os.environ.copy()
134 env['DATABASE_URL'] = settings.getDATABASE_URL()
135
130 with open(toaster_ui_log_filepath, "a+") as f: 136 with open(toaster_ui_log_filepath, "a+") as f:
131 p = subprocess.Popen(cmd, cwd = self.be.builddir, shell=True, stdout=f, stderr=f) 137 p = subprocess.Popen(cmd, cwd = self.be.builddir, shell=True,
138 stdout=f, stderr=f, env=env)
132 139
133 def _toaster_ui_started(filepath, filepos = 0): 140 def _toaster_ui_started(filepath, filepos = 0):
134 if not os.path.exists(filepath): 141 if not os.path.exists(filepath):
diff --git a/bitbake/lib/toaster/toastergui/static/js/base.js b/bitbake/lib/toaster/toastergui/static/js/base.js
deleted file mode 100644
index ed22a4ebc1..0000000000
--- a/bitbake/lib/toaster/toastergui/static/js/base.js
+++ /dev/null
@@ -1,229 +0,0 @@
1'use strict';
2
3function basePageInit(ctx) {
4
5 var newBuildButton = $("#new-build-button");
6 var newBuildTargetInput;
7 var newBuildTargetBuildBtn;
8 var projectNameForm = $("#project-name-change-form");
9 var projectNameContainer = $("#project-name-container");
10 var projectName = $("#project-name");
11 var projectNameFormToggle = $("#project-change-form-toggle");
12 var projectNameChangeCancel = $("#project-name-change-cancel");
13
14 /* initially the current project is used unless overridden by the new build
15 * button in top right nav
16 */
17 var selectedProject = libtoaster.ctx;
18
19 var selectedTarget;
20
21 var newBuildProjectInput = $("#new-build-button #project-name-input");
22 var newBuildProjectSaveBtn = $("#new-build-button #save-project-button");
23
24 /* Project name change functionality */
25 projectNameFormToggle.click(function(e){
26 e.preventDefault();
27 projectNameContainer.hide();
28 projectNameForm.fadeIn();
29 });
30
31 projectNameChangeCancel.click(function(e){
32 e.preventDefault();
33 projectNameForm.hide();
34 projectNameContainer.fadeIn();
35 });
36
37 $("#project-name-change-btn").click(function(e){
38 var newProjectName = $("#project-name-change-input").val();
39
40 libtoaster.editCurrentProject({ projectName: newProjectName }, function (){
41 projectName.html(newProjectName);
42 libtoaster.ctx.projectName = newProjectName;
43 projectNameChangeCancel.click();
44 });
45 });
46
47 _checkProjectBuildable();
48
49 $("#project-topbar .nav li a").each(function(){
50 if (window.location.pathname === $(this).attr('href'))
51 $(this).parent().addClass('active');
52 else
53 $(this).parent().removeClass('active');
54 });
55
56 if ($(".total-builds").length !== 0){
57 libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
58 if (prjInfo.completedbuilds)
59 $(".total-builds").text(prjInfo.completedbuilds.length);
60 });
61 }
62
63 /* Hide the button if we're on the project,newproject or importlyaer page
64 * or if there are no projects yet defined
65 * only show if there isn't already a build-target-input already
66 */
67 if (ctx.numProjects > 0 &&
68 ctx.currentUrl.search('newproject') < 0 &&
69 $(".build-target-input").length === 1) {
70
71 newBuildTargetInput = $("#new-build-button .build-target-input");
72 newBuildTargetBuildBtn = $("#new-build-button").find(".build-button");
73
74 _setupNewBuildButton();
75 newBuildButton.show();
76 } else if ($(".build-target-input").length > 0) {
77 newBuildTargetInput = $("#project-topbar .build-target-input");
78 newBuildTargetBuildBtn = $("#project-topbar .build-button");
79 } else {
80 return;
81 }
82
83 /* Hide the change project icon when there is only one project */
84 if (ctx.numProjects === 1) {
85 $('#project .icon-pencil').hide();
86 }
87
88 /* If we have a project setup the typeahead */
89 if (selectedProject.recipesTypeAheadUrl){
90 libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.recipesTypeAheadUrl, { format: "json" }, function (item) {
91 selectedTarget = item;
92 newBuildTargetBuildBtn.removeAttr("disabled");
93 });
94 }
95
96 newBuildTargetInput.on('input', function () {
97 if ($(this).val().length === 0) {
98 newBuildTargetBuildBtn.attr("disabled", "disabled");
99 } else {
100 newBuildTargetBuildBtn.removeAttr("disabled");
101 }
102 });
103
104 newBuildTargetBuildBtn.click(function (e) {
105 e.preventDefault();
106
107 if (!newBuildTargetInput.val()) {
108 return;
109 }
110
111 /* We use the value of the input field so as to maintain any command also
112 * added e.g. core-image-minimal:clean
113 */
114 selectedTarget = { name: newBuildTargetInput.val() };
115
116 /* Fire off the build */
117 libtoaster.startABuild(selectedProject.projectBuildsUrl,
118 selectedProject.projectId, selectedTarget.name, function(){
119 window.location.replace(selectedProject.projectBuildsUrl);
120 }, null);
121 });
122
123 function _checkProjectBuildable() {
124 if (selectedProject.projectId === undefined || selectedProject.projectIsDefault) {
125 return;
126 }
127
128 libtoaster.getProjectInfo(selectedProject.projectPageUrl,
129 function (data) {
130 if (data.machine === null || data.machine.name === undefined || data.layers.length === 0) {
131 /* we can't build anything without a machine and some layers */
132 $("#new-build-button #targets-form").hide();
133 $("#new-build-button .alert").show();
134 } else {
135 $("#new-build-button #targets-form").show();
136 $("#new-build-button .alert").hide();
137
138 /* we can build this project; enable input fields */
139 newBuildTargetInput.removeAttr("disabled");
140 }
141 }, null);
142 }
143
144 /* Setup New build button in the top nav bar */
145 function _setupNewBuildButton() {
146
147 /* If we don't have a current project then present the set project
148 * form.
149 */
150 if (selectedProject.projectId === undefined || selectedProject.projectIsDefault) {
151 $('#change-project-form').show();
152 $('#project .icon-pencil').hide();
153 }
154
155 libtoaster.makeTypeahead(newBuildProjectInput, selectedProject.projectsTypeAheadUrl, { format : "json" }, function (item) {
156 /* successfully selected a project */
157 newBuildProjectSaveBtn.removeAttr("disabled");
158 selectedProject = item;
159 });
160
161 /* Any typing in the input apart from enter key is going to invalidate
162 * the value that has been set by selecting a suggestion from the typeahead
163 */
164 newBuildProjectInput.on('input', function (event) {
165 if (event.keyCode === 13) {
166 return;
167 }
168 newBuildProjectSaveBtn.attr("disabled", "disabled");
169 });
170
171
172 newBuildProjectSaveBtn.click(function () {
173 selectedProject.projectId = selectedProject.id;
174 /* Update the typeahead project_id paramater */
175 _checkProjectBuildable();
176
177 newBuildTargetInput.removeAttr("disabled");
178
179 /* We've got a new project so now we need to update the
180 * target urls. We can get this from the new project's info
181 */
182 $.getJSON(selectedProject.projectPageUrl, { format: "json" },
183 function(projectInfo){
184 /* Update the typeahead to use the new selectedProject */
185 selectedProject = projectInfo;
186
187 libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.recipesTypeAheadUrl, { format: "json" }, function (item) {
188 /* successfully selected a target */
189 selectedTarget = item;
190 newBuildTargetBuildBtn.removeAttr("disabled");
191 });
192
193 });
194 newBuildTargetInput.val("");
195
196 /* set up new form aspect */
197 $("#new-build-button #project a").text(selectedProject.name).attr('href', selectedProject.projectPageUrl);
198 $("#new-build-button .alert a").attr('href', selectedProject.projectPageUrl);
199 $("#project .icon-pencil").show();
200
201 $("#change-project-form").slideUp({ 'complete' : function () {
202 $("#new-build-button #project").show();
203 }});
204 });
205
206 $('#new-build-button #project .icon-pencil').click(function () {
207 newBuildProjectSaveBtn.attr("disabled", "disabled");
208 newBuildProjectInput.val($("#new-build-button #project a").text());
209 $("#cancel-change-project").show();
210 $(this).parent().hide();
211 $("#change-project-form").slideDown();
212 });
213
214 $("#new-build-button #cancel-change-project").click(function () {
215 $("#change-project-form").hide(function () {
216 $('#new-build-button #project').show();
217 });
218
219 newBuildProjectInput.val("");
220 newBuildProjectSaveBtn.attr("disabled", "disabled");
221 });
222
223 /* Keep the dropdown open even unless we click outside the dropdown area */
224 $(".new-build").click (function (event) {
225 event.stopPropagation();
226 });
227 };
228
229}
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html
index 11ac2a0355..e0b15cef12 100644
--- a/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/bitbake/lib/toaster/toastergui/templates/base.html
@@ -3,15 +3,15 @@
3{% load projecttags %} 3{% load projecttags %}
4{% load project_url_tag %} 4{% load project_url_tag %}
5<html lang="en"> 5<html lang="en">
6 <head> 6 <head>
7 <title> 7 <title>
8 {% block title %} Toaster {% endblock %} 8 {% block title %} Toaster {% endblock %}
9 </title> 9 </title>
10<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css"/> 10 <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css"/>
11<link rel="stylesheet" href="{% static 'css/bootstrap-responsive.min.css' %}" type='text/css'/> 11 <link rel="stylesheet" href="{% static 'css/bootstrap-responsive.min.css' %}" type='text/css'/>
12<link rel="stylesheet" href="{% static 'css/font-awesome.min.css' %}" type='text/css'/> 12 <link rel="stylesheet" href="{% static 'css/font-awesome.min.css' %}" type='text/css'/>
13<link rel="stylesheet" href="{% static 'css/prettify.css' %}" type='text/css'/> 13 <link rel="stylesheet" href="{% static 'css/prettify.css' %}" type='text/css'/>
14<link rel="stylesheet" href="{% static 'css/default.css' %}" type='text/css'/> 14 <link rel="stylesheet" href="{% static 'css/default.css' %}" type='text/css'/>
15 15
16 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 16 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
17 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> 17 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
@@ -40,7 +40,6 @@
40 projectId : {{project.id}}, 40 projectId : {{project.id}},
41 projectPageUrl : {% url 'project' project.id as purl %}{{purl|json}}, 41 projectPageUrl : {% url 'project' project.id as purl %}{{purl|json}},
42 projectName : {{project.name|json}}, 42 projectName : {{project.name|json}},
43 projectIsDefault: {% if project.is_default %}true{% else %}false{% endif %},
44 recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}}, 43 recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}},
45 layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}}, 44 layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}},
46 machinesTypeAheadUrl: {% url 'xhr_machinestypeahead' project.id as paturl%}{{paturl|json}}, 45 machinesTypeAheadUrl: {% url 'xhr_machinestypeahead' project.id as paturl%}{{paturl|json}},
@@ -51,37 +50,24 @@
51 projectId : undefined, 50 projectId : undefined,
52 projectPageUrl : undefined, 51 projectPageUrl : undefined,
53 projectName : undefined, 52 projectName : undefined,
54 projectIsDefault: false,
55 {% endif %} 53 {% endif %}
56 }; 54 };
57 </script> 55 </script>
58 <script src="{% static 'js/base.js' %}"></script> 56 {% block extraheadcontent %}
59 <script> 57 {% endblock %}
60 $(document).ready(function () { 58 </head>
61 /* Vars needed for base.js */
62 var ctx = {};
63 ctx.numProjects = {{projects|length}};
64 ctx.currentUrl = "{{request.path|escapejs}}";
65
66 basePageInit(ctx);
67 });
68 </script>
69 59
70{% block extraheadcontent %} 60 <body style="height: 100%">
71{% endblock %}
72 </head>
73 61
74<body style="height: 100%"> 62 {% csrf_token %}
75 63 <div id="loading-notification" class="alert lead text-center" style="display:none">
76 {% csrf_token %} 64 Loading <i class="fa-pulse icon-spinner"></i>
77 <div id="loading-notification" class="alert lead text-center" style="display:none"> 65 </div>
78 Loading <i class="fa-pulse icon-spinner"></i>
79 </div>
80 66
81 <div id="change-notification" class="alert lead alert-info" style="display:none"> 67 <div id="change-notification" class="alert lead alert-info" style="display:none">
82 <button type="button" class="close" id="hide-alert">&times;</button> 68 <button type="button" class="close" id="hide-alert">&times;</button>
83 <span id="change-notification-msg"></span> 69 <span id="change-notification-msg"></span>
84 </div> 70 </div>
85 71
86 <div class="navbar navbar-fixed-top"> 72 <div class="navbar navbar-fixed-top">
87 <div class="navbar-inner"> 73 <div class="navbar-inner">
@@ -125,72 +111,19 @@
125 111
126 <!-- new project button; only show in build mode --> 112 <!-- new project button; only show in build mode -->
127 {% if BUILD_MODE %} 113 {% if BUILD_MODE %}
128 <div class="btn-group pull-right"> 114 <div class="btn-group pull-right">
129 <a class="btn" id="new-project-button" href="{% url 'newproject' %}">New project</a> 115 <a class="btn" id="new-project-button" href="{% url 'newproject' %}">New project</a>
130 </div> 116 </div>
131 {% endif %}
132
133 <!--
134 New build popover; only shown if there is at least one user-created project
135 and we're in build mode
136 -->
137 {% if BUILD_MODE and non_cli_projects.count > 0 %}
138 <div class="btn-group pull-right" id="new-build-button" style="display:none">
139 <button class="btn dropdown-toggle" data-toggle="dropdown">
140 New build
141 <i class="icon-caret-down"></i>
142 </button>
143 <ul class="dropdown-menu new-build multi-select">
144 <li>
145 <h3>New build</h3>
146 <h6>
147 Project:
148 <span id="project">
149 {% if project.id and not project.is_default %}
150 <a class="lead" href="{% project_url project %}">{{project.name}}</a>
151 {% else %}
152 <a class="lead" href="#"></a>
153 {% endif %}
154 <i class="icon-pencil"></i>
155 </span>
156 </h6>
157 <form id="change-project-form" style="display:none;">
158 <div class="input-append">
159 <input type="text" class="input-medium" id="project-name-input" placeholder="Type a project name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead"/>
160 <button id="save-project-button" class="btn" type="button">Save</button>
161 <a href="#" id="cancel-change-project" class="btn btn-link" style="display: none">Cancel</a>
162 </div>
163 <p><a id="view-all-projects" href="{% url 'all-projects' %}">View all projects</a></p>
164 </form>
165 </li>
166 <li>
167 <div class="alert" style="display:none;">
168 <p>This project configuration is incomplete, so you cannot run builds.</p>
169 <p><a href="{% if project.id %}{% url 'project' project.id %}{% endif %}">View project configuration</a></p>
170 </div>
171 </li>
172 <li id="targets-form">
173 <h6>Recipe(s):</h6>
174 <form>
175 <input type="text" class="input-xlarge build-target-input" placeholder="Type a recipe name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead" disabled/>
176 <div class="row-fluid">
177 <button class="btn btn-primary build-button" disabled>Build</button>
178 </div>
179 </form>
180 </li>
181 </ul>
182 </div>
183 {% endif %} 117 {% endif %}
118 </div>
119 </div>
184 </div> 120 </div>
185 </div>
186</div>
187 121
188<div class="container-fluid top-padded"> 122 <div class="container-fluid top-padded">
189<div class="row-fluid"> 123 <div class="row-fluid">
190{% block pagecontent %} 124 {% block pagecontent %}
191{% endblock %} 125 {% endblock %}
192</div> 126 </div>
193</div> 127 </div>
194</body> 128 </body>
195</html> 129</html>
196
diff --git a/bitbake/lib/toaster/toastergui/templates/projecttopbar.html b/bitbake/lib/toaster/toastergui/templates/projecttopbar.html
index d8f7cbdbe8..8b44acccfd 100644
--- a/bitbake/lib/toaster/toastergui/templates/projecttopbar.html
+++ b/bitbake/lib/toaster/toastergui/templates/projecttopbar.html
@@ -1,3 +1,21 @@
1{% load static %}
2<script src="{% static 'js/projecttopbar.js' %}"></script>
3<script>
4 $(document).ready(function () {
5 var ctx = {
6 numProjectLayers : {{project.get_project_layer_versions.count}},
7 machine : "{{project.get_current_machine_name|default_if_none:""}}",
8 }
9
10 try {
11 projectTopBarInit(ctx);
12 } catch (e) {
13 document.write("Sorry, An error has occurred loading this page");
14 console.warn(e);
15 }
16 });
17</script>
18
1<div class="alert alert-success lead" id="project-created-notification" style="margin-top:15px; display:none"> 19<div class="alert alert-success lead" id="project-created-notification" style="margin-top:15px; display:none">
2 <button type="button" class="close" data-dismiss="alert">×</button> 20 <button type="button" class="close" data-dismiss="alert">×</button>
3 Your project <strong>{{project.name}}</strong> has been created. You can now <a href="{% url 'projectmachines' project.id %}">select your target machine</a> and <a href="{% url 'projectsoftwarerecipes' project.id %}">choose image recipes</a> to build. 21 Your project <strong>{{project.name}}</strong> has been created. You can now <a href="{% url 'projectmachines' project.id %}">select your target machine</a> and <a href="{% url 'projectsoftwarerecipes' project.id %}">choose image recipes</a> to build.