@vuu-ui/vuu-shell 2.1.19-beta.1 → 2.1.19-beta.2

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.
Files changed (64) hide show
  1. package/package.json +15 -16
  2. package/src/ShellContextProvider.js +20 -0
  3. package/src/app-header/AppHeader.css.js +21 -0
  4. package/src/app-header/AppHeader.js +97 -0
  5. package/src/app-header/index.js +1 -0
  6. package/src/application-provider/ApplicationContext.js +9 -0
  7. package/src/application-provider/ApplicationProvider.js +77 -0
  8. package/src/application-provider/index.js +1 -0
  9. package/src/feature/Feature.js +37 -0
  10. package/src/feature/FeatureErrorBoundary.js +33 -0
  11. package/src/feature/Loader.js +5 -0
  12. package/src/feature/index.js +1 -0
  13. package/src/feature-and-layout-provider/FeatureAndLayoutProvider.js +42 -0
  14. package/src/feature-and-layout-provider/index.js +1 -0
  15. package/src/feature-list/FeatureList.css.js +62 -0
  16. package/src/feature-list/FeatureList.js +128 -0
  17. package/src/feature-list/index.js +1 -0
  18. package/src/get-layout-history.js +7 -0
  19. package/src/index.js +14 -0
  20. package/src/left-nav/LeftNav.css.js +177 -0
  21. package/src/left-nav/LeftNav.js +193 -0
  22. package/src/left-nav/index.js +1 -0
  23. package/src/login/LoginPanel.css.js +72 -0
  24. package/src/login/LoginPanel.js +124 -0
  25. package/src/login/VuuLogo.js +108 -0
  26. package/src/persistence-manager/LocalPersistenceManager.js +156 -0
  27. package/src/persistence-manager/PersistenceManager.js +0 -0
  28. package/src/persistence-manager/PersistenceProvider.js +14 -0
  29. package/src/persistence-manager/RemotePersistenceManager.js +123 -0
  30. package/src/persistence-manager/StaticPersistenceManager.js +53 -0
  31. package/src/persistence-manager/index.js +5 -0
  32. package/src/shell-layout-templates/context-panel/ContextPanel.css.js +66 -0
  33. package/src/shell-layout-templates/context-panel/ContextPanel.js +92 -0
  34. package/src/shell-layout-templates/context-panel/index.js +1 -0
  35. package/src/shell-layout-templates/full-height-left-panel/useFullHeightLeftPanel.js +44 -0
  36. package/src/shell-layout-templates/index.js +3 -0
  37. package/src/shell-layout-templates/inlay-left-panel/useInlayLeftPanel.js +68 -0
  38. package/src/shell-layout-templates/left-main-tabs/useLeftMainTabs.js +32 -0
  39. package/src/shell-layout-templates/side-panel/SidePanel.css.js +9 -0
  40. package/src/shell-layout-templates/side-panel/SidePanel.js +31 -0
  41. package/src/shell-layout-templates/side-panel/index.js +1 -0
  42. package/src/shell-layout-templates/simple-content-pane/useSimpleContentPane.js +38 -0
  43. package/src/shell-layout-templates/useShellLayout.js +15 -0
  44. package/src/shell.css.js +59 -0
  45. package/src/shell.js +108 -0
  46. package/src/theme-switch/ThemeSwitch.css.js +34 -0
  47. package/src/theme-switch/ThemeSwitch.js +50 -0
  48. package/src/theme-switch/index.js +1 -0
  49. package/src/user-settings/SettingsForm.css.js +10 -0
  50. package/src/user-settings/SettingsForm.js +141 -0
  51. package/src/user-settings/UserSettingsPanel.css.js +9 -0
  52. package/src/user-settings/UserSettingsPanel.js +29 -0
  53. package/src/user-settings/index.js +2 -0
  54. package/src/workspace-management/LayoutList.css.js +74 -0
  55. package/src/workspace-management/LayoutList.js +130 -0
  56. package/src/workspace-management/LayoutTile.css.js +31 -0
  57. package/src/workspace-management/LayoutTile.js +41 -0
  58. package/src/workspace-management/SaveLayoutPanel.css.js +123 -0
  59. package/src/workspace-management/SaveLayoutPanel.js +141 -0
  60. package/src/workspace-management/WorkspaceProvider.js +209 -0
  61. package/src/workspace-management/defaultWorkspaceJSON.js +88 -0
  62. package/src/workspace-management/index.js +5 -0
  63. package/src/workspace-management/screenshot-utils.js +13 -0
  64. package/src/workspace-management/useWorkspaceContextMenuItems.js +58 -0
