@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.
- package/package.json +15 -16
- package/src/ShellContextProvider.js +20 -0
- package/src/app-header/AppHeader.css.js +21 -0
- package/src/app-header/AppHeader.js +97 -0
- package/src/app-header/index.js +1 -0
- package/src/application-provider/ApplicationContext.js +9 -0
- package/src/application-provider/ApplicationProvider.js +77 -0
- package/src/application-provider/index.js +1 -0
- package/src/feature/Feature.js +37 -0
- package/src/feature/FeatureErrorBoundary.js +33 -0
- package/src/feature/Loader.js +5 -0
- package/src/feature/index.js +1 -0
- package/src/feature-and-layout-provider/FeatureAndLayoutProvider.js +42 -0
- package/src/feature-and-layout-provider/index.js +1 -0
- package/src/feature-list/FeatureList.css.js +62 -0
- package/src/feature-list/FeatureList.js +128 -0
- package/src/feature-list/index.js +1 -0
- package/src/get-layout-history.js +7 -0
- package/src/index.js +14 -0
- package/src/left-nav/LeftNav.css.js +177 -0
- package/src/left-nav/LeftNav.js +193 -0
- package/src/left-nav/index.js +1 -0
- package/src/login/LoginPanel.css.js +72 -0
- package/src/login/LoginPanel.js +124 -0
- package/src/login/VuuLogo.js +108 -0
- package/src/persistence-manager/LocalPersistenceManager.js +156 -0
- package/src/persistence-manager/PersistenceManager.js +0 -0
- package/src/persistence-manager/PersistenceProvider.js +14 -0
- package/src/persistence-manager/RemotePersistenceManager.js +123 -0
- package/src/persistence-manager/StaticPersistenceManager.js +53 -0
- package/src/persistence-manager/index.js +5 -0
- package/src/shell-layout-templates/context-panel/ContextPanel.css.js +66 -0
- package/src/shell-layout-templates/context-panel/ContextPanel.js +92 -0
- package/src/shell-layout-templates/context-panel/index.js +1 -0
- package/src/shell-layout-templates/full-height-left-panel/useFullHeightLeftPanel.js +44 -0
- package/src/shell-layout-templates/index.js +3 -0
- package/src/shell-layout-templates/inlay-left-panel/useInlayLeftPanel.js +68 -0
- package/src/shell-layout-templates/left-main-tabs/useLeftMainTabs.js +32 -0
- package/src/shell-layout-templates/side-panel/SidePanel.css.js +9 -0
- package/src/shell-layout-templates/side-panel/SidePanel.js +31 -0
- package/src/shell-layout-templates/side-panel/index.js +1 -0
- package/src/shell-layout-templates/simple-content-pane/useSimpleContentPane.js +38 -0
- package/src/shell-layout-templates/useShellLayout.js +15 -0
- package/src/shell.css.js +59 -0
- package/src/shell.js +108 -0
- package/src/theme-switch/ThemeSwitch.css.js +34 -0
- package/src/theme-switch/ThemeSwitch.js +50 -0
- package/src/theme-switch/index.js +1 -0
- package/src/user-settings/SettingsForm.css.js +10 -0
- package/src/user-settings/SettingsForm.js +141 -0
- package/src/user-settings/UserSettingsPanel.css.js +9 -0
- package/src/user-settings/UserSettingsPanel.js +29 -0
- package/src/user-settings/index.js +2 -0
- package/src/workspace-management/LayoutList.css.js +74 -0
- package/src/workspace-management/LayoutList.js +130 -0
- package/src/workspace-management/LayoutTile.css.js +31 -0
- package/src/workspace-management/LayoutTile.js +41 -0
- package/src/workspace-management/SaveLayoutPanel.css.js +123 -0
- package/src/workspace-management/SaveLayoutPanel.js +141 -0
- package/src/workspace-management/WorkspaceProvider.js +209 -0
- package/src/workspace-management/defaultWorkspaceJSON.js +88 -0
- package/src/workspace-management/index.js +5 -0
- package/src/workspace-management/screenshot-utils.js +13 -0
- 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,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 };
|