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.

actions.web.ts 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // @ts-expect-error
  2. import { FEEDBACK_REQUEST_IN_PROGRESS } from '../../../modules/UI/UIErrors';
  3. import { IStore } from '../app/types';
  4. import { IJitsiConference } from '../base/conference/reducer';
  5. import { openDialog } from '../base/dialog/actions';
  6. import { extractFqnFromPath } from '../dynamic-branding/functions.any';
  7. import { isVpaasMeeting } from '../jaas/functions';
  8. import {
  9. CANCEL_FEEDBACK,
  10. SUBMIT_FEEDBACK_ERROR,
  11. SUBMIT_FEEDBACK_SUCCESS
  12. } from './actionTypes';
  13. import FeedbackDialog from './components/FeedbackDialog.web';
  14. import { sendFeedbackToJaaSRequest } from './functions.web';
  15. /**
  16. * Caches the passed in feedback in the redux store.
  17. *
  18. * @param {number} score - The quality score given to the conference.
  19. * @param {string} message - A description entered by the participant that
  20. * explains the rating.
  21. * @returns {{
  22. * type: CANCEL_FEEDBACK,
  23. * message: string,
  24. * score: number
  25. * }}
  26. */
  27. export function cancelFeedback(score: number, message: string) {
  28. return {
  29. type: CANCEL_FEEDBACK,
  30. message,
  31. score
  32. };
  33. }
  34. /**
  35. * Potentially open the {@code FeedbackDialog}. It will not be opened if it is
  36. * already open or feedback has already been submitted.
  37. *
  38. * @param {JistiConference} conference - The conference for which the feedback
  39. * would be about. The conference is passed in because feedback can occur after
  40. * a conference has been left, so references to it may no longer exist in redux.
  41. * @param {string} title - The feedback dialog title.
  42. * @returns {Promise} Resolved with value - false if the dialog is enabled and
  43. * resolved with true if the dialog is disabled or the feedback was already
  44. * submitted. Rejected if another dialog is already displayed.
  45. */
  46. export function maybeOpenFeedbackDialog(conference: IJitsiConference, title?: string) {
  47. type R = {
  48. feedbackSubmitted: boolean;
  49. showThankYou: boolean;
  50. wasDialogShown: boolean;
  51. };
  52. return (dispatch: IStore['dispatch'], getState: IStore['getState']): Promise<R> => {
  53. const state = getState();
  54. const { feedbackPercentage = 100 } = state['features/base/config'];
  55. if (config.iAmRecorder) {
  56. // Intentionally fall through the if chain to prevent further action
  57. // from being taken with regards to showing feedback.
  58. } else if (state['features/base/dialog'].component === FeedbackDialog) {
  59. // Feedback is currently being displayed.
  60. return Promise.reject(FEEDBACK_REQUEST_IN_PROGRESS);
  61. } else if (state['features/feedback'].submitted) {
  62. // Feedback has been submitted already.
  63. return Promise.resolve({
  64. feedbackSubmitted: true,
  65. showThankYou: true,
  66. wasDialogShown: false
  67. });
  68. } else if (conference.isCallstatsEnabled() && feedbackPercentage > Math.random() * 100) {
  69. return new Promise(resolve => {
  70. dispatch(openFeedbackDialog(conference, title, () => {
  71. const { submitted } = getState()['features/feedback'];
  72. resolve({
  73. feedbackSubmitted: submitted,
  74. showThankYou: false,
  75. wasDialogShown: true
  76. });
  77. }));
  78. });
  79. }
  80. // If the feedback functionality isn't enabled we show a "thank you"
  81. // message. Signaling it (true), so the caller of requestFeedback can
  82. // act on it.
  83. return Promise.resolve({
  84. feedbackSubmitted: false,
  85. showThankYou: true,
  86. wasDialogShown: false
  87. });
  88. };
  89. }
  90. /**
  91. * Opens {@code FeedbackDialog}.
  92. *
  93. * @param {JitsiConference} conference - The JitsiConference that is being
  94. * rated. The conference is passed in because feedback can occur after a
  95. * conference has been left, so references to it may no longer exist in redux.
  96. * @param {string} [title] - The feedback dialog title.
  97. * @param {Function} [onClose] - An optional callback to invoke when the dialog
  98. * is closed.
  99. * @returns {Object}
  100. */
  101. export function openFeedbackDialog(conference?: IJitsiConference, title?: string, onClose?: Function) {
  102. return openDialog(FeedbackDialog, {
  103. conference,
  104. onClose,
  105. title
  106. });
  107. }
  108. /**
  109. * Sends feedback metadata to JaaS endpoint.
  110. *
  111. * @param {JitsiConference} conference - The JitsiConference that is being rated.
  112. * @param {Object} feedback - The feedback message and score.
  113. *
  114. * @returns {Promise}
  115. */
  116. export function sendJaasFeedbackMetadata(conference: IJitsiConference, feedback: Object) {
  117. return (dispatch: IStore['dispatch'], getState: IStore['getState']): Promise<any> => {
  118. const state = getState();
  119. const { jaasFeedbackMetadataURL } = state['features/base/config'];
  120. const { jwt, user, tenant } = state['features/base/jwt'];
  121. if (!isVpaasMeeting(state) || !jaasFeedbackMetadataURL) {
  122. return Promise.resolve();
  123. }
  124. const meetingFqn = extractFqnFromPath();
  125. const feedbackData = {
  126. ...feedback,
  127. sessionId: conference.sessionId,
  128. userId: user?.id,
  129. meetingFqn,
  130. jwt,
  131. tenant
  132. };
  133. return sendFeedbackToJaaSRequest(jaasFeedbackMetadataURL, feedbackData);
  134. };
  135. }
  136. /**
  137. * Send the passed in feedback.
  138. *
  139. * @param {number} score - An integer between 1 and 5 indicating the user
  140. * feedback. The negative integer -1 is used to denote no score was selected.
  141. * @param {string} message - Detailed feedback from the user to explain the
  142. * rating.
  143. * @param {JitsiConference} conference - The JitsiConference for which the
  144. * feedback is being left.
  145. * @returns {Function}
  146. */
  147. export function submitFeedback(
  148. score: number,
  149. message: string,
  150. conference: IJitsiConference) {
  151. return (dispatch: IStore['dispatch']) =>
  152. conference.sendFeedback(score, message)
  153. .then(() => dispatch({ type: SUBMIT_FEEDBACK_SUCCESS }))
  154. .then(() => dispatch(sendJaasFeedbackMetadata(conference, { score,
  155. message }))
  156. .catch(error => {
  157. dispatch({
  158. type: SUBMIT_FEEDBACK_ERROR,
  159. error
  160. });
  161. return Promise.reject(error);
  162. }));
  163. }