@@ -0,0 +1,209 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { isLayoutJSON, resolveJSONPath } from "@vuu-ui/vuu-layout";
3
+ import { useNotifications } from "@vuu-ui/vuu-notifications";
4
+ import { VuuShellLocation, WorkspaceContext, logger } from "@vuu-ui/vuu-utils";
5
+ import { useCallback, useContext, useEffect, useRef, useState } from "react";
6
+ import { usePersistenceManager } from "../persistence-manager/index.js";
7
+ import { getWorkspaceWithLayoutJSON, loadingJSON } from "./defaultWorkspaceJSON.js";
8
+ const { info: info } = logger("useLayoutManager");
9
+ const ensureLayoutHasTitle = (layout, layoutMetadata)=>{
10
+ if (layout.props?.title !== void 0) return layout;
11
+ return {
12
+ ...layout,
13
+ props: {
14
+ ...layout.props,
15
+ title: layoutMetadata.name
16
+ }
17
+ };
18
+ };
19
+ const loadingApplicationJSON = {
20
+ workspaceJSON: loadingJSON
21
+ };
22
+ const WorkspaceProvider = ({ TabstripProps, children, layoutJSON, activeLayoutIndex, layoutPlaceholderJSON, showTabs, workspaceJSON: customWorkspaceJSON })=>{
23
+ const [layoutMetadata, setLayoutMetadata] = useState([]);
24
+ const [, forceRefresh] = useState({});
25
+ const { showNotification } = useNotifications();
26
+ const persistenceManager = usePersistenceManager();
27
+ const applicationJSONRef = useRef(loadingApplicationJSON);
28
+ const setApplicationJSON = useCallback((applicationJSON, rerender = true)=>{
29
+ applicationJSONRef.current = applicationJSON;
30
+ if (rerender) forceRefresh({});
31
+ }, []);
32
+ const setWorkspaceJSON = useCallback((workspaceJSON, rerender = true)=>{
33
+ setApplicationJSON({
34
+ ...applicationJSONRef.current,
35
+ workspaceJSON
36
+ }, rerender);
37
+ }, [
38
+ setApplicationJSON
39
+ ]);
40
+ const setApplicationSettings = useCallback((settings)=>{
41
+ setApplicationJSON({
42
+ ...applicationJSONRef.current,
43
+ settings: {
44
+ ...applicationJSONRef.current.settings,
45
+ ...settings
46
+ }
47
+ }, false);
48
+ }, [
49
+ setApplicationJSON
50
+ ]);
51
+ useEffect(()=>{
52
+ persistenceManager?.loadMetadata().then((metadata)=>{
53
+ setLayoutMetadata(metadata);
54
+ }).catch((error)=>{
55
+ showNotification({
56
+ content: "Could not load list of available layouts",
57
+ header: "Failed to Load Layouts",
58
+ status: "error",
59
+ type: "toast"
60
+ });
61
+ console.error("Error occurred while retrieving metadata", error);
62
+ });
63
+ persistenceManager?.loadApplicationJSON().then((applicationJSON)=>{
64
+ if (applicationJSON) {
65
+ info?.("applicationJSON loaded successfully");
66
+ setApplicationJSON(applicationJSON);
67
+ } else {
68
+ const workspaceJSON = getWorkspaceWithLayoutJSON(customWorkspaceJSON, layoutJSON, activeLayoutIndex, {
69
+ TabstripProps,
70
+ showTabs
71
+ });
72
+ info?.(`applicationJSON not found, getting defaultWorkspaceJSON,
73
+ ${JSON.stringify(workspaceJSON, null, 2)}
74
+ `);
75
+ setApplicationJSON({
76
+ workspaceJSON
77
+ });
78
+ }
79
+ }).catch((error)=>{
80
+ showNotification({
81
+ content: "Could not load your latest view",
82
+ header: "Failed to Load Layout",
83
+ status: "error",
84
+ type: "toast"
85
+ });
86
+ console.error("Error occurred while retrieving application layout", error);
87
+ });
88
+ }, [
89
+ TabstripProps,
90
+ activeLayoutIndex,
91
+ customWorkspaceJSON,
92
+ layoutJSON,
93
+ showNotification,
94
+ persistenceManager,
95
+ setApplicationJSON,
96
+ showTabs
97
+ ]);
98
+ const saveApplicationLayout = useCallback((layout)=>{
99
+ if (isLayoutJSON(layout)) {
100
+ setWorkspaceJSON(layout, false);
101
+ persistenceManager?.saveApplicationJSON(applicationJSONRef.current);
102
+ } else console.error("Tried to save invalid application layout", layout);
103
+ }, [
104
+ persistenceManager,
105
+ setWorkspaceJSON
106
+ ]);
107
+ const saveLayout = useCallback((metadata)=>{
108
+ let layoutToSave;
109
+ try {
110
+ const { workspaceJSON } = applicationJSONRef.current;
111
+ if (Array.isArray(workspaceJSON)) console.log("how do we identify the right thing to save");
112
+ else layoutToSave = resolveJSONPath(workspaceJSON, `#${VuuShellLocation.Workspace}.ACTIVE_CHILD`);
113
+ } catch (e) {}
114
+ if (layoutToSave && isLayoutJSON(layoutToSave)) persistenceManager?.createLayout(metadata, ensureLayoutHasTitle(layoutToSave, metadata)).then((metadata)=>{
115
+ showNotification({
116
+ content: `${metadata.name} saved successfully`,
117
+ header: "Layout Saved Successfully",
118
+ status: "success",
119
+ type: "toast"
120
+ });
121
+ setLayoutMetadata((prev)=>[
122
+ ...prev,
123
+ metadata
124
+ ]);
125
+ }).catch((error)=>{
126
+ showNotification({
127
+ content: `Failed to save layout ${metadata.name}`,
128
+ header: "Failed to Save Layout",
129
+ status: "error",
130
+ type: "toast"
131
+ });
132
+ console.error("Error occurred while saving layout", error);
133
+ });
134
+ else {
135
+ console.error("Tried to save invalid layout", layoutToSave);
136
+ showNotification({
137
+ content: "Cannot save invalid layout",
138
+ header: "Failed to Save Layout",
139
+ status: "error",
140
+ type: "toast"
141
+ });
142
+ }
143
+ }, [
144
+ showNotification,
145
+ persistenceManager
146
+ ]);
147
+ const saveApplicationSettings = useCallback((settings, key)=>{
148
+ const { settings: applicationSettings } = applicationJSONRef.current;
149
+ key ? setApplicationSettings({
150
+ ...applicationSettings,
151
+ [key]: settings
152
+ }) : setApplicationSettings(settings);
153
+ persistenceManager?.saveApplicationJSON(applicationJSONRef.current);
154
+ }, [
155
+ persistenceManager,
156
+ setApplicationSettings
157
+ ]);
158
+ const getApplicationSettings = useCallback((key)=>{
159
+ const { settings } = applicationJSONRef.current;
160
+ return key ? settings?.[key] : settings;
161
+ }, []);
162
+ const loadLayoutById = useCallback((id)=>{
163
+ persistenceManager?.loadLayout(id).then((layoutJson)=>{
164
+ const { workspaceJSON: currentLayout } = applicationJSONRef.current;
165
+ if (Array.isArray(currentLayout)) console.log("how do we deal witha amulti layoput");
166
+ else setWorkspaceJSON({
167
+ ...currentLayout,
168
+ children: (currentLayout.children || []).concat(layoutJson),
169
+ props: {
170
+ ...currentLayout.props,
171
+ active: currentLayout.children?.length ?? 0
172
+ }
173
+ });
174
+ }).catch((error)=>{
175
+ showNotification({
176
+ content: "Failed to load the requested layout",
177
+ header: "Failed to Load Layout",
178
+ status: "error",
179
+ type: "toast"
180
+ });
181
+ console.error("Error occurred while loading layout", error);
182
+ });
183
+ }, [
184
+ showNotification,
185
+ persistenceManager,
186
+ setWorkspaceJSON
187
+ ]);
188
+ return /*#__PURE__*/ jsx(WorkspaceContext.Provider, {
189
+ value: {
190
+ getApplicationSettings,
191
+ layoutMetadata,
192
+ layoutPlaceholderJSON,
193
+ saveLayout,
194
+ workspaceJSON: applicationJSONRef.current.workspaceJSON,
195
+ saveApplicationLayout,
196
+ saveApplicationSettings,
197
+ loadLayoutById
198
+ },
199
+ children: children
200
+ });
201
+ };
202
+ const useWorkspace = ()=>{
203
+ const { workspaceJSON = getWorkspaceWithLayoutJSON(), ...contextProps } = useContext(WorkspaceContext);
204
+ return {
205
+ ...contextProps,
206
+ workspaceJSON
207
+ };
208
+ };
209
+ export { WorkspaceProvider, useWorkspace };
@@ -0,0 +1,88 @@
1
+ import { VuuShellLocation } from "@vuu-ui/vuu-utils";
2
+ const warningLayout = {
3
+ type: "View",
4
+ props: {
5
+ style: {
6
+ height: "calc(100% - 6px)"
7
+ }
8
+ },
9
+ children: [
10
+ {
11
+ props: {
12
+ className: "vuuShell-warningPlaceholder"
13
+ },
14
+ type: "Placeholder"
15
+ }
16
+ ]
17
+ };
18
+ const loadingJSON = {
19
+ type: "Component",
20
+ id: "loading-main",
21
+ props: {}
22
+ };
23
+ const defaultWorkspaceJSON = {
24
+ type: "Stack",
25
+ id: VuuShellLocation.Workspace,
26
+ props: {
27
+ className: `${VuuShellLocation.Workspace}-tabs`,
28
+ TabstripProps: {
29
+ allowAddTab: true,
30
+ allowCloseTab: true,
31
+ allowRenameTab: true,
32
+ animateSelectionThumb: false,
33
+ "aria-label": "Workspace Tabs",
34
+ location: "workspace-tab",
35
+ variant: "primary"
36
+ },
37
+ preserve: true
38
+ }
39
+ };
40
+ const getStackWorkspaceJSON = (activeLayoutIndex)=>({
41
+ ...defaultWorkspaceJSON,
42
+ active: activeLayoutIndex ?? 0
43
+ });
44
+ const placeholderLayout = {
45
+ props: {
46
+ id: "tab1",
47
+ title: "Tab 1",
48
+ className: "vuuShell-Placeholder"
49
+ },
50
+ type: "Placeholder"
51
+ };
52
+ const getWorkspaceWithLayoutJSON = (customWorkspaceJSON, layoutJSON = placeholderLayout, activeLayoutIndex, stackProps)=>{
53
+ const stackWorkspace = getStackWorkspaceJSON(activeLayoutIndex);
54
+ if (Array.isArray(customWorkspaceJSON)) {
55
+ const workspace = customWorkspaceJSON.find((layout)=>layout.id === VuuShellLocation.Workspace);
56
+ if (workspace) return customWorkspaceJSON.map((ws)=>{
57
+ if (ws.id === VuuShellLocation.Workspace) return {
58
+ ...ws,
59
+ children: Array.isArray(layoutJSON) ? layoutJSON : [
60
+ layoutJSON
61
+ ]
62
+ };
63
+ return ws;
64
+ });
65
+ throw Error("Multiple workspaces have been provided but none has the workspace id");
66
+ }
67
+ if (customWorkspaceJSON) return {
68
+ ...customWorkspaceJSON,
69
+ children: Array.isArray(layoutJSON) ? layoutJSON : [
70
+ layoutJSON
71
+ ]
72
+ };
73
+ return {
74
+ ...stackWorkspace,
75
+ props: {
76
+ ...stackWorkspace.props,
77
+ ...stackProps,
78
+ TabstripProps: {
79
+ ...stackWorkspace.props?.TabstripProps,
80
+ ...stackProps?.TabstripProps
81
+ }
82
+ },
83
+ children: Array.isArray(layoutJSON) ? layoutJSON : [
84
+ layoutJSON
85
+ ]
86
+ };
87
+ };
88
+ export { defaultWorkspaceJSON, getStackWorkspaceJSON, getWorkspaceWithLayoutJSON, loadingJSON, warningLayout };
@@ -0,0 +1,5 @@
1
+ export * from "./SaveLayoutPanel.js";
2
+ export * from "./LayoutList.js";
3
+ export * from "./WorkspaceProvider.js";
4
+ export * from "./defaultWorkspaceJSON.js";
5
+ export * from "./useWorkspaceContextMenuItems.js";
@@ -0,0 +1,13 @@
1
+ import { toPng } from "html-to-image";
2
+ const takeScreenshot = (node)=>new Promise((resolve, reject)=>{
3
+ toPng(node, {
4
+ cacheBust: true
5
+ }).then((screenshot)=>{
6
+ if (!screenshot) reject(new Error("No Screenshot available"));
7
+ resolve(screenshot);
8
+ }).catch((error)=>{
9
+ console.error("the following error occurred while taking a screenshot of a DOMNode", error);
10
+ reject(new Error("Error taking screenshot"));
11
+ });
12
+ });
13
+ export { takeScreenshot };
@@ -0,0 +1,58 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useModal } from "@vuu-ui/vuu-ui-controls";
3
+ import { useCallback, useMemo } from "react";
4
+ import { SaveLayoutPanel } from "./SaveLayoutPanel.js";
5
+ import { useWorkspace } from "./WorkspaceProvider.js";
6
+ const useWorkspaceContextMenuItems = ()=>{
7
+ const { saveLayout } = useWorkspace();
8
+ const { showDialog, closeDialog } = useModal();
9
+ const handleCloseDialog = useCallback(()=>{
10
+ closeDialog();
11
+ }, [
12
+ closeDialog
13
+ ]);
14
+ const handleSave = useCallback((layoutMetadata)=>{
15
+ saveLayout(layoutMetadata);
16
+ closeDialog();
17
+ }, [
18
+ saveLayout,
19
+ closeDialog
20
+ ]);
21
+ const [buildMenuOptions, handleMenuAction] = useMemo(()=>[
22
+ (location, options)=>{
23
+ const locations = location.split(" ");
24
+ const menuDescriptors = [];
25
+ if (locations.includes("workspace-tab")) menuDescriptors.push({
26
+ label: "Save Layout",
27
+ id: "save-layout",
28
+ options
29
+ }, {
30
+ label: "Layout Settings",
31
+ id: "layout-settings",
32
+ options
33
+ });
34
+ return menuDescriptors;
35
+ },
36
+ (menuItemId, options)=>{
37
+ if ("save-layout" === menuItemId) {
38
+ showDialog(/*#__PURE__*/ jsx(SaveLayoutPanel, {
39
+ onCancel: handleCloseDialog,
40
+ onSave: handleSave,
41
+ componentId: options?.controlledComponentId,
42
+ defaultTitle: options?.controlledComponentTitle
43
+ }), "Save Layout", [], true);
44
+ return true;
45
+ }
46
+ return false;
47
+ }
48
+ ], [
49
+ handleCloseDialog,
50
+ handleSave,
51
+ showDialog
52
+ ]);
53
+ return {
54
+ buildMenuOptions,
55
+ handleMenuAction
56
+ };
57
+ };
58
+ export { useWorkspaceContextMenuItems };