@datalayer/core 0.0.3 → 0.0.5
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.
- package/README.md +114 -3
- package/lib/App.css +2 -2
- package/lib/App.d.ts +1 -1
- package/lib/App.js +9 -9
- package/lib/__tests__/index.test.js +5 -5
- package/lib/api/DatalayerApi.d.ts +1 -1
- package/lib/api/DatalayerApi.js +3 -3
- package/lib/api/index.d.ts +3 -3
- package/lib/api/index.js +3 -3
- package/lib/api/runtimes/actions.js +22 -23
- package/lib/api/runtimes/settings.js +3 -3
- package/lib/api/runtimes/snapshots.d.ts +1 -1
- package/lib/api/runtimes/snapshots.js +8 -8
- package/lib/api/runtimes/utils.js +1 -4
- package/lib/collaboration/DatalayerCollaboration.d.ts +9 -0
- package/lib/collaboration/DatalayerCollaboration.js +28 -0
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +54 -0
- package/lib/collaboration/DatalayerCollaborationProvider.js +162 -0
- package/lib/collaboration/index.d.ts +2 -0
- package/lib/collaboration/index.js +6 -0
- package/lib/components/avatars/BoringAvatar.d.ts +1 -1
- package/lib/components/avatars/BoringAvatar.js +2 -2
- package/lib/components/avatars/UserProfileAvatar.js +2 -9
- package/lib/components/banners/NoAutomationBanner.js +4 -4
- package/lib/components/buttons/DownloadCSVButton.js +1 -1
- package/lib/components/buttons/UploadButton.js +1 -1
- package/lib/components/checkout/StripeCheckout.d.ts +1 -1
- package/lib/components/checkout/StripeCheckout.js +6 -6
- package/lib/components/confetti/ConfettiSuccess.js +1 -1
- package/lib/components/context/OrganizationSelect.js +5 -5
- package/lib/components/context/SpaceSelect.js +7 -7
- package/lib/components/display/AvatarSkeleton.js +1 -1
- package/lib/components/display/CenteredSpinner.js +4 -4
- package/lib/components/display/CodePreview.js +4 -4
- package/lib/components/display/DatalayerBox.js +13 -14
- package/lib/components/display/HorizontalCenter.d.ts +1 -1
- package/lib/components/display/HorizontalCenter.js +1 -1
- package/lib/components/display/JupyterDialog.js +17 -15
- package/lib/components/display/NavLink.d.ts +4 -2
- package/lib/components/display/NavLink.js +6 -4
- package/lib/components/display/NotebookSkeleton.js +2 -2
- package/lib/components/display/Placeholder.js +1 -1
- package/lib/components/display/ToTopBranded.js +1 -1
- package/lib/components/echarts/EChartsReact.d.ts +1 -1
- package/lib/components/echarts/EChartsReact.js +1 -1
- package/lib/components/flashes/FlashClosable.js +11 -11
- package/lib/components/flashes/FlashDisclaimer.js +2 -3
- package/lib/components/flashes/FlashGuest.js +3 -4
- package/lib/components/flashes/FlashSurveys.js +3 -4
- package/lib/components/flashes/FlashUnauthorized.js +2 -2
- package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
- package/lib/components/flashes/surveys/Survey2025_1.js +62 -85
- package/lib/components/iam/ExternalTokenSilentLogin.js +6 -4
- package/lib/components/icons/ArtifactIcon.d.ts +2 -2
- package/lib/components/icons/ArtifactIcon.js +39 -39
- package/lib/components/labels/VisibilityLabel.js +2 -5
- package/lib/components/landings/StepBlock.d.ts +1 -1
- package/lib/components/landings/StepBlock.js +1 -1
- package/lib/components/navbar/NavigationVisbilityObserver.js +2 -2
- package/lib/components/navbar/SubdomainNavBar.js +45 -23
- package/lib/components/navbar/SubdomainNavBar.module.css +33 -14
- package/lib/components/nbgrader/NbGradesDetails.d.ts +1 -1
- package/lib/components/nbgrader/NbGradesDetails.js +5 -8
- package/lib/components/notebooks/JupyterNotebook.js +5 -5
- package/lib/components/notebooks/JupyterNotebookToolbar.js +3 -3
- package/lib/components/primer/Helper.d.ts +1 -1
- package/lib/components/primer/Helper.js +5 -3
- package/lib/components/primer/Portals.d.ts +1 -1
- package/lib/components/primer/Portals.js +2 -2
- package/lib/components/primer/Styles.js +1 -1
- package/lib/components/progress/ConsumptionBar.js +2 -2
- package/lib/components/progress/CreditsIndicator.d.ts +1 -1
- package/lib/components/progress/CreditsIndicator.js +4 -7
- package/lib/components/progress/ProgressRing.js +2 -2
- package/lib/components/runtimes/RuntimeCellVariables.js +9 -9
- package/lib/components/runtimes/RuntimeCellVariablesDialog.js +3 -3
- package/lib/components/runtimes/RuntimeLauncherDialog.js +30 -34
- package/lib/components/runtimes/RuntimePickerBase.js +42 -31
- package/lib/components/runtimes/RuntimePickerCell.js +9 -12
- package/lib/components/runtimes/RuntimePickerNotebook.js +44 -44
- package/lib/components/runtimes/RuntimeReservationControl.js +10 -15
- package/lib/components/runtimes/RuntimeSimplePicker.js +9 -12
- package/lib/components/runtimes/RuntimeUtils.js +22 -12
- package/lib/components/runtimes/RuntimeVariables.js +7 -7
- package/lib/components/screenshot/ScreenCapture.js +9 -13
- package/lib/components/screenshot/ScreenCaptureButton.d.ts +1 -1
- package/lib/components/screenshot/ScreenCaptureButton.js +14 -8
- package/lib/components/snapshots/RuntimeSnapshotMenu.js +19 -17
- package/lib/components/snippets/SnippetDialog.js +5 -5
- package/lib/components/storage/ContentsBrowser.js +63 -56
- package/lib/components/storage/ContentsItems.js +10 -8
- package/lib/components/students/StudentItemStatus.d.ts +1 -1
- package/lib/components/students/StudentItemStatus.js +35 -16
- package/lib/components/subnav/SubNav.d.ts +1 -1
- package/lib/components/subnav/SubNav.js +30 -15
- package/lib/components/subnav/SubNav.module.css +55 -21
- package/lib/components/tables/DataTable.js +1 -4
- package/lib/components/text-reveal/TextRevealAnimation.js +7 -2
- package/lib/components/text-reveal/TextRevealAnimation.module.css +4 -2
- package/lib/components/tokens/SpaceVariantToken.d.ts +1 -1
- package/lib/components/tokens/SpaceVariantToken.js +5 -5
- package/lib/components/toolbars/AssignmentEditorToolbar.js +1 -3
- package/lib/components/users/PeerIndicator.d.ts +1 -1
- package/lib/components/users/PeerIndicator.js +5 -5
- package/lib/config/Configuration.d.ts +48 -0
- package/lib/config/Configuration.js +42 -0
- package/lib/config/integrations/Loom.js +3 -3
- package/lib/examples/CellExample.d.ts +2 -2
- package/lib/examples/CellExample.js +34 -3
- package/lib/examples/DatalayerNotebookExample.d.ts +16 -0
- package/lib/examples/DatalayerNotebookExample.js +75 -0
- package/lib/examples/NativeNavigationExample.d.ts +8 -0
- package/lib/examples/NativeNavigationExample.js +97 -0
- package/lib/examples/NotebookExample.d.ts +1 -3
- package/lib/examples/NotebookExample.js +9 -7
- package/lib/examples/NotebookMutationsKernel.d.ts +2 -0
- package/lib/examples/NotebookMutationsKernel.js +115 -0
- package/lib/examples/NotebookMutationsServiceManager.d.ts +2 -0
- package/lib/examples/NotebookMutationsServiceManager.js +107 -0
- package/lib/examples/ReactRouterExample.d.ts +6 -0
- package/lib/examples/ReactRouterExample.js +175 -0
- package/lib/examples/example-selector.d.ts +22 -0
- package/lib/examples/example-selector.js +45 -0
- package/lib/examples/index.d.ts +2 -0
- package/lib/examples/index.js +6 -0
- package/lib/examples/main.js +153 -0
- package/lib/examples/notebooks/IPyWidgetsExample.ipynb.json +101 -0
- package/lib/examples/notebooks/IPyWidgetsExampleWithState.ipynb.json +112 -0
- package/lib/examples/{NotebookExample1.ipynb.json → notebooks/Lite.ipynb.json} +45 -53
- package/lib/examples/notebooks/Matplotlib.ipynb.json +137 -0
- package/lib/examples/notebooks/NotebookExample1.ipynb.json +126 -0
- package/lib/examples/notebooks/NotebookExample2.ipynb.json +48 -0
- package/lib/examples/notebooks/NotebookOutputs.ipynb.json +49 -0
- package/lib/examples/notebooks/NotebookToCExample.ipynb.json +102 -0
- package/lib/examples/notebooks/OutputIPyWidgetsExample.d.ts +145 -0
- package/lib/examples/notebooks/OutputIPyWidgetsExample.js +153 -0
- package/lib/examples/notebooks/PyGWalker.ipynb.json +55 -0
- package/lib/hooks/assets/OutputshotPlaceholders.d.ts +10 -10
- package/lib/hooks/assets/OutputshotPlaceholders.js +10 -10
- package/lib/hooks/index.d.ts +29 -28
- package/lib/hooks/index.js +29 -28
- package/lib/hooks/layouts/LayoutBackdrop.js +3 -6
- package/lib/hooks/layouts/LayoutScreenshot.css +1 -1
- package/lib/hooks/layouts/LayoutScreenshot.js +6 -6
- package/lib/hooks/useAIAgents.d.ts +1 -1
- package/lib/hooks/useAIAgents.js +6 -6
- package/lib/hooks/useAuthorization.js +4 -4
- package/lib/hooks/useBackdrop.js +7 -7
- package/lib/hooks/useBackdropJupyterLab.d.ts +1 -1
- package/lib/hooks/useBackdropJupyterLab.js +4 -4
- package/lib/hooks/useCache.d.ts +6 -2
- package/lib/hooks/useCache.js +233 -179
- package/lib/hooks/useCellOutputshot.js +3 -6
- package/lib/hooks/useContainsFocus.js +2 -1
- package/lib/hooks/useDatalayer.js +5 -3
- package/lib/hooks/useError.d.ts +1 -1
- package/lib/hooks/useError.js +2 -2
- package/lib/hooks/useExternalScript.js +4 -4
- package/lib/hooks/useFocusTrap.js +2 -1
- package/lib/hooks/useIAM.js +4 -5
- package/lib/hooks/useId.js +3 -3
- package/lib/hooks/useJupyterLabTheme.js +3 -1
- package/lib/hooks/useLocation.d.ts +22 -0
- package/lib/hooks/useLocation.js +149 -0
- package/lib/hooks/useLocationHandles.d.ts +2 -2
- package/lib/hooks/useLocationHandles.js +6 -4
- package/lib/hooks/useNavigate.d.ts +5 -1
- package/lib/hooks/useNavigate.js +62 -7
- package/lib/hooks/useNotebookAIAgent.js +3 -1
- package/lib/hooks/useParams.d.ts +5 -0
- package/lib/hooks/useParams.js +112 -0
- package/lib/hooks/useRuntimes.js +2 -2
- package/lib/hooks/useScreenshot.js +5 -5
- package/lib/hooks/useToast.js +15 -13
- package/lib/hooks/useUpload.js +9 -9
- package/lib/hooks/useUser.js +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.js +7 -3
- package/lib/mocks/components/FlashMock.js +4 -4
- package/lib/mocks/hooks/rests/rests.js +15 -18
- package/lib/mocks/hooks/useDatalayerMock.d.ts +2 -2
- package/lib/mocks/hooks/useDatalayerMock.js +7 -7
- package/lib/mocks/models/CodeBlockMock.js +1 -1
- package/lib/mocks/models/CodelineMock.js +1 -1
- package/lib/mocks/models/CourseMock.d.ts +1 -1
- package/lib/mocks/models/CourseMock.js +10 -10
- package/lib/mocks/models/InviteMock.d.ts +1 -1
- package/lib/mocks/models/InviteMock.js +21 -6
- package/lib/mocks/models/JupyterLabUserMock.js +2 -2
- package/lib/mocks/models/OrganisationMock.d.ts +1 -1
- package/lib/mocks/models/OrganisationMock.js +11 -7
- package/lib/mocks/models/SchoolMock.d.ts +1 -1
- package/lib/mocks/models/SchoolMock.js +6 -6
- package/lib/mocks/models/SpaceMock.d.ts +1 -1
- package/lib/mocks/models/SpaceMock.js +9 -9
- package/lib/mocks/models/TeamMock.d.ts +1 -1
- package/lib/mocks/models/TeamMock.js +6 -6
- package/lib/mocks/models/UserMock.d.ts +1 -1
- package/lib/mocks/models/UserMock.js +4 -6
- package/lib/mocks/views/ActionMenuMock.js +1 -1
- package/lib/mocks/views/ChartMock.js +3 -3
- package/lib/mocks/views/ChartMockOptions.js +24 -24
- package/lib/mocks/views/DashboardMock.js +74 -74
- package/lib/mocks/views/FormMock.js +1 -1
- package/lib/mocks/views/TableMock.js +1 -1
- package/lib/models/Account.d.ts +2 -2
- package/lib/models/Assignment.d.ts +2 -2
- package/lib/models/Cell.d.ts +1 -1
- package/lib/models/CodeBlock.d.ts +1 -1
- package/lib/models/CodefeedBlocks.d.ts +2 -2
- package/lib/models/Contact.d.ts +1 -1
- package/lib/models/Contact.js +14 -14
- package/lib/models/ContactIAMProvider.js +2 -2
- package/lib/models/Course.d.ts +7 -7
- package/lib/models/Dataset.d.ts +1 -1
- package/lib/models/Dean.d.ts +1 -1
- package/lib/models/Document.d.ts +1 -1
- package/lib/models/Environment.d.ts +2 -2
- package/lib/models/Exercise.d.ts +1 -1
- package/lib/models/IAMProviderLinked.js +1 -1
- package/lib/models/Instructor.d.ts +1 -1
- package/lib/models/Invite.d.ts +2 -2
- package/lib/models/Invite.js +1 -1
- package/lib/models/Item.d.ts +5 -5
- package/lib/models/LandingRoles.js +18 -18
- package/lib/models/Lesson.d.ts +1 -1
- package/lib/models/Member.d.ts +1 -1
- package/lib/models/Notebook.d.ts +1 -1
- package/lib/models/Organization.d.ts +4 -4
- package/lib/models/Organization.js +2 -2
- package/lib/models/OrganizationMember.d.ts +2 -2
- package/lib/models/Page.js +4 -2
- package/lib/models/PageTag.d.ts +1 -1
- package/lib/models/PageTag.js +56 -9
- package/lib/models/Profile.d.ts +1 -1
- package/lib/models/RolesOrganization.d.ts +1 -1
- package/lib/models/RolesOrganization.js +4 -12
- package/lib/models/RolesPlatform.d.ts +1 -1
- package/lib/models/RolesPlatform.js +12 -34
- package/lib/models/RolesTeam.d.ts +1 -1
- package/lib/models/RolesTeam.js +3 -10
- package/lib/models/Runtime.js +4 -4
- package/lib/models/RuntimeSnapshot.js +1 -1
- package/lib/models/School.d.ts +4 -4
- package/lib/models/Space.d.ts +5 -5
- package/lib/models/Space.js +3 -3
- package/lib/models/SpaceItem.d.ts +8 -8
- package/lib/models/SpaceMember.d.ts +2 -2
- package/lib/models/Student.d.ts +2 -2
- package/lib/models/StudentItem.d.ts +3 -3
- package/lib/models/Team.d.ts +3 -3
- package/lib/models/Team.js +2 -2
- package/lib/models/TeamMember.d.ts +2 -2
- package/lib/models/URN.js +1 -1
- package/lib/models/User.d.ts +2 -2
- package/lib/models/User.js +5 -3
- package/lib/models/UserOnboarding.d.ts +1 -1
- package/lib/models/UserOnboarding.js +7 -7
- package/lib/models/UserSettings.js +2 -2
- package/lib/models/index.d.ts +2 -2
- package/lib/models/index.js +2 -2
- package/lib/navigation/adapters/native.d.ts +11 -0
- package/lib/navigation/adapters/native.js +48 -0
- package/lib/navigation/adapters/nextjs.d.ts +9 -0
- package/lib/navigation/adapters/nextjs.js +35 -0
- package/lib/navigation/adapters/react-router.d.ts +4 -0
- package/lib/navigation/adapters/react-router.js +12 -0
- package/lib/navigation/components.d.ts +20 -0
- package/lib/navigation/components.js +36 -0
- package/lib/navigation/index.d.ts +4 -0
- package/lib/navigation/index.js +12 -0
- package/lib/routes/index.d.ts +1 -1
- package/lib/routes/index.js +1 -1
- package/lib/services/DatalayerServiceManager.d.ts +22 -0
- package/lib/services/DatalayerServiceManager.js +69 -0
- package/lib/services/index.d.ts +4 -0
- package/lib/services/index.js +7 -0
- package/lib/services/reconnectToRuntime.d.ts +32 -0
- package/lib/services/reconnectToRuntime.js +59 -0
- package/lib/state/State.d.ts +1 -1
- package/lib/state/State.js +1 -1
- package/lib/state/index.d.ts +1 -1
- package/lib/state/index.js +1 -1
- package/lib/state/storage/IAMStorage.js +14 -2
- package/lib/state/storage/index.d.ts +1 -1
- package/lib/state/storage/index.js +1 -1
- package/lib/state/substates/AIAgentState.js +4 -2
- package/lib/state/substates/CellState.js +6 -5
- package/lib/state/substates/CoreState.d.ts +1 -1
- package/lib/state/substates/CoreState.js +26 -17
- package/lib/state/substates/DatasourceState.js +1 -1
- package/lib/state/substates/IAMState.d.ts +4 -0
- package/lib/state/substates/IAMState.js +39 -23
- package/lib/state/substates/JupyterLabState.js +1 -1
- package/lib/state/substates/LayoutState.d.ts +2 -2
- package/lib/state/substates/LayoutState.js +41 -28
- package/lib/state/substates/OrganizationState.js +1 -1
- package/lib/state/substates/RuntimesState.js +11 -6
- package/lib/state/substates/SpaceState.js +1 -1
- package/lib/state/substates/SurveysState.js +4 -4
- package/lib/state/substates/TeamState.js +1 -1
- package/lib/test-setup.js +25 -3
- package/lib/theme/DatalayerTheme.js +1 -1
- package/lib/theme/DatalayerThemeProvider.js +17 -14
- package/lib/theme/Palette.js +1 -1
- package/lib/utils/Avatar.js +2 -2
- package/lib/utils/Browser.js +6 -6
- package/lib/utils/Cells.d.ts +1 -1
- package/lib/utils/Cookie.js +1 -1
- package/lib/utils/Date.js +2 -2
- package/lib/utils/Download.js +5 -3
- package/lib/utils/DownloadFile.js +4 -2
- package/lib/utils/Env.js +2 -1
- package/lib/utils/Lazy.d.ts +1 -1
- package/lib/utils/Lazy.js +2 -2
- package/lib/utils/Name.js +10 -8
- package/lib/utils/Notebook.d.ts +1 -1
- package/lib/utils/Notebook.js +3 -3
- package/lib/utils/Number.js +13 -9
- package/lib/utils/Plots.js +4 -4
- package/lib/utils/Screenshot.js +1 -1
- package/lib/utils/Sleep.js +1 -1
- package/lib/utils/Snapshot.js +2 -2
- package/lib/utils/String.js +2 -2
- package/lib/utils/Uri.js +1 -1
- package/lib/utils/WithSuspense.js +3 -6
- package/lib/utils/logger.d.ts +16 -0
- package/lib/utils/logger.js +52 -0
- package/package.json +49 -5
- package/lib/__tests__/App.test.js +0 -17
- /package/lib/{__tests__/App.test.d.ts → examples/main.d.ts} +0 -0
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
import { Poll } from '@lumino/polling';
|
|
6
6
|
import { useStore } from 'zustand';
|
|
7
7
|
import { createStore } from 'zustand/vanilla';
|
|
8
|
-
import { ANONYMOUS_USER_TOKEN, ANONYMOUS_USER, asUser, IAMProvidersSpecs } from '../../models';
|
|
9
|
-
import { getStoredToken, getStoredUser, loadRefreshTokenFromCookie, storeToken, storeUser } from '../storage';
|
|
8
|
+
import { ANONYMOUS_USER_TOKEN, ANONYMOUS_USER, asUser, IAMProvidersSpecs, } from '../../models';
|
|
9
|
+
import { getStoredToken, getStoredUser, loadRefreshTokenFromCookie, storeToken, storeUser, } from '../storage';
|
|
10
10
|
import { requestDatalayerAPI } from '../../api';
|
|
11
11
|
import { getCookie, setCookie, deleteCookie } from '../../utils';
|
|
12
12
|
import { coreStore } from './CoreState';
|
|
@@ -24,16 +24,19 @@ export const iamStore = createStore((set, get) => {
|
|
|
24
24
|
iamRunUrl: coreStore.getState().configuration?.iamRunUrl,
|
|
25
25
|
iamProvidersAuthorizationURL: {},
|
|
26
26
|
version: '',
|
|
27
|
+
isLoginInProgress: false,
|
|
27
28
|
addIAMProviderAuthorizationURL: (provider, authorizationURL) => {
|
|
28
29
|
set(state => ({
|
|
29
30
|
iamProvidersAuthorizationURL: {
|
|
30
31
|
...state.iamProvidersAuthorizationURL,
|
|
31
32
|
[provider]: authorizationURL,
|
|
32
|
-
}
|
|
33
|
+
},
|
|
33
34
|
}));
|
|
34
35
|
},
|
|
35
36
|
login: async (token) => {
|
|
36
37
|
const { refreshUserByToken, iamRunUrl, logout } = get();
|
|
38
|
+
// Set flag to prevent interference from automatic token refresh
|
|
39
|
+
set({ isLoginInProgress: true });
|
|
37
40
|
try {
|
|
38
41
|
const resp = await requestDatalayerAPI({
|
|
39
42
|
url: `${iamRunUrl}/api/iam/v1/login`,
|
|
@@ -41,7 +44,7 @@ export const iamStore = createStore((set, get) => {
|
|
|
41
44
|
body: { token },
|
|
42
45
|
});
|
|
43
46
|
if (resp.success && resp.token) {
|
|
44
|
-
refreshUserByToken(resp.token);
|
|
47
|
+
await refreshUserByToken(resp.token);
|
|
45
48
|
}
|
|
46
49
|
else {
|
|
47
50
|
throw new Error('Invalid Token.');
|
|
@@ -49,12 +52,16 @@ export const iamStore = createStore((set, get) => {
|
|
|
49
52
|
}
|
|
50
53
|
catch (error) {
|
|
51
54
|
console.debug('Failed to login.', error);
|
|
52
|
-
if (error.name === 'RunResponseError' &&
|
|
55
|
+
if (error.name === 'RunResponseError' &&
|
|
56
|
+
error.response.status === 401) {
|
|
53
57
|
console.debug('Received 401 error - Logging out.');
|
|
54
58
|
logout();
|
|
55
59
|
}
|
|
56
60
|
throw error;
|
|
57
61
|
}
|
|
62
|
+
finally {
|
|
63
|
+
set({ isLoginInProgress: false });
|
|
64
|
+
}
|
|
58
65
|
},
|
|
59
66
|
logout: () => {
|
|
60
67
|
storeUser();
|
|
@@ -97,7 +104,7 @@ export const iamStore = createStore((set, get) => {
|
|
|
97
104
|
user: {
|
|
98
105
|
...state.user,
|
|
99
106
|
...user,
|
|
100
|
-
}
|
|
107
|
+
},
|
|
101
108
|
};
|
|
102
109
|
/*
|
|
103
110
|
if (state.user?.email && !updatedState.user.email) {
|
|
@@ -115,9 +122,9 @@ export const iamStore = createStore((set, get) => {
|
|
|
115
122
|
token,
|
|
116
123
|
headers: externalToken
|
|
117
124
|
? {
|
|
118
|
-
'X-External-Token': externalToken
|
|
125
|
+
'X-External-Token': externalToken,
|
|
119
126
|
}
|
|
120
|
-
: undefined
|
|
127
|
+
: undefined,
|
|
121
128
|
});
|
|
122
129
|
const { credits, reservations: creditsReservations = [] } = creditsRaw;
|
|
123
130
|
let available = credits.quota !== null
|
|
@@ -126,7 +133,7 @@ export const iamStore = createStore((set, get) => {
|
|
|
126
133
|
available -= creditsReservations.reduce((consumed, reservation) => consumed + reservation.credits, 0);
|
|
127
134
|
set({
|
|
128
135
|
credits: { ...credits, available: Math.max(0, available) },
|
|
129
|
-
creditsReservations: creditsReservations
|
|
136
|
+
creditsReservations: creditsReservations,
|
|
130
137
|
});
|
|
131
138
|
}
|
|
132
139
|
catch (error) {
|
|
@@ -162,7 +169,7 @@ export const iamStore = createStore((set, get) => {
|
|
|
162
169
|
}
|
|
163
170
|
},
|
|
164
171
|
refreshUserByToken: async (token) => {
|
|
165
|
-
const { iamRunUrl, logout } = get();
|
|
172
|
+
const { iamRunUrl, logout, isLoginInProgress } = get();
|
|
166
173
|
try {
|
|
167
174
|
const data = await requestDatalayerAPI({
|
|
168
175
|
url: `${iamRunUrl}/api/iam/v1/whoami`,
|
|
@@ -188,16 +195,21 @@ export const iamStore = createStore((set, get) => {
|
|
|
188
195
|
else {
|
|
189
196
|
console.debug('Failed to fetch user identity.', error);
|
|
190
197
|
}
|
|
191
|
-
logout
|
|
198
|
+
// Only logout if we're not in the middle of a login attempt
|
|
199
|
+
if (!isLoginInProgress) {
|
|
200
|
+
logout();
|
|
201
|
+
}
|
|
192
202
|
}
|
|
193
203
|
},
|
|
194
|
-
setExternalToken: (externalToken) => set((state) => {
|
|
204
|
+
setExternalToken: (externalToken) => set((state) => {
|
|
205
|
+
return { externalToken };
|
|
206
|
+
}),
|
|
195
207
|
setLogin: (user, token) => set((state) => {
|
|
196
208
|
storeUser(user);
|
|
197
209
|
storeToken(token);
|
|
198
210
|
return {
|
|
199
211
|
user,
|
|
200
|
-
token
|
|
212
|
+
token,
|
|
201
213
|
};
|
|
202
214
|
}),
|
|
203
215
|
setVersion: version => {
|
|
@@ -218,9 +230,9 @@ const creditsPoll = new Poll({
|
|
|
218
230
|
frequency: {
|
|
219
231
|
interval: 60 * 1000,
|
|
220
232
|
backoff: true,
|
|
221
|
-
max: 600 * 1000
|
|
233
|
+
max: 600 * 1000,
|
|
222
234
|
},
|
|
223
|
-
standby: () => (iamStore.getState().user?.id ? 'when-hidden' : true)
|
|
235
|
+
standby: () => (iamStore.getState().user?.id ? 'when-hidden' : true),
|
|
224
236
|
});
|
|
225
237
|
// Initialize the IAM store with the stored token if it is valid.
|
|
226
238
|
iamStore
|
|
@@ -237,7 +249,7 @@ iamStore
|
|
|
237
249
|
requestDatalayerAPI({
|
|
238
250
|
url: `${iamRunUrl}/api/iam/v1/login`,
|
|
239
251
|
method: 'POST',
|
|
240
|
-
body: { token: externalToken }
|
|
252
|
+
body: { token: externalToken },
|
|
241
253
|
})
|
|
242
254
|
.then(response => {
|
|
243
255
|
if (response.token) {
|
|
@@ -258,11 +270,13 @@ iamStore
|
|
|
258
270
|
creditsPoll.start();
|
|
259
271
|
// Force a refresh when the user comeback to the application tab
|
|
260
272
|
// Useful for checkout platform redirecting to another tab to add credits.
|
|
261
|
-
document
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
273
|
+
if (typeof document !== 'undefined') {
|
|
274
|
+
document.addEventListener('visibilitychange', () => {
|
|
275
|
+
if (!document.hidden && iamStore.getState().user?.id) {
|
|
276
|
+
creditsPoll.refresh();
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
266
280
|
});
|
|
267
281
|
// Connect the core store with the iam store.
|
|
268
282
|
coreStore.subscribe((state, prevState) => {
|
|
@@ -273,14 +287,16 @@ coreStore.subscribe((state, prevState) => {
|
|
|
273
287
|
iamStore.setState({ iamRunUrl });
|
|
274
288
|
// Check the token is valid with the new server.
|
|
275
289
|
if (iamStore.getState().externalToken) {
|
|
276
|
-
iamStore
|
|
290
|
+
iamStore
|
|
291
|
+
.getState()
|
|
277
292
|
.login(iamStore.getState().externalToken)
|
|
278
293
|
.catch(reason => {
|
|
279
294
|
console.error('Failed to refresh the user after updating the IAM RUN URL.', reason);
|
|
280
295
|
});
|
|
281
296
|
}
|
|
282
297
|
else {
|
|
283
|
-
iamStore
|
|
298
|
+
iamStore
|
|
299
|
+
.getState()
|
|
284
300
|
.refreshUser()
|
|
285
301
|
.catch(reason => {
|
|
286
302
|
console.error('Failed to refresh the user after updating the IAM server URL.', reason);
|
|
@@ -9,7 +9,7 @@ export const jupyterLabStore = createStore((set, get) => ({
|
|
|
9
9
|
setJupyterLabAdapter: (jupyterLabAdapter) => set((state) => ({ jupyterLabAdapter })),
|
|
10
10
|
plugin: (id) => {
|
|
11
11
|
return get().jupyterLabAdapter?.plugin(id);
|
|
12
|
-
}
|
|
12
|
+
},
|
|
13
13
|
}));
|
|
14
14
|
export function useJupyterLabStore(selector) {
|
|
15
15
|
return useStore(jupyterLabStore, selector);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactPortal } from
|
|
2
|
-
import { IAnyOrganization, IAnySpace, IAnyTeam, ISpaceItem } from
|
|
1
|
+
import { ReactPortal } from 'react';
|
|
2
|
+
import { IAnyOrganization, IAnySpace, IAnyTeam, ISpaceItem } from '../../models';
|
|
3
3
|
export type BannerDisplayVariant = 'danger' | 'info' | 'success' | 'warning';
|
|
4
4
|
export type LeftSidebarVariant = 'codefeed' | 'course' | 'empty' | 'guess-account' | 'guess-space' | 'guess-spaces' | 'organization' | 'organization-space' | 'organization-spaces' | 'organizations' | 'public' | 'unchanged' | 'user' | 'user-space' | 'user-spaces';
|
|
5
5
|
export type BackdropDisplay = {
|
|
@@ -17,8 +17,12 @@ export const layoutStore = createStore((set, get) => ({
|
|
|
17
17
|
screenCapture: undefined,
|
|
18
18
|
space: undefined,
|
|
19
19
|
team: undefined,
|
|
20
|
-
hideBackdrop: () => set((state) => ({
|
|
21
|
-
|
|
20
|
+
hideBackdrop: () => set((state) => ({
|
|
21
|
+
backdrop: { open: false, message: undefined },
|
|
22
|
+
})),
|
|
23
|
+
hideScreenshot: () => set((state) => ({
|
|
24
|
+
screenshot: { open: false, message: undefined },
|
|
25
|
+
})),
|
|
22
26
|
setBootstrapped: (bootstrapped) => set((state) => ({ bootstrapped })),
|
|
23
27
|
showBackdrop: (message) => set((state) => ({ backdrop: { open: true, message } })),
|
|
24
28
|
showScreenshot: (message) => set((state) => ({ screenshot: { open: true, message } })),
|
|
@@ -27,46 +31,55 @@ export const layoutStore = createStore((set, get) => ({
|
|
|
27
31
|
timestamp: new Date(),
|
|
28
32
|
message: bannerDisplay.message,
|
|
29
33
|
variant: bannerDisplay.variant,
|
|
30
|
-
}
|
|
34
|
+
},
|
|
31
35
|
})),
|
|
32
36
|
setLeftPortal: (leftPortal) => set((state) => ({ leftPortal })),
|
|
33
37
|
setRightPortal: (rightPortal) => set((state) => ({ rightPortal })),
|
|
34
|
-
resetLeftPortal: () => set((state) => ({
|
|
35
|
-
|
|
38
|
+
resetLeftPortal: () => set((state) => ({
|
|
39
|
+
leftPortal: state.leftPortal?.pinned ? state.leftPortal : undefined,
|
|
40
|
+
})),
|
|
41
|
+
resetRightPortal: () => set((state) => ({
|
|
42
|
+
rightPortal: state.rightPortal?.pinned ? state.rightPortal : undefined,
|
|
43
|
+
})),
|
|
36
44
|
resetForcedLeftPortal: () => set((state) => ({ leftPortal: undefined })),
|
|
37
45
|
resetForcedRightPortal: () => set((state) => ({ rightPortal: undefined })),
|
|
38
46
|
setLeftSidebarVariant: (leftSidebarVariant) => set((state) => ({ leftSidebarVariant })),
|
|
39
47
|
updateLayoutOrganization: (organization) => set((state) => {
|
|
40
|
-
return
|
|
41
|
-
organization: organization
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
return {
|
|
49
|
+
organization: organization
|
|
50
|
+
? {
|
|
51
|
+
...state.organization,
|
|
52
|
+
...organization,
|
|
53
|
+
}
|
|
54
|
+
: undefined,
|
|
55
|
+
};
|
|
47
56
|
}),
|
|
48
57
|
updateLayoutTeam: (team) => set((state) => {
|
|
49
|
-
return
|
|
50
|
-
team: team
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
return {
|
|
59
|
+
team: team
|
|
60
|
+
? {
|
|
61
|
+
...state.team,
|
|
62
|
+
...team,
|
|
63
|
+
}
|
|
64
|
+
: undefined,
|
|
65
|
+
};
|
|
56
66
|
}),
|
|
57
67
|
updateLayoutSpace: (space) => set((state) => {
|
|
58
|
-
return
|
|
59
|
-
space: space
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
return {
|
|
69
|
+
space: space
|
|
70
|
+
? {
|
|
71
|
+
...state.space,
|
|
72
|
+
...space,
|
|
73
|
+
}
|
|
74
|
+
: undefined,
|
|
75
|
+
};
|
|
65
76
|
}),
|
|
66
77
|
setItem: (item) => set((state) => ({ item })),
|
|
67
|
-
triggerItemsRefresh: () => set((state) => ({
|
|
78
|
+
triggerItemsRefresh: () => set((state) => ({
|
|
79
|
+
itemsRefreshCount: state.itemsRefreshCount + 1,
|
|
80
|
+
})),
|
|
68
81
|
setScreenCapture: (screenCapture) => set((state) => ({ screenCapture })),
|
|
69
|
-
reset: () => set((state) => ({ bootstrapped: false
|
|
82
|
+
reset: () => set((state) => ({ bootstrapped: false })),
|
|
70
83
|
}));
|
|
71
84
|
export function useLayoutStore(selector) {
|
|
72
85
|
return useStore(layoutStore, selector);
|
|
@@ -7,7 +7,7 @@ import { useStore } from 'zustand';
|
|
|
7
7
|
export const organizationStore = createStore((set, get) => ({
|
|
8
8
|
organizations: [],
|
|
9
9
|
updateOrganizations: (organizations) => set((state) => ({
|
|
10
|
-
organizations
|
|
10
|
+
organizations,
|
|
11
11
|
})),
|
|
12
12
|
}));
|
|
13
13
|
export function useOrganizationStore(selector) {
|
|
@@ -16,7 +16,7 @@ export const runtimesStore = createStore((set, get) => {
|
|
|
16
16
|
return {
|
|
17
17
|
configuration: {
|
|
18
18
|
maxNotebookRuntimes: 5,
|
|
19
|
-
maxCellRuntimes: 3
|
|
19
|
+
maxCellRuntimes: 3,
|
|
20
20
|
},
|
|
21
21
|
setConfiguration: (configuration) => {
|
|
22
22
|
set(state => JSONExt.deepEqual(state.configuration, configuration)
|
|
@@ -53,7 +53,11 @@ export const runtimesStore = createStore((set, get) => {
|
|
|
53
53
|
*/
|
|
54
54
|
addRuntimeModel: (model) => {
|
|
55
55
|
const kernels = get().runtimeModels;
|
|
56
|
-
|
|
56
|
+
// TODO
|
|
57
|
+
// We need to review the IRuntimeModel/IRuntimePod/Kernel.IModel and their id/uid handling.
|
|
58
|
+
// The id is the kernel id, which is no more always present for some reasons.
|
|
59
|
+
// So we need to also check the uid of the model.
|
|
60
|
+
const index = kernels.findIndex(m => (model.id === m.id || model.uid === m.uid) ?? -1);
|
|
57
61
|
if (index < 0) {
|
|
58
62
|
set({ runtimeModels: [...kernels, model] });
|
|
59
63
|
}
|
|
@@ -127,7 +131,7 @@ export const runtimesStore = createStore((set, get) => {
|
|
|
127
131
|
if (version && !get().version) {
|
|
128
132
|
set(state => ({ version }));
|
|
129
133
|
}
|
|
130
|
-
}
|
|
134
|
+
},
|
|
131
135
|
};
|
|
132
136
|
});
|
|
133
137
|
// Poll remote kernels
|
|
@@ -137,12 +141,12 @@ const kernelsPoll = new Poll({
|
|
|
137
141
|
frequency: {
|
|
138
142
|
interval: 61 * 1000,
|
|
139
143
|
backoff: true,
|
|
140
|
-
max: 300 * 1000
|
|
144
|
+
max: 300 * 1000,
|
|
141
145
|
},
|
|
142
146
|
name: '@datalayer/jupyter-kernels:KernelsManager#kernels',
|
|
143
147
|
standby: () => iamStore.getState().token || runtimesStore.getState().runtimesRunUrl
|
|
144
148
|
? 'when-hidden'
|
|
145
|
-
: true
|
|
149
|
+
: true,
|
|
146
150
|
});
|
|
147
151
|
// Force refresh at expiration date if next tick is after it.
|
|
148
152
|
runtimesStore.subscribe((state, prevState) => {
|
|
@@ -160,7 +164,8 @@ runtimesStore.subscribe((state, prevState) => {
|
|
|
160
164
|
});
|
|
161
165
|
coreStore.subscribe((state, prevState) => {
|
|
162
166
|
if (state.configuration.runtimesRunUrl &&
|
|
163
|
-
state.configuration.runtimesRunUrl !==
|
|
167
|
+
state.configuration.runtimesRunUrl !==
|
|
168
|
+
prevState.configuration.runtimesRunUrl) {
|
|
164
169
|
const runtimesRunUrl = state.configuration.runtimesRunUrl;
|
|
165
170
|
console.log(`Updating runtimesRunUrl with new value ${runtimesRunUrl}`);
|
|
166
171
|
runtimesStore.setState({ runtimesRunUrl });
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { createStore } from 'zustand/vanilla';
|
|
6
6
|
import { useStore } from 'zustand';
|
|
7
7
|
import { requestDatalayerAPI } from '../../api';
|
|
8
|
-
import { asSurvey } from '../../models';
|
|
8
|
+
import { asSurvey, } from '../../models';
|
|
9
9
|
import { coreStore } from './CoreState';
|
|
10
10
|
import { iamStore } from './IAMState';
|
|
11
11
|
export const surveysStore = createStore((set, get) => ({
|
|
@@ -65,9 +65,9 @@ export const surveysStore = createStore((set, get) => ({
|
|
|
65
65
|
set((state) => ({ surveys }));
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
|
-
set((state) => ({
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
set((state) => ({
|
|
69
|
+
surveys: new Map([[survey.name, survey]]),
|
|
70
|
+
}));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
else {
|
package/lib/test-setup.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Test setup for unit tests
|
|
6
6
|
// Add any global test configuration here
|
|
7
7
|
// Define webpack globals that are expected by some dependencies
|
|
8
|
-
global.__webpack_public_path__ =
|
|
8
|
+
global.__webpack_public_path__ = '';
|
|
9
9
|
// Define other globals that might be needed
|
|
10
10
|
global.global = globalThis;
|
|
11
11
|
// Mock DragEvent and other DOM APIs not available in jsdom
|
|
@@ -13,7 +13,7 @@ class MockDragEvent extends Event {
|
|
|
13
13
|
dataTransfer = null;
|
|
14
14
|
constructor(type, init) {
|
|
15
15
|
super(type, init);
|
|
16
|
-
this.dataTransfer =
|
|
16
|
+
this.dataTransfer = init?.dataTransfer || null;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
// Mock DataTransfer if not available
|
|
@@ -24,7 +24,9 @@ class MockDataTransfer {
|
|
|
24
24
|
items = [];
|
|
25
25
|
types = [];
|
|
26
26
|
clearData(format) { }
|
|
27
|
-
getData(format) {
|
|
27
|
+
getData(format) {
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
28
30
|
setData(format, data) { }
|
|
29
31
|
setDragImage(image, x, y) { }
|
|
30
32
|
}
|
|
@@ -53,5 +55,25 @@ vi.mock('@datalayer/jupyter-react', () => ({
|
|
|
53
55
|
serviceManager: null,
|
|
54
56
|
}),
|
|
55
57
|
JupyterReactTheme: ({ children }) => children,
|
|
58
|
+
CollaborationProviderBase: class CollaborationProviderBase {
|
|
59
|
+
},
|
|
60
|
+
CollaborationStatus: {
|
|
61
|
+
IDLE: 'idle',
|
|
62
|
+
CONNECTING: 'connecting',
|
|
63
|
+
CONNECTED: 'connected',
|
|
64
|
+
DISCONNECTED: 'disconnected',
|
|
65
|
+
},
|
|
56
66
|
}));
|
|
57
67
|
vi.mock('@jupyter/web-components', () => ({}));
|
|
68
|
+
vi.mock('@jupyter/ydoc', () => ({
|
|
69
|
+
YNotebook: class YNotebook {
|
|
70
|
+
},
|
|
71
|
+
}));
|
|
72
|
+
vi.mock('y-websocket', () => ({
|
|
73
|
+
WebsocketProvider: class WebsocketProvider {
|
|
74
|
+
constructor() { }
|
|
75
|
+
connect() { }
|
|
76
|
+
disconnect() { }
|
|
77
|
+
destroy() { }
|
|
78
|
+
},
|
|
79
|
+
}));
|
|
@@ -4,7 +4,7 @@ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect, useState } from 'react';
|
|
7
|
-
import { BaseStyles, ThemeProvider as PrimerThemeProvider } from '@primer/react';
|
|
7
|
+
import { BaseStyles, ThemeProvider as PrimerThemeProvider, } from '@primer/react';
|
|
8
8
|
import { loadJupyterConfig, jupyterLabTheme } from '@datalayer/jupyter-react';
|
|
9
9
|
import { datalayerTheme } from '../theme';
|
|
10
10
|
import { useRuntimesStore } from '../state';
|
|
@@ -28,7 +28,9 @@ export function DatalayerThemeProvider(props) {
|
|
|
28
28
|
setColorMode(matches ? 'dark' : 'light');
|
|
29
29
|
}
|
|
30
30
|
function updateColorMode(themeManager) {
|
|
31
|
-
setColorMode(themeManager.theme && !themeManager.isLight(themeManager.theme)
|
|
31
|
+
setColorMode(themeManager.theme && !themeManager.isLight(themeManager.theme)
|
|
32
|
+
? 'dark'
|
|
33
|
+
: 'light');
|
|
32
34
|
}
|
|
33
35
|
if (inJupyterLab) {
|
|
34
36
|
// TODO remove the try/catch for JupyterLab > 4.1.
|
|
@@ -48,22 +50,23 @@ export function DatalayerThemeProvider(props) {
|
|
|
48
50
|
}
|
|
49
51
|
else {
|
|
50
52
|
colorSchemeFromMedia({
|
|
51
|
-
matches: window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
53
|
+
matches: window.matchMedia('(prefers-color-scheme: dark)').matches,
|
|
52
54
|
});
|
|
53
|
-
window
|
|
55
|
+
window
|
|
56
|
+
.matchMedia('(prefers-color-scheme: dark)')
|
|
57
|
+
.addEventListener('change', colorSchemeFromMedia);
|
|
54
58
|
return () => {
|
|
55
|
-
window
|
|
59
|
+
window
|
|
60
|
+
.matchMedia('(prefers-color-scheme: dark)')
|
|
61
|
+
.removeEventListener('change', colorSchemeFromMedia);
|
|
56
62
|
};
|
|
57
63
|
}
|
|
58
64
|
}
|
|
59
65
|
}, [inJupyterLab, jupyterLabAdapter]);
|
|
60
|
-
return
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}, children: children }) })
|
|
67
|
-
:
|
|
68
|
-
_jsx(_Fragment, {}));
|
|
66
|
+
return inJupyterLab !== undefined ? (_jsx(PrimerThemeProvider, { colorMode: colorMode, theme: inJupyterLab ? jupyterLabTheme : datalayerTheme, ...rest, children: _jsx(BaseStyles, { style: {
|
|
67
|
+
backgroundColor: 'var(--bgColor-default)',
|
|
68
|
+
color: 'var(--fgColor-default)',
|
|
69
|
+
fontSize: 'var(--text-body-size-medium)',
|
|
70
|
+
...baseStyles,
|
|
71
|
+
}, children: children }) })) : (_jsx(_Fragment, {}));
|
|
69
72
|
}
|
package/lib/theme/Palette.js
CHANGED
|
@@ -9,7 +9,7 @@ const JUPYTERLAB_COLLABORATORS_COLORS = {
|
|
|
9
9
|
'--jp-collaborator-color4': '#00e4d0',
|
|
10
10
|
'--jp-collaborator-color5': '#45d4ff',
|
|
11
11
|
'--jp-collaborator-color6': '#e2b1ff',
|
|
12
|
-
'--jp-collaborator-color7': '#ff9de6'
|
|
12
|
+
'--jp-collaborator-color7': '#ff9de6',
|
|
13
13
|
};
|
|
14
14
|
export const jpCssToColor = (cssVariableName) => {
|
|
15
15
|
return JUPYTERLAB_COLLABORATORS_COLORS[cssVariableName.replaceAll('var(', '').replaceAll(')', '')];
|
package/lib/utils/Avatar.js
CHANGED
|
@@ -26,8 +26,8 @@ export function stringAvatar(name) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
export function getAvatarURL(url) {
|
|
29
|
-
return url
|
|
30
|
-
url.startsWith('https://www.gravatar.com/avatar')
|
|
29
|
+
return url
|
|
30
|
+
? url.startsWith('https://www.gravatar.com/avatar')
|
|
31
31
|
? `${url}?v=4&s=200&d=${DEFAULT_AVATAR_URL_ENCODED}` // Use gravatar syntax - sizing works for Gravatar and GitHub
|
|
32
32
|
: url
|
|
33
33
|
: DEFAULT_AVATAR_URL; // This fallback should barely be used - hence we allow decoding the URI.
|
package/lib/utils/Browser.js
CHANGED
|
@@ -8,22 +8,22 @@ export const detectBrowser = () => {
|
|
|
8
8
|
const userAgent = navigator.userAgent;
|
|
9
9
|
let browserName;
|
|
10
10
|
if (userAgent.match(/chrome|chromium|crios/i)) {
|
|
11
|
-
browserName =
|
|
11
|
+
browserName = 'chrome';
|
|
12
12
|
}
|
|
13
13
|
else if (userAgent.match(/firefox|fxios/i)) {
|
|
14
|
-
browserName =
|
|
14
|
+
browserName = 'firefox';
|
|
15
15
|
}
|
|
16
16
|
else if (userAgent.match(/safari/i)) {
|
|
17
|
-
browserName =
|
|
17
|
+
browserName = 'safari';
|
|
18
18
|
}
|
|
19
19
|
else if (userAgent.match(/opr\//i)) {
|
|
20
|
-
browserName =
|
|
20
|
+
browserName = 'opera';
|
|
21
21
|
}
|
|
22
22
|
else if (userAgent.match(/edg/i)) {
|
|
23
|
-
browserName =
|
|
23
|
+
browserName = 'edge';
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
|
-
browserName =
|
|
26
|
+
browserName = 'Unknow browser.';
|
|
27
27
|
}
|
|
28
28
|
return browserName;
|
|
29
29
|
};
|
package/lib/utils/Cells.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { IDataset } from
|
|
1
|
+
import { IDataset } from '../models';
|
|
2
2
|
export declare const getDatasetCell: (dataset: IDataset) => string;
|
package/lib/utils/Cookie.js
CHANGED
|
@@ -16,7 +16,7 @@ export function getCookie(cname) {
|
|
|
16
16
|
return cookie;
|
|
17
17
|
}
|
|
18
18
|
// From https://www.w3schools.com/js/js_cookies.asp
|
|
19
|
-
const name = cname +
|
|
19
|
+
const name = cname + '=';
|
|
20
20
|
const decodedCookie = decodeURIComponent(document.cookie);
|
|
21
21
|
const ca = decodedCookie.split(';');
|
|
22
22
|
for (let i = 0; i < ca.length; i++) {
|
package/lib/utils/Date.js
CHANGED
|
@@ -10,11 +10,11 @@ const units = {
|
|
|
10
10
|
day: 24 * 60 * 60 * 1000,
|
|
11
11
|
hour: 60 * 60 * 1000,
|
|
12
12
|
minute: 60 * 1000,
|
|
13
|
-
second: 1000
|
|
13
|
+
second: 1000,
|
|
14
14
|
};
|
|
15
15
|
const rtf = new Intl.RelativeTimeFormat(undefined, {
|
|
16
16
|
numeric: 'auto',
|
|
17
|
-
style: 'short'
|
|
17
|
+
style: 'short',
|
|
18
18
|
});
|
|
19
19
|
export const getRelativeTime = (d1, d2 = new Date()) => {
|
|
20
20
|
const elapsed = d1.getTime() - d2.getTime();
|
package/lib/utils/Download.js
CHANGED
|
@@ -9,10 +9,10 @@ export function jsonToCSVString(json) {
|
|
|
9
9
|
json.forEach(obj => {
|
|
10
10
|
const rowCells = headers.map(header => {
|
|
11
11
|
const val = obj[header];
|
|
12
|
-
if (typeof val ===
|
|
12
|
+
if (typeof val === 'number') {
|
|
13
13
|
return val;
|
|
14
14
|
}
|
|
15
|
-
if (typeof val ===
|
|
15
|
+
if (typeof val === 'string') {
|
|
16
16
|
return val;
|
|
17
17
|
}
|
|
18
18
|
if (val instanceof Date) {
|
|
@@ -26,7 +26,9 @@ export function jsonToCSVString(json) {
|
|
|
26
26
|
return csvString;
|
|
27
27
|
}
|
|
28
28
|
export const downloadJson = (data, fileName, extension) => {
|
|
29
|
-
const jsonData = new Blob([JSON.stringify(data)], {
|
|
29
|
+
const jsonData = new Blob([JSON.stringify(data)], {
|
|
30
|
+
type: 'application/json',
|
|
31
|
+
});
|
|
30
32
|
const jsonURL = URL.createObjectURL(jsonData);
|
|
31
33
|
const jsonLink = document.createElement('a');
|
|
32
34
|
jsonLink.href = jsonURL;
|
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
* .zip ZIP archive application/zip
|
|
12
12
|
*/
|
|
13
13
|
export const downloadFile = (data, filename, mime, bom) => {
|
|
14
|
-
const blobData =
|
|
14
|
+
const blobData = typeof bom !== 'undefined' ? [bom, data] : [data];
|
|
15
15
|
const blob = new Blob(blobData, { type: mime || 'application/octet-stream' });
|
|
16
|
-
const blobURL =
|
|
16
|
+
const blobURL = window.URL && window.URL.createObjectURL
|
|
17
|
+
? window.URL.createObjectURL(blob)
|
|
18
|
+
: window.webkitURL.createObjectURL(blob);
|
|
17
19
|
const tempLink = document.createElement('a');
|
|
18
20
|
tempLink.style.display = 'none';
|
|
19
21
|
tempLink.href = blobURL;
|
package/lib/utils/Env.js
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
export const isDevDeployment = () => {
|
|
6
|
-
return location.hostname.startsWith('dev') ||
|
|
6
|
+
return (location.hostname.startsWith('dev') ||
|
|
7
|
+
location.hostname.startsWith('localhost'));
|
|
7
8
|
};
|