You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MessageHandler.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /* global $, APP, toastr, Impromptu */
  2. import UIUtil from './UIUtil';
  3. /**
  4. * Flag for enable/disable of the notifications.
  5. * @type {boolean}
  6. */
  7. let notificationsEnabled = true;
  8. /**
  9. * Flag for enabling/disabling popups.
  10. * @type {boolean}
  11. */
  12. let popupEnabled = true;
  13. /**
  14. * Currently displayed two button dialog.
  15. * @type {null}
  16. */
  17. let twoButtonDialog = null;
  18. var messageHandler = {
  19. OK: "dialog.OK",
  20. CANCEL: "dialog.Cancel",
  21. /**
  22. * Shows a message to the user.
  23. *
  24. * @param titleKey the key used to find the translation of the title of the
  25. * message, if a message title is not provided.
  26. * @param messageKey the key used to find the translation of the message,
  27. * if a message is not provided.
  28. * @param message the message to show. If a falsy value is provided,
  29. * messageKey will be used to get a message via the translation API.
  30. * @param closeFunction function to be called after
  31. * the prompt is closed (optional)
  32. * @return the prompt that was created, or null
  33. */
  34. openMessageDialog: function(titleKey, messageKey, message, closeFunction) {
  35. if (!popupEnabled)
  36. return null;
  37. if (!message) {
  38. message = APP.translation.generateTranslationHTML(messageKey);
  39. }
  40. let dialog = $.prompt(message, {
  41. title: this._getFormattedTitleString(titleKey),
  42. persistent: false,
  43. promptspeed: 0,
  44. classes: this._getDialogClasses(),
  45. close: function (e, v, m, f) {
  46. if(closeFunction)
  47. closeFunction(e, v, m, f);
  48. }
  49. });
  50. APP.translation.translateElement(dialog);
  51. return dialog;
  52. },
  53. /**
  54. * Shows a message to the user with two buttons: first is given as a
  55. * parameter and the second is Cancel.
  56. *
  57. * @param titleKey the key for the title of the message
  58. * @param msgString the text of the message
  59. * @param persistent boolean value which determines whether the message is
  60. * persistent or not
  61. * @param leftButton the fist button's text
  62. * @param submitFunction function to be called on submit
  63. * @param loadedFunction function to be called after the prompt is fully
  64. * loaded
  65. * @param closeFunction function to be called after the prompt is closed
  66. * @param focus optional focus selector or button index to be focused after
  67. * the dialog is opened
  68. * @param defaultButton index of default button which will be activated when
  69. * the user press 'enter'. Indexed from 0.
  70. * @return the prompt that was created, or null
  71. */
  72. openTwoButtonDialog: function(options) {
  73. let {
  74. titleKey,
  75. msgKey,
  76. msgString,
  77. leftButtonKey,
  78. submitFunction,
  79. loadedFunction,
  80. closeFunction,
  81. focus,
  82. size,
  83. defaultButton,
  84. wrapperClass,
  85. classes
  86. } = options;
  87. if (!popupEnabled || twoButtonDialog)
  88. return null;
  89. var buttons = [];
  90. var leftButton = leftButtonKey ?
  91. APP.translation.generateTranslationHTML(leftButtonKey) :
  92. APP.translation.generateTranslationHTML('dialog.Submit');
  93. buttons.push({ title: leftButton, value: true});
  94. var cancelButton
  95. = APP.translation.generateTranslationHTML("dialog.Cancel");
  96. buttons.push({title: cancelButton, value: false});
  97. var message = msgString;
  98. if (msgKey) {
  99. message = APP.translation.generateTranslationHTML(msgKey);
  100. }
  101. classes = classes || this._getDialogClasses(size);
  102. if (wrapperClass) {
  103. classes.prompt += ` ${wrapperClass}`;
  104. }
  105. twoButtonDialog = $.prompt(message, {
  106. title: this._getFormattedTitleString(titleKey),
  107. persistent: false,
  108. buttons: buttons,
  109. defaultButton: defaultButton,
  110. focus: focus,
  111. loaded: loadedFunction,
  112. promptspeed: 0,
  113. classes,
  114. submit: function (e, v, m, f) {
  115. twoButtonDialog = null;
  116. if (v){
  117. if (submitFunction)
  118. submitFunction(e, v, m, f);
  119. }
  120. },
  121. close: function (e, v, m, f) {
  122. twoButtonDialog = null;
  123. if (closeFunction) {
  124. closeFunction(e, v, m, f);
  125. }
  126. }
  127. });
  128. APP.translation.translateElement(twoButtonDialog);
  129. return twoButtonDialog;
  130. },
  131. /**
  132. * Shows a message to the user with two buttons: first is given as a
  133. * parameter and the second is Cancel.
  134. *
  135. * @param titleKey the key for the title of the message
  136. * @param msgString the text of the message
  137. * @param persistent boolean value which determines whether the message is
  138. * persistent or not
  139. * @param buttons object with the buttons. The keys must be the name of the
  140. * button and value is the value that will be passed to
  141. * submitFunction
  142. * @param submitFunction function to be called on submit
  143. * @param loadedFunction function to be called after the prompt is fully
  144. * loaded
  145. * @param closeFunction function to be called on dialog close
  146. */
  147. openDialog: function (titleKey, msgString, persistent, buttons,
  148. submitFunction, loadedFunction, closeFunction) {
  149. if (!popupEnabled)
  150. return;
  151. let args = {
  152. title: this._getFormattedTitleString(titleKey),
  153. persistent: persistent,
  154. buttons: buttons,
  155. defaultButton: 1,
  156. promptspeed: 0,
  157. loaded: loadedFunction,
  158. submit: submitFunction,
  159. close: closeFunction,
  160. classes: this._getDialogClasses()
  161. };
  162. if (persistent) {
  163. args.closeText = '';
  164. }
  165. let dialog = new Impromptu(msgString, args);
  166. APP.translation.translateElement(dialog.getPrompt());
  167. return dialog;
  168. },
  169. /**
  170. * Returns the formatted title string.
  171. *
  172. * @return the title string formatted as a div.
  173. */
  174. _getFormattedTitleString(titleKey) {
  175. let $titleString = $('<h2>');
  176. $titleString.addClass('aui-dialog2-header-main');
  177. $titleString.attr('data-i18n',titleKey);
  178. return $('<div>').append($titleString).html();
  179. },
  180. /**
  181. * Returns the dialog css classes.
  182. *
  183. * @return the dialog css classes
  184. */
  185. _getDialogClasses(size = 'small') {
  186. return {
  187. box: '',
  188. form: '',
  189. prompt: `dialog aui-layer aui-dialog2 aui-dialog2-${size}`,
  190. close: 'aui-icon aui-icon-small aui-iconfont-close-dialog',
  191. fade: 'aui-blanket',
  192. button: 'button-control',
  193. message: 'aui-dialog2-content',
  194. buttons: 'aui-dialog2-footer',
  195. defaultButton: 'button-control_primary',
  196. title: 'aui-dialog2-header'
  197. };
  198. },
  199. /**
  200. * Closes currently opened dialog.
  201. */
  202. closeDialog: function () {
  203. $.prompt.close();
  204. },
  205. /**
  206. * Shows a dialog with different states to the user.
  207. *
  208. * @param statesObject object containing all the states of the dialog.
  209. * @param options impromptu options
  210. * @param translateOptions options passed to translation
  211. */
  212. openDialogWithStates: function (statesObject, options, translateOptions) {
  213. if (!popupEnabled)
  214. return;
  215. let { classes, size } = options;
  216. let defaultClasses = this._getDialogClasses(size);
  217. options.classes = Object.assign({}, defaultClasses, classes);
  218. options.promptspeed = options.promptspeed || 0;
  219. for (let state in statesObject) {
  220. let currentState = statesObject[state];
  221. if(currentState.titleKey) {
  222. currentState.title
  223. = this._getFormattedTitleString(currentState.titleKey);
  224. }
  225. }
  226. let dialog = new Impromptu(statesObject, options);
  227. APP.translation.translateElement(dialog.getPrompt(), translateOptions);
  228. return dialog;
  229. },
  230. /**
  231. * Opens new popup window for given <tt>url</tt> centered over current
  232. * window.
  233. *
  234. * @param url the URL to be displayed in the popup window
  235. * @param w the width of the popup window
  236. * @param h the height of the popup window
  237. * @param onPopupClosed optional callback function called when popup window
  238. * has been closed.
  239. *
  240. * @returns {object} popup window object if opened successfully or undefined
  241. * in case we failed to open it(popup blocked)
  242. */
  243. openCenteredPopup: function (url, w, h, onPopupClosed) {
  244. if (!popupEnabled)
  245. return;
  246. var l = window.screenX + (window.innerWidth / 2) - (w / 2);
  247. var t = window.screenY + (window.innerHeight / 2) - (h / 2);
  248. var popup = window.open(
  249. url, '_blank',
  250. 'top=' + t + ', left=' + l + ', width=' + w + ', height=' + h + '');
  251. if (popup && onPopupClosed) {
  252. var pollTimer = window.setInterval(function () {
  253. if (popup.closed !== false) {
  254. window.clearInterval(pollTimer);
  255. onPopupClosed();
  256. }
  257. }, 200);
  258. }
  259. return popup;
  260. },
  261. /**
  262. * Shows a dialog prompting the user to send an error report.
  263. *
  264. * @param titleKey the title of the message
  265. * @param msgKey the text of the message
  266. * @param error the error that is being reported
  267. */
  268. openReportDialog: function(titleKey, msgKey, error) {
  269. this.openMessageDialog(titleKey, msgKey);
  270. console.log(error);
  271. //FIXME send the error to the server
  272. },
  273. /**
  274. * Shows an error dialog to the user.
  275. * @param titleKey the title of the message.
  276. * @param msgKey the text of the message.
  277. */
  278. showError: function(titleKey, msgKey) {
  279. if (!titleKey) {
  280. titleKey = "dialog.oops";
  281. }
  282. if (!msgKey) {
  283. msgKey = "dialog.defaultError";
  284. }
  285. messageHandler.openMessageDialog(titleKey, msgKey);
  286. },
  287. /**
  288. * Displays a notification.
  289. * @param displayName the display name of the participant that is
  290. * associated with the notification.
  291. * @param displayNameKey the key from the language file for the display
  292. * name. Only used if displayName i not provided.
  293. * @param cls css class for the notification
  294. * @param messageKey the key from the language file for the text of the
  295. * message.
  296. * @param messageArguments object with the arguments for the message.
  297. * @param options object with language options.
  298. */
  299. notify: function(displayName, displayNameKey, cls, messageKey,
  300. messageArguments, options) {
  301. // If we're in ringing state we skip all toaster notifications.
  302. if(!notificationsEnabled || APP.UI.isRingOverlayVisible())
  303. return;
  304. var displayNameSpan = '<span class="nickname" ';
  305. if (displayName) {
  306. displayNameSpan += ">" + UIUtil.escapeHtml(displayName);
  307. } else {
  308. displayNameSpan += "data-i18n='" + displayNameKey + "'>";
  309. }
  310. displayNameSpan += "</span>";
  311. let element = toastr.info(
  312. displayNameSpan + '<br>' +
  313. '<span class=' + cls + ' data-i18n="' + messageKey + '"' +
  314. (messageArguments?
  315. " data-i18n-options='"
  316. + JSON.stringify(messageArguments) + "'"
  317. : "") + "></span>", null, options);
  318. APP.translation.translateElement(element);
  319. return element;
  320. },
  321. /**
  322. * Removes the toaster.
  323. * @param toasterElement
  324. */
  325. remove: function(toasterElement) {
  326. toasterElement.remove();
  327. },
  328. /**
  329. * Enables / disables notifications.
  330. */
  331. enableNotifications: function (enable) {
  332. notificationsEnabled = enable;
  333. },
  334. enablePopups: function (enable) {
  335. popupEnabled = enable;
  336. },
  337. /**
  338. * Returns true if dialog is opened
  339. * false otherwise
  340. * @returns {boolean} isOpened
  341. */
  342. isDialogOpened: function () {
  343. return !!$.prompt.getCurrentStateName();
  344. }
  345. };
  346. module.exports = messageHandler;