@vuu-ui/vuu-shell 0.5.4 → 0.5.6
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/cjs/index.js +1 -554
- package/cjs/index.js.map +7 -0
- package/esm/index.js +2 -0
- package/esm/index.js.map +7 -0
- package/index.css +1 -77
- package/index.css.map +1 -1
- package/package.json +7 -11
- package/src/ShellContextProvider.tsx +0 -54
- package/src/app-header/AppHeader.css +0 -6
- package/src/app-header/AppHeader.tsx +0 -33
- package/src/app-header/index.ts +0 -1
- package/src/app-palette/AppPalette.tsx +0 -56
- package/src/app-palette/index.ts +0 -1
- package/src/feature/ErrorBoundary.jsx +0 -31
- package/src/feature/Feature.tsx +0 -52
- package/src/feature/Loader.tsx +0 -2
- package/src/feature/css-module-loader.ts +0 -6
- package/src/feature/index.ts +0 -1
- package/src/get-layout-history.js +0 -12
- package/src/index.ts +0 -6
- package/src/login/LoginPanel.css +0 -24
- package/src/login/LoginPanel.tsx +0 -63
- package/src/login/index.ts +0 -2
- package/src/login/login-utils.ts +0 -21
- package/src/shell.css +0 -15
- package/src/shell.tsx +0 -171
- package/src/shellTypes.ts +0 -18
- package/src/use-force-render.js +0 -6
- package/src/use-layout-config.js +0 -55
- package/src/user-profile/UserPanel.css +0 -26
- package/src/user-profile/UserPanel.tsx +0 -81
- package/src/user-profile/UserProfile.css +0 -3
- package/src/user-profile/UserProfile.tsx +0 -47
- package/src/user-profile/index.ts +0 -1
package/src/shell.tsx
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { connectToServer } from "@vuu-ui/vuu-data";
|
|
2
|
-
import {
|
|
3
|
-
HTMLAttributes,
|
|
4
|
-
MouseEvent,
|
|
5
|
-
ReactElement,
|
|
6
|
-
ReactNode,
|
|
7
|
-
useCallback,
|
|
8
|
-
useEffect,
|
|
9
|
-
useRef,
|
|
10
|
-
useState,
|
|
11
|
-
} from "react";
|
|
12
|
-
import useLayoutConfig from "./use-layout-config";
|
|
13
|
-
import { ShellContextProvider } from "./ShellContextProvider";
|
|
14
|
-
import cx from "classnames";
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
Chest,
|
|
18
|
-
DraggableLayout,
|
|
19
|
-
Drawer,
|
|
20
|
-
FlexboxLayout as Flexbox,
|
|
21
|
-
LayoutProvider,
|
|
22
|
-
View,
|
|
23
|
-
} from "@vuu-ui/vuu-layout";
|
|
24
|
-
|
|
25
|
-
import { AppHeader } from "./app-header";
|
|
26
|
-
// import { AppPalette } from "./app-palette";
|
|
27
|
-
|
|
28
|
-
import { LayoutJSON } from "@vuu-ui/vuu-layout/src/layout-reducer";
|
|
29
|
-
import "./shell.css";
|
|
30
|
-
|
|
31
|
-
export type VuuUser = {
|
|
32
|
-
username: string;
|
|
33
|
-
token: string;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const warningLayout = {
|
|
37
|
-
type: "View",
|
|
38
|
-
props: {
|
|
39
|
-
style: { height: "calc(100% - 6px)" },
|
|
40
|
-
},
|
|
41
|
-
children: [
|
|
42
|
-
{
|
|
43
|
-
props: {
|
|
44
|
-
className: "vuuShell-warningPlaceholder",
|
|
45
|
-
},
|
|
46
|
-
type: "Placeholder",
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export interface ShellProps extends HTMLAttributes<HTMLDivElement> {
|
|
52
|
-
children?: ReactNode;
|
|
53
|
-
defaultLayout?: LayoutJSON;
|
|
54
|
-
leftSidePanel?: ReactElement;
|
|
55
|
-
loginUrl?: string;
|
|
56
|
-
// paletteConfig: any;
|
|
57
|
-
serverUrl?: string;
|
|
58
|
-
user: VuuUser;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export const Shell = ({
|
|
62
|
-
children,
|
|
63
|
-
className,
|
|
64
|
-
defaultLayout = warningLayout,
|
|
65
|
-
leftSidePanel,
|
|
66
|
-
loginUrl,
|
|
67
|
-
serverUrl,
|
|
68
|
-
user,
|
|
69
|
-
...htmlAttributes
|
|
70
|
-
}: ShellProps) => {
|
|
71
|
-
const paletteView = useRef<HTMLDivElement>(null);
|
|
72
|
-
const [open, setOpen] = useState(false);
|
|
73
|
-
const layoutId = useRef("latest");
|
|
74
|
-
|
|
75
|
-
const [layout, setLayoutConfig, loadLayoutById] = useLayoutConfig(
|
|
76
|
-
user,
|
|
77
|
-
defaultLayout
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const handleLayoutChange = useCallback(
|
|
81
|
-
(layout) => {
|
|
82
|
-
setLayoutConfig(layout);
|
|
83
|
-
},
|
|
84
|
-
[setLayoutConfig]
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const handleDrawerClick = (e: MouseEvent<HTMLElement>) => {
|
|
88
|
-
const target = e.target as HTMLElement;
|
|
89
|
-
if (!paletteView.current?.contains(target)) {
|
|
90
|
-
setOpen(!open);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const handleNavigate = useCallback(
|
|
95
|
-
(id) => {
|
|
96
|
-
layoutId.current = id;
|
|
97
|
-
loadLayoutById(id);
|
|
98
|
-
},
|
|
99
|
-
[loadLayoutById]
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
useEffect(() => {
|
|
103
|
-
if (serverUrl && user.token) {
|
|
104
|
-
connectToServer(serverUrl, user.token);
|
|
105
|
-
}
|
|
106
|
-
}, [serverUrl, user.token]);
|
|
107
|
-
|
|
108
|
-
const getDrawers = () => {
|
|
109
|
-
const drawers: ReactElement[] = [];
|
|
110
|
-
if (leftSidePanel) {
|
|
111
|
-
drawers.push(
|
|
112
|
-
<Drawer
|
|
113
|
-
key="left-panel"
|
|
114
|
-
onClick={handleDrawerClick}
|
|
115
|
-
open={open}
|
|
116
|
-
position="left"
|
|
117
|
-
inline
|
|
118
|
-
peekaboo
|
|
119
|
-
sizeOpen={200}
|
|
120
|
-
toggleButton="end"
|
|
121
|
-
>
|
|
122
|
-
<View
|
|
123
|
-
className="vuuShell-palette"
|
|
124
|
-
id="vw-app-palette"
|
|
125
|
-
key="app-palette"
|
|
126
|
-
ref={paletteView}
|
|
127
|
-
style={{ height: "100%" }}
|
|
128
|
-
>
|
|
129
|
-
{leftSidePanel}
|
|
130
|
-
</View>
|
|
131
|
-
</Drawer>
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return drawers;
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
return (
|
|
139
|
-
// ShellContext TBD
|
|
140
|
-
<ShellContextProvider value={undefined}>
|
|
141
|
-
<LayoutProvider layout={layout} onLayoutChange={handleLayoutChange}>
|
|
142
|
-
<DraggableLayout
|
|
143
|
-
className={cx("vuuShell", className)}
|
|
144
|
-
{...htmlAttributes}
|
|
145
|
-
>
|
|
146
|
-
<Flexbox
|
|
147
|
-
className="App"
|
|
148
|
-
style={{ flexDirection: "column", height: "100%", width: "100%" }}
|
|
149
|
-
>
|
|
150
|
-
<AppHeader
|
|
151
|
-
layoutId={layoutId.current}
|
|
152
|
-
loginUrl={loginUrl}
|
|
153
|
-
user={user}
|
|
154
|
-
onNavigate={handleNavigate}
|
|
155
|
-
/>
|
|
156
|
-
<Chest style={{ flex: 1 }}>
|
|
157
|
-
{getDrawers().concat(
|
|
158
|
-
<DraggableLayout
|
|
159
|
-
dropTarget
|
|
160
|
-
key="main-content"
|
|
161
|
-
style={{ width: "100%", height: "100%" }}
|
|
162
|
-
/>
|
|
163
|
-
)}
|
|
164
|
-
</Chest>
|
|
165
|
-
</Flexbox>
|
|
166
|
-
</DraggableLayout>
|
|
167
|
-
</LayoutProvider>
|
|
168
|
-
{children}
|
|
169
|
-
</ShellContextProvider>
|
|
170
|
-
);
|
|
171
|
-
};
|
package/src/shellTypes.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
declare global {
|
|
2
|
-
const vuuConfig: Promise<VuuConfig>;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export interface FeatureConfig {
|
|
6
|
-
name: string;
|
|
7
|
-
title: string;
|
|
8
|
-
url: string;
|
|
9
|
-
css?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type Features = {
|
|
13
|
-
[key: string]: FeatureConfig;
|
|
14
|
-
};
|
|
15
|
-
export interface VuuConfig {
|
|
16
|
-
features?: Features;
|
|
17
|
-
websocketUrl: string;
|
|
18
|
-
}
|
package/src/use-force-render.js
DELETED
package/src/use-layout-config.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from "react";
|
|
2
|
-
|
|
3
|
-
const useLayoutConfig = (user, defaultLayout) => {
|
|
4
|
-
const [layout, _setLayout] = useState(defaultLayout);
|
|
5
|
-
|
|
6
|
-
const setLayout = (layout) => {
|
|
7
|
-
_setLayout(layout);
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const load = useCallback(
|
|
11
|
-
async (id = "latest") => {
|
|
12
|
-
fetch(`api/vui/${user.username}/${id}`, {})
|
|
13
|
-
.then((response) => {
|
|
14
|
-
return response.ok ? response.json() : defaultLayout;
|
|
15
|
-
})
|
|
16
|
-
.then(setLayout)
|
|
17
|
-
.catch(() => {
|
|
18
|
-
// TODO we should set a layout with a warning here
|
|
19
|
-
setLayout(defaultLayout);
|
|
20
|
-
});
|
|
21
|
-
},
|
|
22
|
-
[defaultLayout, user.username]
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
load();
|
|
27
|
-
}, [load]);
|
|
28
|
-
|
|
29
|
-
const saveData = useCallback(
|
|
30
|
-
(data) => {
|
|
31
|
-
fetch(`api/vui/${user.username}`, {
|
|
32
|
-
method: "POST",
|
|
33
|
-
headers: {
|
|
34
|
-
"Content-Type": "application/json",
|
|
35
|
-
},
|
|
36
|
-
body: JSON.stringify(data),
|
|
37
|
-
}).then((response) => {
|
|
38
|
-
return response.ok ? response.json() : defaultLayout;
|
|
39
|
-
});
|
|
40
|
-
// .then((data) => console.log(data));
|
|
41
|
-
},
|
|
42
|
-
[defaultLayout, user]
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const loadLayoutById = useCallback(
|
|
46
|
-
(id) => {
|
|
47
|
-
load(id);
|
|
48
|
-
},
|
|
49
|
-
[load]
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
return [layout, saveData, loadLayoutById];
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export default useLayoutConfig;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
.vuuUserPanel {
|
|
2
|
-
background-color: white;
|
|
3
|
-
display: flex;
|
|
4
|
-
flex-direction: column;
|
|
5
|
-
max-height: 400px;
|
|
6
|
-
padding: 12px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
vuuUserPanel-history {
|
|
10
|
-
flex: 1 1 auto;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.vuuUserPanel-buttonBar {
|
|
14
|
-
--saltButton-width: 100%;
|
|
15
|
-
align-items: flex-end;
|
|
16
|
-
border-top: 1px solid var(--surface3);
|
|
17
|
-
display: flex;
|
|
18
|
-
flex: 0 0 32px;
|
|
19
|
-
justify-content: flex-start;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.btn-logout {
|
|
23
|
-
--hwButton-icon-left: 12px;
|
|
24
|
-
--hwButton-padding: 0 6px 0 24px;
|
|
25
|
-
padding-left: 24px;
|
|
26
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef, useCallback, useEffect, useState } from "react";
|
|
2
|
-
import { formatDate } from "@vuu-ui/vuu-utils";
|
|
3
|
-
import { logout } from "../login";
|
|
4
|
-
import { getLayoutHistory } from "../get-layout-history";
|
|
5
|
-
import { ExportIcon } from "@salt-ds/icons";
|
|
6
|
-
import { Button } from "@salt-ds/core";
|
|
7
|
-
import { List, ListItem } from "@heswell/salt-lab";
|
|
8
|
-
|
|
9
|
-
import "./UserPanel.css";
|
|
10
|
-
|
|
11
|
-
const byLastUpdate = ({ lastUpdate: l1 }, { lastUpdate: l2 }) => {
|
|
12
|
-
return l2 === l1 ? 0 : l2 < l1 ? -1 : 1;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const HistoryListItem = (props) => {
|
|
16
|
-
return <ListItem {...props} />;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const UserPanel = forwardRef(function UserPanel(
|
|
20
|
-
{ loginUrl, onNavigate, user, layoutId = "latest" },
|
|
21
|
-
forwardedRef
|
|
22
|
-
) {
|
|
23
|
-
const [history, setHistory] = useState([]);
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
async function getHistory() {
|
|
27
|
-
const history = await getLayoutHistory(user);
|
|
28
|
-
console.log({ history });
|
|
29
|
-
const sortedHistory = history
|
|
30
|
-
.filter((item) => item.id !== "latest")
|
|
31
|
-
.sort(byLastUpdate)
|
|
32
|
-
.map(({ id, lastUpdate }) => ({
|
|
33
|
-
lastUpdate,
|
|
34
|
-
id,
|
|
35
|
-
label: `Saved at ${formatDate(new Date(lastUpdate), "kk:mm:ss")}`,
|
|
36
|
-
}));
|
|
37
|
-
console.log({ sortedHistory });
|
|
38
|
-
setHistory(sortedHistory);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
getHistory();
|
|
42
|
-
}, [user]);
|
|
43
|
-
|
|
44
|
-
const handleHisorySelected = useCallback(
|
|
45
|
-
(evt, selected) => {
|
|
46
|
-
if (selected) {
|
|
47
|
-
onNavigate(selected.id);
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
[onNavigate]
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const handleLogout = useCallback(() => {
|
|
54
|
-
logout(loginUrl);
|
|
55
|
-
}, [loginUrl]);
|
|
56
|
-
|
|
57
|
-
const selected =
|
|
58
|
-
history.length === 0
|
|
59
|
-
? []
|
|
60
|
-
: layoutId === "latest"
|
|
61
|
-
? history[0]
|
|
62
|
-
: history.find((i) => i.id === layoutId);
|
|
63
|
-
console.log({ selected });
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<div className="vuuUserPanel" ref={forwardedRef}>
|
|
67
|
-
<List
|
|
68
|
-
ListItem={HistoryListItem}
|
|
69
|
-
className="vuuUserPanel-history"
|
|
70
|
-
onSelect={handleHisorySelected}
|
|
71
|
-
selected={selected}
|
|
72
|
-
source={history}
|
|
73
|
-
/>
|
|
74
|
-
<div className="vuuUserPanel-buttonBar">
|
|
75
|
-
<Button aria-label="logout" onClick={handleLogout}>
|
|
76
|
-
<ExportIcon /> Logout
|
|
77
|
-
</Button>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
);
|
|
81
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import React, { useCallback, useRef, useState } from "react";
|
|
2
|
-
import { Button } from "@salt-ds/core";
|
|
3
|
-
import { DropdownBase } from "@heswell/salt-lab";
|
|
4
|
-
import { UserSolidIcon } from "@salt-ds/icons";
|
|
5
|
-
import { UserPanel } from "./UserPanel";
|
|
6
|
-
|
|
7
|
-
import "./UserProfile.css";
|
|
8
|
-
|
|
9
|
-
export const UserProfile = ({ layoutId, loginUrl, onNavigate, user }) => {
|
|
10
|
-
const [open, setOpen] = useState(false);
|
|
11
|
-
const openRef = useRef(false);
|
|
12
|
-
const buttonRef = useRef(null);
|
|
13
|
-
|
|
14
|
-
const toggle = useCallback(() => {
|
|
15
|
-
setOpen((isOpen) => {
|
|
16
|
-
return (openRef.current = !isOpen);
|
|
17
|
-
});
|
|
18
|
-
requestAnimationFrame(() => {
|
|
19
|
-
if (!openRef.current) {
|
|
20
|
-
requestAnimationFrame(() => {
|
|
21
|
-
buttonRef.current.focus();
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
const handleNavigate = (id) => {
|
|
28
|
-
setOpen(false);
|
|
29
|
-
onNavigate(id);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<div className="vuuUserProfile">
|
|
34
|
-
<DropdownBase placement="bottom-end" onCancel={toggle}>
|
|
35
|
-
<Button ref={buttonRef} variant="secondary">
|
|
36
|
-
<UserSolidIcon />
|
|
37
|
-
</Button>
|
|
38
|
-
<UserPanel
|
|
39
|
-
layoutId={layoutId}
|
|
40
|
-
loginUrl={loginUrl}
|
|
41
|
-
onNavigate={handleNavigate}
|
|
42
|
-
user={user}
|
|
43
|
-
/>
|
|
44
|
-
</DropdownBase>
|
|
45
|
-
</div>
|
|
46
|
-
);
|
|
47
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './UserProfile';
|