diff options
author | Michael Wood <michael.g.wood@intel.com> | 2015-07-31 15:09:12 +0300 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-08-01 11:26:12 +0100 |
commit | 80c1586bbb7f661f37754de5ba637c8d6e2185de (patch) | |
tree | 56011e83e1f192a68f4e9014ca266dd6cd76c719 /bitbake/lib/toaster/toastergui/static | |
parent | 258c929973e233f212938ea69eec8f83f3285854 (diff) | |
download | poky-80c1586bbb7f661f37754de5ba637c8d6e2185de.tar.gz |
bitbake: toastergui: Add new project page and navigation
This brings in the new project page design and improved navigation. As
this also removes the dependency on Angular it also required that the
entry points to the project page such as machine-change notifications
are also updated.
[YOCTO #7329]
(Bitbake rev: 6489e6eb5c3b0d59063b6d60521fc33fe563e707)
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/toastergui/static')
5 files changed, 485 insertions, 49 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/base.js b/bitbake/lib/toaster/toastergui/static/js/base.js index 6fd77ea457..0fb1f8b6bf 100644 --- a/bitbake/lib/toaster/toastergui/static/js/base.js +++ b/bitbake/lib/toaster/toastergui/static/js/base.js | |||
@@ -6,13 +6,20 @@ function basePageInit(ctx) { | |||
6 | var newBuildTargetInput; | 6 | var newBuildTargetInput; |
7 | var newBuildTargetBuildBtn; | 7 | var newBuildTargetBuildBtn; |
8 | 8 | ||
9 | /* initially the current project is used unless overridden by the new build | ||
10 | * button in top right nav | ||
11 | */ | ||
9 | var selectedProject = libtoaster.ctx; | 12 | var selectedProject = libtoaster.ctx; |
13 | |||
10 | var selectedTarget; | 14 | var selectedTarget; |
11 | 15 | ||
12 | var newBuildProjectInput = $("#new-build-button #project-name-input"); | 16 | var newBuildProjectInput = $("#new-build-button #project-name-input"); |
13 | var newBuildProjectSaveBtn = $("#new-build-button #save-project-button"); | 17 | var newBuildProjectSaveBtn = $("#new-build-button #save-project-button"); |
14 | 18 | ||
15 | $("#config-nav .nav li a").each(function(){ | 19 | |
20 | _checkProjectBuildable(); | ||
21 | |||
22 | $("#project-topbar .nav li a").each(function(){ | ||
16 | if (window.location.pathname === $(this).attr('href')) | 23 | if (window.location.pathname === $(this).attr('href')) |
17 | $(this).parent().addClass('active'); | 24 | $(this).parent().addClass('active'); |
18 | else | 25 | else |
@@ -26,7 +33,7 @@ function basePageInit(ctx) { | |||
26 | }); | 33 | }); |
27 | } | 34 | } |
28 | 35 | ||
29 | /* Hide the button if we're on the project,newproject or importlyaer page | 36 | /* Hide the button if we're on the project,newproject or importlyaer page |
30 | * or if there are no projects yet defined | 37 | * or if there are no projects yet defined |
31 | * only show if there isn't already a build-target-input already | 38 | * only show if there isn't already a build-target-input already |
32 | */ | 39 | */ |
@@ -37,8 +44,8 @@ function basePageInit(ctx) { | |||
37 | newBuildTargetInput = $("#new-build-button .build-target-input"); | 44 | newBuildTargetInput = $("#new-build-button .build-target-input"); |
38 | newBuildTargetBuildBtn = $("#new-build-button .build-button"); | 45 | newBuildTargetBuildBtn = $("#new-build-button .build-button"); |
39 | 46 | ||
40 | newBuildButton.show(); | ||
41 | _setupNewBuildButton(); | 47 | _setupNewBuildButton(); |
48 | newBuildButton.show(); | ||
42 | } else if ($(".build-target-input").length > 0) { | 49 | } else if ($(".build-target-input").length > 0) { |
43 | newBuildTargetInput = $("#project-topbar .build-target-input"); | 50 | newBuildTargetInput = $("#project-topbar .build-target-input"); |
44 | newBuildTargetBuildBtn = $("#project-topbar .build-button"); | 51 | newBuildTargetBuildBtn = $("#project-topbar .build-button"); |
@@ -52,9 +59,35 @@ function basePageInit(ctx) { | |||
52 | $('#project .icon-pencil').hide(); | 59 | $('#project .icon-pencil').hide(); |
53 | } | 60 | } |
54 | 61 | ||
62 | libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.projectTargetsUrl, { format: "json" }, function (item) { | ||
63 | /* successfully selected a target */ | ||
64 | selectedTarget = item; | ||
65 | }); | ||
55 | 66 | ||
56 | _checkProjectBuildable(); | 67 | newBuildTargetInput.on('input', function () { |
68 | if ($(this).val().length === 0) { | ||
69 | newBuildTargetBuildBtn.attr("disabled", "disabled"); | ||
70 | } else { | ||
71 | newBuildTargetBuildBtn.removeAttr("disabled"); | ||
72 | } | ||
73 | }); | ||
74 | |||
75 | newBuildTargetBuildBtn.click(function (e) { | ||
76 | e.preventDefault(); | ||
77 | |||
78 | if (!newBuildTargetInput.val()) { | ||
79 | return; | ||
80 | } | ||
57 | 81 | ||
82 | if (!selectedTarget) { | ||
83 | selectedTarget = { name: newBuildTargetInput.val() }; | ||
84 | } | ||
85 | /* Fire off the build */ | ||
86 | libtoaster.startABuild(selectedProject.projectBuildsUrl, | ||
87 | selectedProject.projectId, selectedTarget.name, function(){ | ||
88 | window.location.replace(selectedProject.projectBuildsUrl); | ||
89 | }, null); | ||
90 | }); | ||
58 | 91 | ||
59 | function _checkProjectBuildable() { | 92 | function _checkProjectBuildable() { |
60 | if (selectedProject.projectId === undefined) { | 93 | if (selectedProject.projectId === undefined) { |
@@ -74,21 +107,12 @@ function basePageInit(ctx) { | |||
74 | /* we can build this project; enable input fields */ | 107 | /* we can build this project; enable input fields */ |
75 | newBuildTargetInput.prop("disabled", false); | 108 | newBuildTargetInput.prop("disabled", false); |
76 | newBuildTargetBuildBtn.prop("disabled", false); | 109 | newBuildTargetBuildBtn.prop("disabled", false); |
77 | 110 | } | |
78 | libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.projectTargetsUrl, { format: "json" }, function (item) { | ||
79 | /* successfully selected a target */ | ||
80 | selectedProject.projectPageUrl = item.projectPageUrl; | ||
81 | selectedProject.projectName = item.name; | ||
82 | selectedProject.projectId = item.id; | ||
83 | selectedProject.projectBuildsUrl = item.projectBuildsUrl; | ||
84 | }); | ||
85 | |||
86 | } | ||
87 | }, null); | 111 | }, null); |
88 | } | 112 | } |
89 | 113 | ||
114 | /* Setup New build button in the top nav bar */ | ||
90 | function _setupNewBuildButton() { | 115 | function _setupNewBuildButton() { |
91 | /* Setup New build button */ | ||
92 | 116 | ||
93 | /* If we don't have a current project then present the set project | 117 | /* If we don't have a current project then present the set project |
94 | * form. | 118 | * form. |
@@ -98,7 +122,6 @@ function basePageInit(ctx) { | |||
98 | $('#project .icon-pencil').hide(); | 122 | $('#project .icon-pencil').hide(); |
99 | } | 123 | } |
100 | 124 | ||
101 | |||
102 | libtoaster.makeTypeahead(newBuildProjectInput, selectedProject.projectsUrl, { format : "json" }, function (item) { | 125 | libtoaster.makeTypeahead(newBuildProjectInput, selectedProject.projectsUrl, { format : "json" }, function (item) { |
103 | /* successfully selected a project */ | 126 | /* successfully selected a project */ |
104 | newBuildProjectSaveBtn.removeAttr("disabled"); | 127 | newBuildProjectSaveBtn.removeAttr("disabled"); |
@@ -115,40 +138,16 @@ function basePageInit(ctx) { | |||
115 | newBuildProjectSaveBtn.attr("disabled", "disabled"); | 138 | newBuildProjectSaveBtn.attr("disabled", "disabled"); |
116 | }); | 139 | }); |
117 | 140 | ||
118 | newBuildTargetInput.on('input', function () { | ||
119 | if ($(this).val().length === 0) { | ||
120 | newBuildTargetBuildBtn.attr("disabled", "disabled"); | ||
121 | } else { | ||
122 | newBuildTargetBuildBtn.removeAttr("disabled"); | ||
123 | } | ||
124 | }); | ||
125 | |||
126 | newBuildTargetBuildBtn.click(function () { | ||
127 | if (!newBuildTargetInput.val()) { | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | if (!selectedTarget) { | ||
132 | selectedTarget = { name: newBuildTargetInput.val() }; | ||
133 | } | ||
134 | /* fire and forget */ | ||
135 | libtoaster.startABuild(selectedProject.projectBuildsUrl, selectedProject.projectId, selectedTarget.name, null, null); | ||
136 | window.location.replace(selectedProject.projectPageUrl); | ||
137 | }); | ||
138 | 141 | ||
139 | newBuildProjectSaveBtn.click(function () { | 142 | newBuildProjectSaveBtn.click(function () { |
140 | selectedProject.projectId = selectedProject.pk; | 143 | selectedProject.projectId = selectedProject.pk; |
141 | /* Update the typeahead project_id paramater */ | 144 | /* Update the typeahead project_id paramater */ |
142 | _checkProjectBuildable(); | 145 | _checkProjectBuildable(); |
143 | 146 | ||
144 | /* we set the effective context of the page to the currently selected project */ | ||
145 | /* TBD: do we override even if we already have a context project ?? */ | ||
146 | /* TODO: replace global library context with references to the "selected" project */ | ||
147 | |||
148 | /* we can create a target typeahead only after we have a project selected */ | ||
149 | newBuildTargetInput.prop("disabled", false); | 147 | newBuildTargetInput.prop("disabled", false); |
150 | newBuildTargetBuildBtn.prop("disabled", false); | 148 | newBuildTargetBuildBtn.prop("disabled", false); |
151 | 149 | ||
150 | /* Update the typeahead to use the new selectedProject */ | ||
152 | libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.projectTargetsUrl, { format: "json" }, function (item) { | 151 | libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.projectTargetsUrl, { format: "json" }, function (item) { |
153 | /* successfully selected a target */ | 152 | /* successfully selected a target */ |
154 | selectedTarget = item; | 153 | selectedTarget = item; |
diff --git a/bitbake/lib/toaster/toastergui/static/js/importlayer.js b/bitbake/lib/toaster/toastergui/static/js/importlayer.js index 560e25a01c..03274c00f3 100644 --- a/bitbake/lib/toaster/toastergui/static/js/importlayer.js +++ b/bitbake/lib/toaster/toastergui/static/js/importlayer.js | |||
@@ -16,8 +16,6 @@ function importLayerPageInit (ctx) { | |||
16 | var currentLayerDepSelection; | 16 | var currentLayerDepSelection; |
17 | var validLayerName = /^(\w|-)+$/; | 17 | var validLayerName = /^(\w|-)+$/; |
18 | 18 | ||
19 | $("#new-project-button").hide(); | ||
20 | |||
21 | libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.projectLayersUrl, { include_added: "true" }, function(item){ | 19 | libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.projectLayersUrl, { include_added: "true" }, function(item){ |
22 | currentLayerDepSelection = item; | 20 | currentLayerDepSelection = item; |
23 | 21 | ||
@@ -154,7 +152,7 @@ function importLayerPageInit (ctx) { | |||
154 | } else { | 152 | } else { |
155 | /* Success layer import now go to the project page */ | 153 | /* Success layer import now go to the project page */ |
156 | $.cookie('layer-imported-alert', JSON.stringify(data), { path: '/'}); | 154 | $.cookie('layer-imported-alert', JSON.stringify(data), { path: '/'}); |
157 | window.location.replace(libtoaster.ctx.projectPageUrl+'#/layerimported'); | 155 | window.location.replace(libtoaster.ctx.projectPageUrl+'?notify=layer-imported'); |
158 | } | 156 | } |
159 | }, | 157 | }, |
160 | error: function (data) { | 158 | error: function (data) { |
diff --git a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js index 291ed98c34..be6bbcd20f 100644 --- a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js +++ b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js | |||
@@ -16,14 +16,15 @@ function layerDetailsPageInit (ctx) { | |||
16 | }); | 16 | }); |
17 | 17 | ||
18 | $(".breadcrumb li:first a").click(function(e){ | 18 | $(".breadcrumb li:first a").click(function(e){ |
19 | e.preventDefault(); | ||
19 | /* By default this link goes to the project configuration page. However | 20 | /* By default this link goes to the project configuration page. However |
20 | * if we have some builds we go there instead of the default href | 21 | * if we have some builds we go there instead of the default href |
21 | */ | 22 | */ |
22 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ | 23 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ |
23 | if (prjInfo.builds && prjInfo.builds.length > 0) { | 24 | if (prjInfo.builds && prjInfo.builds.length > 0) { |
24 | window.location.replace(libtoaster.ctx.projectBuildsUrl); | 25 | window.location.replace(libtoaster.ctx.projectBuildsUrl); |
25 | e.preventDefault(); | 26 | } else { |
26 | return; | 27 | window.location.replace(libtoaster.ctx.projectPageUrl); |
27 | } | 28 | } |
28 | }); | 29 | }); |
29 | }); | 30 | }); |
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js index afd665ca99..079bbcb0b8 100644 --- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js +++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js | |||
@@ -79,11 +79,12 @@ var libtoaster = (function (){ | |||
79 | data: data, | 79 | data: data, |
80 | headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, | 80 | headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, |
81 | success: function (_data) { | 81 | success: function (_data) { |
82 | /* No proper reponse YOCTO #7995 | ||
82 | if (_data.error !== "ok") { | 83 | if (_data.error !== "ok") { |
83 | console.warn(_data.error); | 84 | console.warn(_data.error); |
84 | } else { | 85 | } else { */ |
85 | if (onsuccess !== undefined) onsuccess(_data); | 86 | if (onsuccess !== undefined) onsuccess(_data); |
86 | } | 87 | // } |
87 | }, | 88 | }, |
88 | error: function (_data) { | 89 | error: function (_data) { |
89 | console.warn("Call failed"); | 90 | console.warn("Call failed"); |
@@ -180,7 +181,15 @@ var libtoaster = (function (){ | |||
180 | if (onFail !== undefined) | 181 | if (onFail !== undefined) |
181 | onFail(data); | 182 | onFail(data); |
182 | } else { | 183 | } else { |
183 | onSuccess(data.layerdeps); | 184 | var deps = {}; |
185 | /* Filter out layer dep ids which are in the | ||
186 | * project already. | ||
187 | */ | ||
188 | deps.list = data.layerdeps.list.filter(function(layerObj){ | ||
189 | return (data.projectlayers.lastIndexOf(layerObj.id) < 0); | ||
190 | }); | ||
191 | |||
192 | onSuccess(deps); | ||
184 | } | 193 | } |
185 | }, function() { | 194 | }, function() { |
186 | console.log("E: Failed to make request"); | 195 | console.log("E: Failed to make request"); |
diff --git a/bitbake/lib/toaster/toastergui/static/js/projectpage.js b/bitbake/lib/toaster/toastergui/static/js/projectpage.js new file mode 100644 index 0000000000..b7cb074f11 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/static/js/projectpage.js | |||
@@ -0,0 +1,429 @@ | |||
1 | "use strict"; | ||
2 | |||
3 | function projectPageInit(ctx) { | ||
4 | |||
5 | var layerAddInput = $("#layer-add-input"); | ||
6 | var layersInPrjList = $("#layers-in-project-list"); | ||
7 | var layerAddBtn = $("#add-layer-btn"); | ||
8 | |||
9 | var machineChangeInput = $("#machine-change-input"); | ||
10 | var machineChangeBtn = $("#machine-change-btn"); | ||
11 | var machineForm = $("#select-machine-form"); | ||
12 | var machineChangeFormToggle = $("#change-machine-toggle"); | ||
13 | var machineNameTitle = $("#project-machine-name"); | ||
14 | var machineChangeCancel = $("#cancel-machine-change"); | ||
15 | |||
16 | var freqBuildBtn = $("#freq-build-btn"); | ||
17 | var freqBuildList = $("#freq-build-list"); | ||
18 | |||
19 | var releaseChangeFormToggle = $("#release-change-toggle"); | ||
20 | var releaseTitle = $("#project-release-title"); | ||
21 | var releaseForm = $("#change-release-form"); | ||
22 | var releaseModal = $("#change-release-modal"); | ||
23 | var cancelReleaseChange = $("#cancel-release-change"); | ||
24 | |||
25 | var currentLayerAddSelection; | ||
26 | var currentMachineAddSelection = {}; | ||
27 | |||
28 | var urlParams = libtoaster.parseUrlParams(); | ||
29 | |||
30 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ | ||
31 | updateProjectLayers(prjInfo.layers); | ||
32 | updateFreqBuildRecipes(prjInfo.freqtargets); | ||
33 | updateProjectRelease(prjInfo.release); | ||
34 | updateProjectReleases(prjInfo.releases, prjInfo.release); | ||
35 | |||
36 | /* If we're receiving a machine set from the url and it's different from | ||
37 | * our current machine then activate set machine sequence. | ||
38 | */ | ||
39 | if (urlParams.hasOwnProperty('setMachine') && | ||
40 | urlParams.setMachine !== prjInfo.machine.name){ | ||
41 | currentMachineAddSelection.name = urlParams.setMachine; | ||
42 | machineChangeBtn.click(); | ||
43 | } else { | ||
44 | updateMachineName(prjInfo.machine.name); | ||
45 | } | ||
46 | |||
47 | /* Now we're really ready show the page */ | ||
48 | $("#project-page").show(); | ||
49 | }); | ||
50 | |||
51 | (function notificationRequest(){ | ||
52 | |||
53 | if (urlParams.hasOwnProperty('notify')){ | ||
54 | switch (urlParams.notify){ | ||
55 | case 'new-project': | ||
56 | $("#project-created-notification").show(); | ||
57 | break; | ||
58 | case 'layer-imported': | ||
59 | layerImportedNotification(); | ||
60 | break; | ||
61 | default: | ||
62 | break; | ||
63 | } | ||
64 | } | ||
65 | })(); | ||
66 | |||
67 | /* Layer imported notification */ | ||
68 | function layerImportedNotification(){ | ||
69 | var imported = $.cookie("layer-imported-alert"); | ||
70 | var message = "Layer imported"; | ||
71 | |||
72 | if (!imported) | ||
73 | return; | ||
74 | else | ||
75 | imported = JSON.parse(imported); | ||
76 | |||
77 | if (imported.deps_added.length === 0) { | ||
78 | message = "You have imported <strong><a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a></strong> and added it to your project."; | ||
79 | } else { | ||
80 | |||
81 | var links = "<a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a>, "; | ||
82 | |||
83 | imported.deps_added.map (function(item, index){ | ||
84 | links +='<a href="'+item.layerdetailurl+'">'+item.name+'</a>'; | ||
85 | /*If we're at the last element we don't want the trailing comma */ | ||
86 | if (imported.deps_added[index+1] !== undefined) | ||
87 | links += ', '; | ||
88 | }); | ||
89 | |||
90 | /* Length + 1 here to do deps + the imported layer */ | ||
91 | message = 'You have imported <strong><a href="'+imported.imported_layer.layerdetailurl+'">'+imported.imported_layer.name+'</a></strong> and added <strong>'+(imported.deps_added.length+1)+'</strong> layers to your project: <strong>'+links+'</strong>'; | ||
92 | } | ||
93 | |||
94 | libtoaster.showChangeNotification(message); | ||
95 | |||
96 | $.removeCookie("layer-imported-alert", { path: "/"}); | ||
97 | } | ||
98 | |||
99 | /* Add/Rm layer functionality */ | ||
100 | |||
101 | libtoaster.makeTypeahead(layerAddInput, libtoaster.ctx.projectLayersUrl, { include_added: "false" }, function(item){ | ||
102 | currentLayerAddSelection = item; | ||
103 | layerAddBtn.removeAttr("disabled"); | ||
104 | }); | ||
105 | |||
106 | layerAddBtn.click(function(e){ | ||
107 | e.preventDefault(); | ||
108 | var layerObj = currentLayerAddSelection; | ||
109 | |||
110 | addRmLayer(layerObj, true); | ||
111 | /* Reset the text input */ | ||
112 | layerAddInput.val(""); | ||
113 | }); | ||
114 | |||
115 | function addRmLayer(layerObj, add){ | ||
116 | |||
117 | libtoaster.addRmLayer(layerObj, add, function(layerDepsList){ | ||
118 | if (add){ | ||
119 | updateProjectLayers([layerObj]); | ||
120 | updateProjectLayers(layerDepsList); | ||
121 | } | ||
122 | |||
123 | /* Show the alert message */ | ||
124 | var message = libtoaster.makeLayerAddRmAlertMsg(layerObj, layerDepsList, add); | ||
125 | libtoaster.showChangeNotification(message); | ||
126 | }); | ||
127 | } | ||
128 | |||
129 | function updateProjectLayers(layers){ | ||
130 | |||
131 | /* No layers to add */ | ||
132 | if (layers.length === 0){ | ||
133 | updateLayersCount(); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | for (var i in layers){ | ||
138 | var layerObj = layers[i]; | ||
139 | |||
140 | var projectLayer = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>"); | ||
141 | |||
142 | projectLayer.data('layer', layerObj); | ||
143 | projectLayer.children("span").tooltip(); | ||
144 | |||
145 | var link = projectLayer.children("a"); | ||
146 | |||
147 | link.attr("href", layerObj.layerdetailurl); | ||
148 | link.text(layerObj.name); | ||
149 | /* YOCTO #8024 | ||
150 | link.tooltip({title: layerObj.giturl + " | "+ layerObj.branch.name, placement: "right"}); | ||
151 | branch name not accessible sometimes it is revision instead | ||
152 | */ | ||
153 | |||
154 | var trashItem = projectLayer.children("span"); | ||
155 | trashItem.click(function (e) { | ||
156 | e.preventDefault(); | ||
157 | var layerObjToRm = $(this).parent().data('layer'); | ||
158 | |||
159 | addRmLayer(layerObjToRm, false); | ||
160 | |||
161 | $(this).parent().fadeOut(function (){ | ||
162 | $(this).remove(); | ||
163 | updateLayersCount(); | ||
164 | }); | ||
165 | }); | ||
166 | |||
167 | layersInPrjList.append(projectLayer); | ||
168 | |||
169 | updateLayersCount(); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | function updateLayersCount(){ | ||
174 | var count = $("#layers-in-project-list").children().length; | ||
175 | |||
176 | if (count === 0) | ||
177 | $("#no-layers-in-project").fadeIn(); | ||
178 | else | ||
179 | $("#no-layers-in-project").hide(); | ||
180 | |||
181 | $("#project-layers-count").text(count); | ||
182 | |||
183 | return count; | ||
184 | } | ||
185 | |||
186 | /* Frequent builds functionality */ | ||
187 | function updateFreqBuildRecipes(recipes) { | ||
188 | var noMostBuilt = $("#no-most-built"); | ||
189 | |||
190 | if (recipes.length === 0){ | ||
191 | noMostBuilt.show(); | ||
192 | freqBuildBtn.hide(); | ||
193 | } else { | ||
194 | noMostBuilt.hide(); | ||
195 | freqBuildBtn.show(); | ||
196 | } | ||
197 | |||
198 | for (var i in recipes){ | ||
199 | var freqTargetCheck = $('<li><label class="checkbox"><input type="checkbox" /><span class="freq-target-name"></span></label></li>'); | ||
200 | freqTargetCheck.find(".freq-target-name").text(recipes[i]); | ||
201 | freqTargetCheck.find("input").val(recipes[i]); | ||
202 | freqTargetCheck.click(function(){ | ||
203 | if (freqBuildList.find(":checked").length > 0) | ||
204 | freqBuildBtn.removeAttr("disabled"); | ||
205 | else | ||
206 | freqBuildBtn.attr("disabled", "disabled"); | ||
207 | }); | ||
208 | |||
209 | freqBuildList.append(freqTargetCheck); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | freqBuildBtn.click(function(e){ | ||
214 | e.preventDefault(); | ||
215 | |||
216 | var toBuild = ""; | ||
217 | freqBuildList.find(":checked").each(function(){ | ||
218 | toBuild += $(this).val(); | ||
219 | toBuild += " "; | ||
220 | }); | ||
221 | |||
222 | libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl, libtoaster.ctx.projectId, toBuild, function(){ | ||
223 | /* Build started */ | ||
224 | window.location.replace(libtoaster.ctx.projectBuildsUrl); | ||
225 | }, | ||
226 | function(){ | ||
227 | /* Build start failed */ | ||
228 | /* [YOCTO #7995] */ | ||
229 | window.location.replace(libtoaster.ctx.projectBuildsUrl); | ||
230 | }); | ||
231 | }); | ||
232 | |||
233 | |||
234 | /* Change machine functionality */ | ||
235 | |||
236 | machineChangeFormToggle.click(function(){ | ||
237 | machineForm.slideDown(); | ||
238 | machineNameTitle.hide(); | ||
239 | $(this).hide(); | ||
240 | }); | ||
241 | |||
242 | machineChangeCancel.click(function(){ | ||
243 | machineForm.slideUp(function(){ | ||
244 | machineNameTitle.show(); | ||
245 | machineChangeFormToggle.show(); | ||
246 | }); | ||
247 | }); | ||
248 | |||
249 | function updateMachineName(machineName){ | ||
250 | machineChangeInput.val(machineName); | ||
251 | machineNameTitle.text(machineName); | ||
252 | } | ||
253 | |||
254 | libtoaster.makeTypeahead(machineChangeInput, libtoaster.ctx.projectMachinesUrl, { }, function(item){ | ||
255 | currentMachineAddSelection = item; | ||
256 | machineChangeBtn.removeAttr("disabled"); | ||
257 | }); | ||
258 | |||
259 | machineChangeBtn.click(function(e){ | ||
260 | e.preventDefault(); | ||
261 | if (currentMachineAddSelection.name === undefined) | ||
262 | return; | ||
263 | |||
264 | libtoaster.editCurrentProject({ machineName : currentMachineAddSelection.name }, | ||
265 | function(){ | ||
266 | /* Success machine changed */ | ||
267 | updateMachineName(currentMachineAddSelection.name); | ||
268 | machineChangeCancel.click(); | ||
269 | |||
270 | /* Show the alert message */ | ||
271 | var message = $('<span class="lead">You have changed the machine to: <strong><span id="notify-machine-name"></span></strong></span>'); | ||
272 | message.find("#notify-machine-name").text(currentMachineAddSelection.name); | ||
273 | libtoaster.showChangeNotification(message); | ||
274 | }, | ||
275 | function(){ | ||
276 | /* Failed machine changed */ | ||
277 | console.log("failed to change machine"); | ||
278 | }); | ||
279 | }); | ||
280 | |||
281 | |||
282 | /* Change release functionality */ | ||
283 | function updateProjectRelease(release){ | ||
284 | releaseTitle.text(release.description); | ||
285 | } | ||
286 | |||
287 | function updateProjectReleases(releases, current){ | ||
288 | for (var i in releases){ | ||
289 | var releaseOption = $("<option></option>"); | ||
290 | |||
291 | releaseOption.val(releases[i].id); | ||
292 | releaseOption.text(releases[i].description); | ||
293 | releaseOption.data('release', releases[i]); | ||
294 | |||
295 | if (releases[i].id == current.id) | ||
296 | releaseOption.attr("selected", "selected"); | ||
297 | |||
298 | releaseForm.children("select").append(releaseOption); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | releaseChangeFormToggle.click(function(){ | ||
303 | releaseForm.slideDown(); | ||
304 | releaseTitle.hide(); | ||
305 | $(this).hide(); | ||
306 | }); | ||
307 | |||
308 | cancelReleaseChange.click(function(e){ | ||
309 | e.preventDefault(); | ||
310 | releaseForm.slideUp(function(){ | ||
311 | releaseTitle.show(); | ||
312 | releaseChangeFormToggle.show(); | ||
313 | }); | ||
314 | }); | ||
315 | |||
316 | function changeProjectRelease(release, layersToRm){ | ||
317 | libtoaster.editCurrentProject({ projectVersion : release.id }, | ||
318 | function(){ | ||
319 | /* Success */ | ||
320 | /* Update layers list with new layers */ | ||
321 | layersInPrjList.addClass('muted'); | ||
322 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, | ||
323 | function(prjInfo){ | ||
324 | layersInPrjList.children().remove(); | ||
325 | updateProjectLayers(prjInfo.layers); | ||
326 | layersInPrjList.removeClass('muted'); | ||
327 | releaseChangedNotification(release, prjInfo.layers, layersToRm); | ||
328 | }); | ||
329 | updateProjectRelease(release); | ||
330 | cancelReleaseChange.click(); | ||
331 | }); | ||
332 | } | ||
333 | |||
334 | /* Create a notification to show the changes to the layer configuration | ||
335 | * caused by changing a release. | ||
336 | */ | ||
337 | |||
338 | function releaseChangedNotification(release, layers, layersToRm){ | ||
339 | |||
340 | var message; | ||
341 | |||
342 | if (layers.length === 0 && layersToRm.length === 0){ | ||
343 | message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>.'); | ||
344 | message.find("#notify-release-name").text(release.description); | ||
345 | libtoaster.showChangeNotification(message); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | /* Create the whitespace separated list of layers removed */ | ||
350 | var layersDelList = ""; | ||
351 | |||
352 | layersToRm.map(function(layer, i){ | ||
353 | layersDelList += layer.name; | ||
354 | if (layersToRm[i+1] !== undefined) | ||
355 | layersDelList += ', '; | ||
356 | }); | ||
357 | |||
358 | message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>. This has caused the following changes in your project layers:</span><ul id="notify-layers-changed-list"></ul></span>'); | ||
359 | |||
360 | var changedList = message.find("#notify-layers-changed-list"); | ||
361 | |||
362 | message.find("#notify-release-name").text(release.description); | ||
363 | |||
364 | /* Manually construct the list item for changed layers */ | ||
365 | var li = '<li><strong>'+layers.length+'</strong> layers changed to the <strong>'+release.name+'</strong> release: '; | ||
366 | for (var i in layers){ | ||
367 | li += '<a href='+layers[i].layerdetailurl+'>'+layers[i].name+'</a>'; | ||
368 | if (i !== 0) | ||
369 | li += ', '; | ||
370 | } | ||
371 | |||
372 | changedList.append($(li)); | ||
373 | |||
374 | /* Layers removed */ | ||
375 | if (layersToRm && layersToRm.length > 0){ | ||
376 | if (layersToRm.length == 1) | ||
377 | li = '<li><strong>1</strong> layer deleted: '+layersToRm[0].name+'</li>'; | ||
378 | else | ||
379 | li = '<li><strong>'+layersToRm.length+'</strong> layers deleted: '+layersDelList+'</li>'; | ||
380 | |||
381 | changedList.append($(li)); | ||
382 | } | ||
383 | |||
384 | libtoaster.showChangeNotification(message); | ||
385 | } | ||
386 | |||
387 | /* Show the modal dialog which gives the option to remove layers which | ||
388 | * aren't compatible with the proposed release | ||
389 | */ | ||
390 | function showReleaseLayerChangeModal(release, layers){ | ||
391 | var layersToRmList = releaseModal.find("#layers-to-remove-list"); | ||
392 | layersToRmList.text(""); | ||
393 | |||
394 | releaseModal.find(".proposed-release-change-name").text(release.description); | ||
395 | releaseModal.data("layers", layers); | ||
396 | releaseModal.data("release", release); | ||
397 | |||
398 | for (var i in layers){ | ||
399 | layersToRmList.append($("<li></li>").text(layers[i].name)); | ||
400 | } | ||
401 | releaseModal.modal('show'); | ||
402 | } | ||
403 | |||
404 | $("#change-release-btn").click(function(e){ | ||
405 | e.preventDefault(); | ||
406 | |||
407 | var newRelease = releaseForm.find("option:selected").data('release'); | ||
408 | |||
409 | $.getJSON(ctx.typeaheadUrl, | ||
410 | { search: newRelease.id, type: "versionlayers" }, | ||
411 | function(layers) { | ||
412 | if (layers.rows.length === 0){ | ||
413 | /* No layers to change for this release */ | ||
414 | changeProjectRelease(newRelease, []); | ||
415 | } else { | ||
416 | showReleaseLayerChangeModal(newRelease, layers.rows); | ||
417 | } | ||
418 | }); | ||
419 | }); | ||
420 | |||
421 | /* Release change modal accept */ | ||
422 | $("#change-release-and-rm-layers").click(function(){ | ||
423 | var layers = releaseModal.data("layers"); | ||
424 | var release = releaseModal.data("release"); | ||
425 | |||
426 | changeProjectRelease(release, layers); | ||
427 | }); | ||
428 | |||
429 | } | ||