acsi-core 0.10.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,7 @@ interface IProps {
9
9
  onSubmit?: any;
10
10
  bodyPadding?: string;
11
11
  className?: string;
12
+ disableBackdropClick?: boolean;
12
13
  }
13
14
  declare const CoreModal: (props: IProps) => React.JSX.Element;
14
15
  export default CoreModal;
@@ -2,6 +2,8 @@ import React from "react";
2
2
  interface IOprion {
3
3
  label: string;
4
4
  value: string;
5
+ hiddenCheckbox?: boolean;
6
+ border?: boolean;
5
7
  }
6
8
  interface IProps {
7
9
  name?: string;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * MSALRedirectHandler component
3
+ *
4
+ * This component handles MSAL redirect authentication flows by processing
5
+ * the hash fragment in the URL before any router code can clear it.
6
+ *
7
+ * Uses useLayoutEffect to run synchronously before browser paint,
8
+ * ensuring it processes the redirect before React Router initializes.
9
+ *
10
+ * This component uses the singleton MSAL instance to avoid conflicts
11
+ * and ensure consistent state management.
12
+ */
13
+ declare const MSALRedirectHandler: () => null;
14
+ export default MSALRedirectHandler;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  declare const historyCore: import("history").History<unknown>;
2
- import { setLoading, setAlert, setTenant, setAddTenant, setTeam, setUser, setMenuCollapse, setIsRefetchSidebar, setLoadingPage } from "./redux/commons/action";
2
+ import { setLoading, setAlert, setTenant, setAddTenant, setTeam, setUser, setMenuCollapse, setIsRefetchSidebar, setLoadingPage, setIsFirstCalendar } from "./redux/commons/action";
3
3
  import { BASE_URL, ACCESS_TOKEN, DATE_TIME_MIN_VALUE, OPENSALT_BASE_URL, ORGANIZATION_TEAM, ORGANIZATION_TENANT } from "./utils/constants";
4
4
  import Login from "./containers/Login/views/Login";
5
5
  import store from "./store";
@@ -28,5 +28,6 @@ import CustomAsyncSelect from "./components/Selects/CustomAsyncSelect";
28
28
  import CustomCreatable from "./components/Selects/CustomCreatable";
29
29
  import CustomSelectOption from "./components/Selects/CustomSelectOption";
30
30
  import utcToLocalTime from "./utils/utcToLocalTime";
31
+ import timeSpanToLocalMoment from "./utils/timeSpanToLocalMoment";
31
32
  import Cookies from "js-cookie";
32
- export { setLoading, setLoadingPage, BASE_URL, OPENSALT_BASE_URL, ACCESS_TOKEN, DATE_TIME_MIN_VALUE, ORGANIZATION_TEAM, ORGANIZATION_TENANT, firstCheckToken, getImageUrl, Login, utcToLocalTime, getAccessToken, store, historyCore, setAlert, setUser, setTenant, setAddTenant, setTeam, setMenuCollapse, setIsRefetchSidebar, Loading, NotFound, LayoutContext, api, apiUpload, ConfirmDialog, CommonDialog, ToastContainer, toast, Role, Cookies, CustomPagination, useGoogleSignOut, CoreButton, CoreInput, CoreSelect, CoreCheckbox, CoreRadio, CoreError, CoreModal, CoreRange, CoreTextArea, CoreSearch, CoreSelectCompact, CoreInputCompact, CoreTitleInput, CoreTooltip, getErrorMessage, MarkdownLatexRender, CustomSelect, CustomAsyncSelect, CustomCreatable, CustomSelectOption, GoogleOAuthProvider, useAmplitude, AmplitudeEvent, initializeAmplitude, initSentry };
33
+ export { setLoading, setLoadingPage, setIsFirstCalendar, BASE_URL, OPENSALT_BASE_URL, ACCESS_TOKEN, DATE_TIME_MIN_VALUE, ORGANIZATION_TEAM, ORGANIZATION_TENANT, firstCheckToken, getImageUrl, Login, utcToLocalTime, timeSpanToLocalMoment, getAccessToken, store, historyCore, setAlert, setUser, setTenant, setAddTenant, setTeam, setMenuCollapse, setIsRefetchSidebar, Loading, NotFound, LayoutContext, api, apiUpload, ConfirmDialog, CommonDialog, ToastContainer, toast, Role, Cookies, CustomPagination, useGoogleSignOut, CoreButton, CoreInput, CoreSelect, CoreCheckbox, CoreRadio, CoreError, CoreModal, CoreRange, CoreTextArea, CoreSearch, CoreSelectCompact, CoreInputCompact, CoreTitleInput, CoreTooltip, getErrorMessage, MarkdownLatexRender, CustomSelect, CustomAsyncSelect, CustomCreatable, CustomSelectOption, GoogleOAuthProvider, useAmplitude, AmplitudeEvent, initializeAmplitude, initSentry };
package/dist/index.js CHANGED
@@ -19,10 +19,10 @@ var rehypeRaw = _interopDefault(require('rehype-raw'));
19
19
  require('katex/dist/katex.min.css');
20
20
  var Cookies = _interopDefault(require('js-cookie'));
21
21
  var moment = _interopDefault(require('moment'));
22
+ var msalBrowser = require('@azure/msal-browser');
22
23
  var reactToastify = require('react-toastify');
23
24
  var reactGoogleLogin = require('@leecheuk/react-google-login');
24
25
  var material = require('@mui/material');
25
- require('@azure/msal-browser');
26
26
  var amplitude = require('@amplitude/analytics-browser');
27
27
  var Sentry = require('@sentry/react');
28
28
  var fa = require('react-icons/fa');
@@ -625,6 +625,7 @@ var setIsRefetchSidebar = toolkit.createAction("common/setIsRefetchSidebar");
625
625
  var setTenant = toolkit.createAction("common/setTenant");
626
626
  var setAddTenant = toolkit.createAction("common/setAddTenant");
627
627
  var setTeam = toolkit.createAction("common/setTeam");
628
+ var setIsFirstCalendar = toolkit.createAction("common/setIsFirstCalendar");
628
629
 
629
630
  var REQUEST_ORIGIN = process.env.REACT_APP_REQUEST_ORIGIN || "";
630
631
  var ADMIN_ORIGIN = process.env.REACT_APP_ADMIN_ORIGIN || "";
@@ -641,6 +642,7 @@ var PUSHER_CONFIG = {
641
642
  };
642
643
  var MICROSOFT_CLIENT_ID = process.env.REACT_APP_MICROSOFT_CLIENT_ID || "";
643
644
  var MICROSOFT_URL_DIRECT = process.env.REACT_APP_MICROSOFT_URL_DIRECT || "";
645
+ var MICROSOFT_SSO_ENABLED = process.env.REACT_APP_MICROSOFT_SSO_ENABLED || "false";
644
646
  var OPENSALT_BASE_URL = process.env.REACT_APP_OPENSALT || "";
645
647
  var ACCESS_TOKEN = "ACCESS_TOKEN";
646
648
  var AUTH_COOKIE = "auth";
@@ -672,25 +674,6 @@ var ORGANIZATION_TEAM = "ORGANIZATION_TEAM";
672
674
 
673
675
  var styleGlobal = {"signup_wrap":"_1KLz9","box-signin":"_2Jo1o","signin_title":"_3egBO","signup_link":"_1DoIT","google_button":"_34hK_","microsoft_button":"_19ESb","box-field":"_2e9xO","box-input":"_3zXRp","box-text":"_8NJga","box-button-email":"_21FPk","box-signin-container":"_1QERu","box-signin-text":"_2-znH","box-signin-logo":"_1aB2m","box-right":"_3qndF","image-slideshow":"_1aM7m","active":"_Vx1zf","box-right-body":"_JzdCr","box-right-footer":"_19aCA","pr-30":"_2HB5r","width-400":"_4ehXP"};
674
676
 
675
- // A type of promise-like that resolves synchronously and supports only one observer
676
-
677
- const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";
678
-
679
- const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";
680
-
681
- // Asynchronously call a function and send errors to recovery continuation
682
- function _catch(body, recover) {
683
- try {
684
- var result = body();
685
- } catch(e) {
686
- return recover(e);
687
- }
688
- if (result && result.then) {
689
- return result.then(void 0, recover);
690
- }
691
- return result;
692
- }
693
-
694
677
  function _arrayLikeToArray(r, a) {
695
678
  (null == a || a > r.length) && (a = r.length);
696
679
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
@@ -739,6 +722,25 @@ function _unsupportedIterableToArray(r, a) {
739
722
  }
740
723
  }
741
724
 
725
+ // A type of promise-like that resolves synchronously and supports only one observer
726
+
727
+ const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";
728
+
729
+ const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";
730
+
731
+ // Asynchronously call a function and send errors to recovery continuation
732
+ function _catch(body, recover) {
733
+ try {
734
+ var result = body();
735
+ } catch(e) {
736
+ return recover(e);
737
+ }
738
+ if (result && result.then) {
739
+ return result.then(void 0, recover);
740
+ }
741
+ return result;
742
+ }
743
+
742
744
  var styles = {"core-button":"_xvNBN","primary":"_U9Qyp","secondary":"_1VzMy","text":"_pZNuj","danger":"_2uYm1","light":"_wxH5S"};
743
745
 
744
746
  var _excluded = ["type", "children", "onClick", "icon", "disabled", "htmlType"];
@@ -1098,12 +1100,16 @@ var CoreModal = function CoreModal(props) {
1098
1100
  onSubmit = props.onSubmit,
1099
1101
  _props$bodyPadding = props.bodyPadding,
1100
1102
  bodyPadding = _props$bodyPadding === void 0 ? "24px" : _props$bodyPadding,
1101
- className = props.className;
1103
+ className = props.className,
1104
+ _props$disableBackdro = props.disableBackdropClick,
1105
+ disableBackdropClick = _props$disableBackdro === void 0 ? false : _props$disableBackdro;
1102
1106
  return React__default.createElement(reactstrap.Modal, {
1103
1107
  isOpen: open,
1104
- toggle: onClose,
1108
+ toggle: disableBackdropClick ? undefined : onClose,
1105
1109
  centered: true,
1106
- modalClassName: className
1110
+ modalClassName: className,
1111
+ backdrop: disableBackdropClick ? "static" : true,
1112
+ keyboard: !disableBackdropClick
1107
1113
  }, React__default.createElement("form", {
1108
1114
  onSubmit: onSubmit ? handleSubmit(onSubmit) : undefined,
1109
1115
  className: "" + styles$6["core-modal-container"]
@@ -1371,7 +1377,7 @@ var CoreSearch = function CoreSearch(props) {
1371
1377
  var styles$a = {"core-select-compact":"_3ql5D","label":"_3fPQC"};
1372
1378
 
1373
1379
  var Option$1 = function Option(props) {
1374
- return React__default.createElement("div", null, React__default.createElement(ReactSelect.components.Option, Object.assign({}, props), React__default.createElement(CoreInput$1, {
1380
+ return React__default.createElement("div", null, React__default.createElement(ReactSelect.components.Option, Object.assign({}, props), props.data.hiddenCheckbox ? React__default.createElement("span", null, props.label) : React__default.createElement(CoreInput$1, {
1375
1381
  checked: props.isSelected,
1376
1382
  onChange: function onChange() {
1377
1383
  return null;
@@ -1480,6 +1486,10 @@ var CoreSelectCompact = function CoreSelectCompact(props) {
1480
1486
  backgroundColor: COLORS.lightBlueHover
1481
1487
  }
1482
1488
  });
1489
+ if (state.data.border) {
1490
+ styles.borderTop = "1px solid #E6E6EB";
1491
+ styles.borderRadius = "0px";
1492
+ }
1483
1493
  return styles;
1484
1494
  };
1485
1495
  var multiValueStyles = function multiValueStyles(base) {
@@ -2322,6 +2332,55 @@ var TypeLogin;
2322
2332
  TypeLogin[TypeLogin["Microsoft"] = 3] = "Microsoft";
2323
2333
  })(TypeLogin || (TypeLogin = {}));
2324
2334
 
2335
+ var AuthenticationMessage;
2336
+ (function (AuthenticationMessage) {
2337
+ AuthenticationMessage["NotAllowedToRegister"] = "NotAllowedToRegister";
2338
+ AuthenticationMessage["InvalidGoogleToken"] = "InvalidGoogleToken";
2339
+ })(AuthenticationMessage || (AuthenticationMessage = {}));
2340
+ (function (Role) {
2341
+ Role["Student"] = "Student";
2342
+ Role["Teacher"] = "Teacher";
2343
+ Role["Admin"] = "Admin";
2344
+ })(exports.Role || (exports.Role = {}));
2345
+ var msalConfig = function msalConfig(clientId, redirectUri) {
2346
+ return {
2347
+ auth: {
2348
+ clientId: clientId,
2349
+ authority: "https://login.microsoftonline.com/common",
2350
+ redirectUri: redirectUri
2351
+ },
2352
+ cache: {
2353
+ cacheLocation: "sessionStorage",
2354
+ storeAuthStateInCookie: false
2355
+ },
2356
+ system: {
2357
+ loggerOptions: {
2358
+ loggerCallback: function loggerCallback(level, message, containsPii) {
2359
+ if (containsPii) {
2360
+ return;
2361
+ }
2362
+ switch (level) {
2363
+ case msalBrowser.LogLevel.Error:
2364
+ console.error(message);
2365
+ return;
2366
+ case msalBrowser.LogLevel.Info:
2367
+ console.info(message);
2368
+ return;
2369
+ case msalBrowser.LogLevel.Verbose:
2370
+ console.debug(message);
2371
+ return;
2372
+ case msalBrowser.LogLevel.Warning:
2373
+ console.warn(message);
2374
+ return;
2375
+ default:
2376
+ return;
2377
+ }
2378
+ }
2379
+ }
2380
+ }
2381
+ };
2382
+ };
2383
+
2325
2384
  var BlockLogin = function BlockLogin(_ref) {
2326
2385
  var onNavigate = _ref.onNavigate,
2327
2386
  role = _ref.role,
@@ -2456,6 +2515,91 @@ var BlockLogin = function BlockLogin(_ref) {
2456
2515
  return console.log(errorResponse);
2457
2516
  }
2458
2517
  });
2518
+ var fnLoginMicrosoft = function fnLoginMicrosoft() {
2519
+ try {
2520
+ var msalInstance = new msalBrowser.PublicClientApplication(msalConfig(MICROSOFT_CLIENT_ID, MICROSOFT_URL_DIRECT));
2521
+ if (!msalInstance) {
2522
+ console.error("MSAL instance not initialized");
2523
+ return Promise.resolve();
2524
+ }
2525
+ return Promise.resolve(_catch(function () {
2526
+ return Promise.resolve(msalInstance.initialize()).then(function () {
2527
+ var loginRequest = {
2528
+ scopes: ["openid", "profile", "email"]
2529
+ };
2530
+ var silentRequest = _extends$1({}, loginRequest, {
2531
+ prompt: "select_account"
2532
+ });
2533
+ return Promise.resolve(msalInstance.loginPopup(silentRequest)).then(function (response) {
2534
+ return function () {
2535
+ if (response && response.account) {
2536
+ var account = response.account;
2537
+ var fullName = (account === null || account === void 0 ? void 0 : account.name) || "";
2538
+ var infoLogin = {
2539
+ firstName: fullName.split(' ').slice(0, -1).join(' '),
2540
+ lastName: fullName.split(' ').slice(-1).join(' '),
2541
+ fullName: fullName,
2542
+ imageUrl: "",
2543
+ email: (account === null || account === void 0 ? void 0 : account.username) || "",
2544
+ token: (response === null || response === void 0 ? void 0 : response.accessToken) || "",
2545
+ googleId: (account === null || account === void 0 ? void 0 : account.homeAccountId) || "",
2546
+ role: role,
2547
+ type: TypeLogin.Microsoft
2548
+ };
2549
+ dispatch(setLoading(true));
2550
+ return Promise.resolve(apiLoginGoogle(infoLogin)).then(function (authResult) {
2551
+ var _authResult$data2;
2552
+ if (((_authResult$data2 = authResult.data) === null || _authResult$data2 === void 0 ? void 0 : _authResult$data2.id) == null) {
2553
+ dispatch(setLoading(false));
2554
+ alert("Please contact admin.");
2555
+ return;
2556
+ }
2557
+ localStorage.clear();
2558
+ var tokenJWT = authResult.data.token;
2559
+ trackEvent === null || trackEvent === void 0 ? void 0 : trackEvent({
2560
+ eventName: exports.AmplitudeEvent.LOGIN,
2561
+ eventProperties: {
2562
+ email: email,
2563
+ login_method: 'microsoft',
2564
+ user_role: authResult.data.role,
2565
+ success: true,
2566
+ timestamp: new Date().toISOString()
2567
+ }
2568
+ });
2569
+ if (role === "LandingPage") {
2570
+ CookieService.setAuthCookie({
2571
+ token: tokenJWT,
2572
+ expiresAt: Date.now() + 24 * 60 * 60 * 1000
2573
+ });
2574
+ var getRedirectUrl = function getRedirectUrl(role) {
2575
+ switch (role) {
2576
+ case "Admin":
2577
+ return ADMIN_ORIGIN;
2578
+ case "Teacher":
2579
+ return TEACHER_ORIGIN;
2580
+ default:
2581
+ return role + "." + REQUEST_ORIGIN;
2582
+ }
2583
+ };
2584
+ var redirectUrl = getRedirectUrl(authResult.data.role);
2585
+ window.location.href = redirectUrl + "/dashboard";
2586
+ dispatch(setLoading(false));
2587
+ }
2588
+ localStorage.setItem(ACCESS_TOKEN, tokenJWT);
2589
+ onNavigate("/dashboard");
2590
+ dispatch(setLoading(false));
2591
+ });
2592
+ }
2593
+ }();
2594
+ });
2595
+ });
2596
+ }, function (error) {
2597
+ console.error("Microsoft login error:", error);
2598
+ }));
2599
+ } catch (e) {
2600
+ return Promise.reject(e);
2601
+ }
2602
+ };
2459
2603
  React__default.useEffect(function () {
2460
2604
  return function () {
2461
2605
  if (resendTimer) {
@@ -2563,7 +2707,18 @@ var BlockLogin = function BlockLogin(_ref) {
2563
2707
  height: 24,
2564
2708
  alt: "Google sign-in",
2565
2709
  src: "/images/icons/Google__G__logo.png"
2566
- }), "Sign in with Google")), React__default.createElement("span", {
2710
+ }), "Sign in with Google")), MICROSOFT_SSO_ENABLED === "true" && React__default.createElement("div", {
2711
+ className: "" + styleGlobal["microsoft_button"]
2712
+ }, React__default.createElement("button", {
2713
+ onClick: function onClick() {
2714
+ return fnLoginMicrosoft();
2715
+ }
2716
+ }, React__default.createElement("img", {
2717
+ width: 24,
2718
+ height: 24,
2719
+ alt: "Google sign-in",
2720
+ src: "/images/Single-Sign-On-logo.png"
2721
+ }), "Sign in with Microsoft")), React__default.createElement("span", {
2567
2722
  className: "" + styleGlobal["box-field"]
2568
2723
  }, "OR"), React__default.createElement("div", {
2569
2724
  className: "" + styleGlobal["box-input"]
@@ -3163,7 +3318,8 @@ var initialState = {
3163
3318
  user: null,
3164
3319
  academy: null,
3165
3320
  menuCollapse: false,
3166
- isRefetchSidebar: false
3321
+ isRefetchSidebar: false,
3322
+ isFirstCalendar: false
3167
3323
  };
3168
3324
  var commonReducer = toolkit.createReducer(initialState, function (builder) {
3169
3325
  builder.addCase(setLoading, function (state, action) {
@@ -3188,6 +3344,8 @@ var commonReducer = toolkit.createReducer(initialState, function (builder) {
3188
3344
  state.user.tenantInfo = action.payload;
3189
3345
  }).addCase(setTeam, function (state, action) {
3190
3346
  state.user.currentTeamId = action.payload;
3347
+ }).addCase(setIsFirstCalendar, function (state) {
3348
+ state.isFirstCalendar = !state.isFirstCalendar;
3191
3349
  });
3192
3350
  });
3193
3351
 
@@ -3393,17 +3551,6 @@ var CommonDialog = function CommonDialog(_ref) {
3393
3551
  }, title)), children);
3394
3552
  };
3395
3553
 
3396
- var AuthenticationMessage;
3397
- (function (AuthenticationMessage) {
3398
- AuthenticationMessage["NotAllowedToRegister"] = "NotAllowedToRegister";
3399
- AuthenticationMessage["InvalidGoogleToken"] = "InvalidGoogleToken";
3400
- })(AuthenticationMessage || (AuthenticationMessage = {}));
3401
- (function (Role) {
3402
- Role["Student"] = "Student";
3403
- Role["Teacher"] = "Teacher";
3404
- Role["Admin"] = "Admin";
3405
- })(exports.Role || (exports.Role = {}));
3406
-
3407
3554
  var CustomPagination = function CustomPagination(_ref) {
3408
3555
  var currentPage = _ref.currentPage,
3409
3556
  totalPage = _ref.totalPage,
@@ -3675,15 +3822,13 @@ var useAmplitude = function useAmplitude() {
3675
3822
  };
3676
3823
 
3677
3824
  var initializeAmplitude = function initializeAmplitude(apiKey) {
3678
- if (process.env.NODE_ENV === 'production' || process.env.REACT_APP_ENABLE_AMPLITUDE === 'true') {
3679
- amplitude.init(apiKey, {
3680
- defaultTracking: {
3681
- pageViews: true,
3682
- sessions: true,
3683
- formInteractions: true
3684
- }
3685
- });
3686
- }
3825
+ amplitude.init(apiKey, {
3826
+ defaultTracking: {
3827
+ pageViews: true,
3828
+ sessions: true,
3829
+ formInteractions: true
3830
+ }
3831
+ });
3687
3832
  };
3688
3833
 
3689
3834
  function initSentry(dsn, release) {
@@ -3908,6 +4053,16 @@ var utcToLocalTime = (function (time, FORMAT) {
3908
4053
  }
3909
4054
  });
3910
4055
 
4056
+ var timeSpanToLocalMoment = (function (time) {
4057
+ if (!time) return null;
4058
+ var times = time.split(":");
4059
+ if (times.length !== 3) return null;
4060
+ var totalSeconds = +times[0] * 60 * 60 + +times[1] * 60 + +times[2];
4061
+ var startOfDay = moment.utc().startOf("day");
4062
+ var dateTime = startOfDay.add(totalSeconds, "seconds");
4063
+ return dateTime.local();
4064
+ });
4065
+
3911
4066
  var historyCore = createBrowserHistory();
3912
4067
 
3913
4068
  Object.defineProperty(exports, 'GoogleOAuthProvider', {
@@ -3972,6 +4127,7 @@ exports.initSentry = initSentry;
3972
4127
  exports.initializeAmplitude = initializeAmplitude;
3973
4128
  exports.setAddTenant = setAddTenant;
3974
4129
  exports.setAlert = setAlert;
4130
+ exports.setIsFirstCalendar = setIsFirstCalendar;
3975
4131
  exports.setIsRefetchSidebar = setIsRefetchSidebar;
3976
4132
  exports.setLoading = setLoading;
3977
4133
  exports.setLoadingPage = setLoadingPage;
@@ -3980,6 +4136,7 @@ exports.setTeam = setTeam;
3980
4136
  exports.setTenant = setTenant;
3981
4137
  exports.setUser = setUser;
3982
4138
  exports.store = store;
4139
+ exports.timeSpanToLocalMoment = timeSpanToLocalMoment;
3983
4140
  exports.useAmplitude = useAmplitude;
3984
4141
  exports.useGoogleSignOut = useGoogleSignOut;
3985
4142
  exports.utcToLocalTime = utcToLocalTime;