utils.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. var multipleClustersSupported = false;
  22. /* Allows 'this' to be bound statically.
  23. *
  24. * Primarily used when creating objects whose methods will be used as
  25. * callbacks in unknown contexts.
  26. */
  27. Function.prototype.bind = function(scope) {
  28. var _function = this;
  29. return function() {
  30. return _function.apply(scope, arguments);
  31. };
  32. };
  33. var globalSingletonInformationalPanel;
  34. function createInformationalPanel( containerNodeId, headerContentString ) {
  35. /* XXX This should check that globalSingletonInformationalPanel is within
  36. * containerNodeId, and only then perform this cleanup, but this whole
  37. * panel-related section needs to be rewritten anyway - for now, we only
  38. * support the one globalSingletonInformationalPanel, and passing in
  39. * anything other than #informationalPanelContainerDivId as containerNodeId
  40. * is not guaranteed to work.
  41. */
  42. if( globalSingletonInformationalPanel ) {
  43. destroyInformationalPanel( globalSingletonInformationalPanel );
  44. }
  45. globalYui.one( containerNodeId ).append('<div id="informationalPanelInnerContainerDivId"></div>');
  46. var newPanel = new globalYui.Panel({
  47. srcNode: '#informationalPanelInnerContainerDivId',
  48. headerContent: headerContentString,
  49. width: 800,
  50. height: 400,
  51. render: true,
  52. modal: true,
  53. zIndex: 100,
  54. centered: true,
  55. visible: false
  56. });
  57. globalSingletonInformationalPanel = newPanel;
  58. return newPanel;
  59. }
  60. function destroyInformationalPanel( theInformationalPanelInstance ) {
  61. if( theInformationalPanelInstance ) {
  62. theInformationalPanelInstance.hide();
  63. theInformationalPanelInstance.destroy();
  64. if( theInformationalPanelInstance === globalSingletonInformationalPanel ) {
  65. globalSingletonInformationalPanel = null;
  66. }
  67. }
  68. }
  69. function showLoadingImg() {
  70. globalYui.one("#loadingDivId").show();
  71. }
  72. function hideLoadingImg() {
  73. globalYui.one("#loadingDivId").hide();
  74. }
  75. function swapStageVisibilities( currentStageDivSelector, newStageDivSelector ) {
  76. globalYui.log("In swapStageVisibilities: " + currentStageDivSelector + "->" + newStageDivSelector);
  77. /* Hide the current stage. */
  78. globalYui.one(currentStageDivSelector).hide();
  79. /* Show the new stage. */
  80. globalYui.one(newStageDivSelector).show();
  81. }
  82. /* TODO XXX Consider bundling the last 3 parameters into their own NewStage object.
  83. * TODO XXX Do the same for the first 2 parameters and a CurrentStage object.
  84. */
  85. function transitionToNextStage( currentStageDivSelector, currentStageData, newStageDivSelector, newStageData, newStageRenderFunction ) {
  86. clearFormStatus();
  87. globalYui.one(currentStageDivSelector).hide();
  88. /* Render the next stage. */
  89. newStageRenderFunction(newStageData);
  90. globalYui.log("In transitionToNextStage: " + currentStageDivSelector + "->" + newStageDivSelector);
  91. //// tshooter: No longer doing this given dynamic rendering on stages. Only hide current stage.
  92. /* And make it visibly replace the currently showing one. */
  93. ///// tshooter: commented: swapStageVisibilities(currentStageDivSelector, newStageDivSelector);
  94. /* And now, handle the updates to addNodesWizardStages... */
  95. /* There can be only one 'current' stage at a time. */
  96. var currentStage = globalYui.one('.installationWizardCurrentStage');
  97. if ( currentStage ) {
  98. var nextStage = null;
  99. /* Check to make sure we haven't reached the last stage. */
  100. if( nextStage = currentStage.next('.installationWizardUnvisitedStage') ) {
  101. /* Mark this up-until-now 'current' stage as 'visited'. */
  102. currentStage.replaceClass( 'installationWizardCurrentStage', 'installationWizardVisitedStage' );
  103. /* Mark the stage after that as the new 'current' stage. */
  104. nextStage.replaceClass( 'installationWizardUnvisitedStage', 'installationWizardCurrentStage' );
  105. }
  106. }
  107. }
  108. function clearFormStatus() {
  109. var formStatusDiv = globalYui.all("#formStatusDivId");
  110. // formStatusDiv.setContent("");
  111. formStatusDiv.setStyle("visibility", "hidden");
  112. formStatusDiv.hide();
  113. formStatusDiv.set('className','');
  114. formStatusDiv.addClass("formStatusBar");
  115. }
  116. function setFormStatus(statusString, isError, noFade) {
  117. var formStatusDivCssClass;
  118. if (isError) {
  119. formStatusDivCssClass = 'statusError';
  120. } else {
  121. formStatusDivCssClass = 'statusOk';
  122. }
  123. var formStatusDiv = globalYui.all("#formStatusDivId");
  124. formStatusDiv.setStyle("visibility", "visible");
  125. formStatusDiv.show();
  126. formStatusDiv.set('className','');
  127. formStatusDiv.addClass("formStatusBar");
  128. formStatusDiv.addClass(formStatusDivCssClass);
  129. formStatusDiv.setContent(statusString);
  130. if (!isError && !noFade) {
  131. //setTimeout(fadeFormStatus, 1000);
  132. }
  133. }
  134. function fadeFormStatus() {
  135. var formStatusDiv = globalYui.one("#formStatusDivId");
  136. formStatusDiv.addClass("formStatusBarZeroOpacity");
  137. }
  138. function convertDisplayType (displayType) {
  139. switch (displayType) {
  140. case "NODISPLAY":
  141. return "NODISPLAY";
  142. case "TEXT":
  143. return "text";
  144. case "SECRET":
  145. return "password";
  146. case "ONOFF":
  147. return "checkbox";
  148. default:
  149. return "text";
  150. }
  151. }
  152. function executeStage(inputUrl, renderStageFunction) {
  153. globalYui.io(inputUrl, {
  154. method: 'GET',
  155. timeout : 10000,
  156. on: {
  157. success: function (x,o) {
  158. globalYui.log("RAW JSON DATA: " + o.responseText);
  159. // Process the JSON data returned from the server
  160. try {
  161. responseJson = globalYui.JSON.parse(o.responseText);
  162. }
  163. catch (e) {
  164. hideLoadingImg();
  165. alert("JSON Parse failed!");
  166. return;
  167. }
  168. globalYui.log("PARSED DATA: " + globalYui.Lang.dump(responseJson));
  169. if (responseJson.result != 0) {
  170. hideLoadingImg();
  171. // Error!
  172. alert("Got error during getting data: " + responseJson.error);
  173. return;
  174. }
  175. responseJson = responseJson.response;
  176. renderStageFunction(responseJson);
  177. hideLoadingImg();
  178. return;
  179. },
  180. failure: function (x,o) {
  181. alert("Async call failed!");
  182. return;
  183. }
  184. }
  185. });
  186. }
  187. function submitDataAndProgressToNextScreen(url, requestData, submitButton, thisScreenId, nextScreenId, nextScreenRenderFunction, errorHandlerFunction) {
  188. showLoadingImg();
  189. globalYui.io(url, {
  190. method: 'POST',
  191. data: globalYui.JSON.stringify(requestData),
  192. timeout : 10000,
  193. on: {
  194. start: function(x, o) {
  195. submitButton.set('disabled', true);
  196. globalYui.log("In start function");
  197. // showLoadingImg();
  198. },
  199. complete: function(x, o) {
  200. submitButton.set('disabled', false);
  201. globalYui.log("In stop function");
  202. // hideLoadingImg();
  203. },
  204. success: function (x,o) {
  205. submitButton.set('disabled', false);
  206. globalYui.log("RAW JSON DATA: " + o.responseText);
  207. // Process the JSON data returned from the server
  208. try {
  209. responseJson = globalYui.JSON.parse(o.responseText);
  210. }
  211. catch (e) {
  212. submitButton.set('disabled', false);
  213. hideLoadingImg();
  214. alert("JSON Parse failed!");
  215. return;
  216. }
  217. globalYui.log("PARSED DATA: " + globalYui.Lang.dump(responseJson));
  218. if (responseJson.result != 0) {
  219. submitButton.set('disabled', false);
  220. // Error!
  221. globalYui.log("Got error during submit data!" + responseJson.error);
  222. if ( errorHandlerFunction ) {
  223. globalYui.log("Invoking error handler function");
  224. errorHandlerFunction(responseJson);
  225. } else {
  226. alert("Got error during submit data!" + responseJson.error);
  227. }
  228. hideLoadingImg();
  229. return;
  230. }
  231. responseJson = responseJson.response;
  232. /* Done with this stage, transition to the next. */
  233. transitionToNextStage( thisScreenId, requestData, nextScreenId, responseJson, nextScreenRenderFunction );
  234. },
  235. failure: function (x,o) {
  236. submitButton.set('disabled', false);
  237. alert("Async call failed!");
  238. }
  239. }
  240. });
  241. }
  242. function PeriodicDataPoller( dataSourceContext, responseHandler ) {
  243. this.dataSourceContext = dataSourceContext;
  244. /* Smoothe out the optional bits of this.dataSourceContext. */
  245. if( !this.dataSourceContext.pollInterval ) {
  246. /* How often we poll. */
  247. this.dataSourceContext.pollInterval = 5000;
  248. }
  249. if( !this.dataSourceContext.maxFailedAttempts ) {
  250. /* How many failed attempts before we stop polling. */
  251. this.dataSourceContext.maxFailedAttempts = 25;
  252. }
  253. this.responseHandler = responseHandler;
  254. /* Of course, we're not paused when we start off. */
  255. this.paused = false;
  256. this.dataSource = new globalYui.DataSource.IO ({
  257. source: this.dataSourceContext.source
  258. });
  259. this.dataSource.plug(globalYui.Plugin.DataSourceJSONSchema, {
  260. schema: this.dataSourceContext.schema
  261. });
  262. this.dataSourcePollFailureCount = 0;
  263. /* Set when start() is invoked. */
  264. this.dataSourcePollHandle = null;
  265. this.dataSourcePollRequestContext = {
  266. request: this.dataSourceContext.request,
  267. callback: {
  268. success: function (e) {
  269. /* Avoid race conditions in JS by not processing incoming responses
  270. * from the backend if the PDP is paused (which is our signal that
  271. * a previous response is still in the middle of being processed).
  272. */
  273. if( !(this.isPaused()) ) {
  274. /* Reset our failure count every time we succeed. */
  275. this.dataSourcePollFailureCount = 0;
  276. /* Invoke user-pluggable code. */
  277. if( this.responseHandler.success ) {
  278. this.responseHandler.success( e, this );
  279. }
  280. }
  281. }.bind(this),
  282. failure: function (e) {
  283. if( !(this.isPaused()) ) {
  284. ++this.dataSourcePollFailureCount;
  285. if( this.dataSourcePollFailureCount > this.dataSourceContext.maxFailedAttempts ) {
  286. /* Invoke user-pluggable code. */
  287. if( this.responseHandler.failure ) {
  288. this.responseHandler.failure( e, this );
  289. }
  290. /* No point making any more attempts. */
  291. this.stop();
  292. }
  293. }
  294. }.bind(this)
  295. }
  296. };
  297. }
  298. /* Start polling. */
  299. PeriodicDataPoller.prototype.start = function() {
  300. this.dataSourcePollHandle = this.dataSource.setInterval
  301. ( this.dataSourceContext.pollInterval, this.dataSourcePollRequestContext );
  302. }
  303. /* Stop polling. */
  304. PeriodicDataPoller.prototype.stop = function() {
  305. /* Always unPause() during stop(), so the next start() won't be neutered. */
  306. this.unPause();
  307. this.dataSource.clearInterval( this.dataSourcePollHandle );
  308. }
  309. /* When the PDP is paused, the polling continues on its regular fixed
  310. * interval, but this.responseHandler is not invoked, thus avoiding
  311. * a race condition (at least) in JS.
  312. *
  313. * TODO XXX Improve upon this to not even make calls to the backend
  314. * while not losing our periodicity.
  315. */
  316. PeriodicDataPoller.prototype.pause = function() {
  317. this.paused = true;
  318. }
  319. PeriodicDataPoller.prototype.unPause = function() {
  320. this.paused = false;
  321. }
  322. PeriodicDataPoller.prototype.isPaused = function() {
  323. return this.paused;
  324. }
  325. /* Perform a one-time poll.
  326. *
  327. * Meant to be used when the polling is not at a set frequency (as with the
  328. * start()/stop() pair), and is instead meant to be under explicit
  329. * control of the application.
  330. */
  331. PeriodicDataPoller.prototype.pollOnce = function() {
  332. globalYui.io(this.dataSourceContext.source + this.dataSourcePollRequestContext.request, {
  333. on: this.dataSourcePollRequestContext.callback
  334. });
  335. }
  336. function titleCase(word){
  337. return word.substr(0,1).toUpperCase() + word.substr(1).toLowerCase();
  338. }
  339. function generateHMCUrl( uriPath ) {
  340. var url = '';
  341. /* By default, go to the HMC home page. */
  342. uriPath = ( typeof uriPath == "undefined" ) ? '/hmc/html/index.php' : uriPath;
  343. var currentUrl = window.location.href;
  344. globalYui.log('Current URL: ' + currentUrl);
  345. var currentPathPos = currentUrl.indexOf(window.location.pathname);
  346. globalYui.log('Current Path Pos: ' + currentPathPos);
  347. if( -1 != currentPathPos ) {
  348. url = currentUrl.substr(0, currentPathPos) + uriPath;
  349. }
  350. return url;
  351. }