@celljs/shell 3.0.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.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/cell-locale.yml +13 -0
- package/cell.yml +18 -0
- package/lib/browser/annotation/index.d.ts +3 -0
- package/lib/browser/annotation/index.d.ts.map +1 -0
- package/lib/browser/annotation/index.js +19 -0
- package/lib/browser/annotation/index.js.map +1 -0
- package/lib/browser/annotation/left-area.d.ts +2 -0
- package/lib/browser/annotation/left-area.d.ts.map +1 -0
- package/lib/browser/annotation/left-area.js +12 -0
- package/lib/browser/annotation/left-area.js.map +1 -0
- package/lib/browser/annotation/top-area.d.ts +2 -0
- package/lib/browser/annotation/top-area.d.ts.map +1 -0
- package/lib/browser/annotation/top-area.js +12 -0
- package/lib/browser/annotation/top-area.js.map +1 -0
- package/lib/browser/apps/app-service.d.ts +11 -0
- package/lib/browser/apps/app-service.d.ts.map +1 -0
- package/lib/browser/apps/app-service.js +55 -0
- package/lib/browser/apps/app-service.js.map +1 -0
- package/lib/browser/apps/apps.d.ts +13 -0
- package/lib/browser/apps/apps.d.ts.map +1 -0
- package/lib/browser/apps/apps.js +44 -0
- package/lib/browser/apps/apps.js.map +1 -0
- package/lib/browser/apps/index.d.ts +3 -0
- package/lib/browser/apps/index.d.ts.map +1 -0
- package/lib/browser/apps/index.js +19 -0
- package/lib/browser/apps/index.js.map +1 -0
- package/lib/browser/area/area-protocol.d.ts +18 -0
- package/lib/browser/area/area-protocol.d.ts.map +1 -0
- package/lib/browser/area/area-protocol.js +22 -0
- package/lib/browser/area/area-protocol.js.map +1 -0
- package/lib/browser/area/index.d.ts +4 -0
- package/lib/browser/area/index.d.ts.map +1 -0
- package/lib/browser/area/index.js +20 -0
- package/lib/browser/area/index.js.map +1 -0
- package/lib/browser/area/left/index.d.ts +2 -0
- package/lib/browser/area/left/index.d.ts.map +1 -0
- package/lib/browser/area/left/index.js +18 -0
- package/lib/browser/area/left/index.js.map +1 -0
- package/lib/browser/area/left/left.d.ts +5 -0
- package/lib/browser/area/left/left.d.ts.map +1 -0
- package/lib/browser/area/left/left.js +31 -0
- package/lib/browser/area/left/left.js.map +1 -0
- package/lib/browser/area/top/index.d.ts +2 -0
- package/lib/browser/area/top/index.d.ts.map +1 -0
- package/lib/browser/area/top/index.js +18 -0
- package/lib/browser/area/top/index.js.map +1 -0
- package/lib/browser/area/top/top.d.ts +5 -0
- package/lib/browser/area/top/top.d.ts.map +1 -0
- package/lib/browser/area/top/top.js +31 -0
- package/lib/browser/area/top/top.js.map +1 -0
- package/lib/browser/index.d.ts +5 -0
- package/lib/browser/index.d.ts.map +1 -0
- package/lib/browser/index.js +21 -0
- package/lib/browser/index.js.map +1 -0
- package/lib/browser/layout/index.d.ts +2 -0
- package/lib/browser/layout/index.d.ts.map +1 -0
- package/lib/browser/layout/index.js +18 -0
- package/lib/browser/layout/index.js.map +1 -0
- package/lib/browser/layout/layout.d.ts +6 -0
- package/lib/browser/layout/layout.d.ts.map +1 -0
- package/lib/browser/layout/layout.js +65 -0
- package/lib/browser/layout/layout.js.map +1 -0
- package/lib/browser/module.d.ts +4 -0
- package/lib/browser/module.d.ts.map +1 -0
- package/lib/browser/module.js +6 -0
- package/lib/browser/module.js.map +1 -0
- package/lib/browser/tool/account.d.ts +5 -0
- package/lib/browser/tool/account.d.ts.map +1 -0
- package/lib/browser/tool/account.js +66 -0
- package/lib/browser/tool/account.js.map +1 -0
- package/lib/browser/tool/app-set.d.ts +5 -0
- package/lib/browser/tool/app-set.d.ts.map +1 -0
- package/lib/browser/tool/app-set.js +55 -0
- package/lib/browser/tool/app-set.js.map +1 -0
- package/lib/browser/tool/index.d.ts +5 -0
- package/lib/browser/tool/index.d.ts.map +1 -0
- package/lib/browser/tool/index.js +21 -0
- package/lib/browser/tool/index.js.map +1 -0
- package/lib/browser/tool/logo.d.ts +5 -0
- package/lib/browser/tool/logo.d.ts.map +1 -0
- package/lib/browser/tool/logo.js +38 -0
- package/lib/browser/tool/logo.js.map +1 -0
- package/lib/browser/tool/settings.d.ts +5 -0
- package/lib/browser/tool/settings.d.ts.map +1 -0
- package/lib/browser/tool/settings.js +66 -0
- package/lib/browser/tool/settings.js.map +1 -0
- package/lib/common/index.d.ts +2 -0
- package/lib/common/index.d.ts.map +1 -0
- package/lib/common/index.js +18 -0
- package/lib/common/index.js.map +1 -0
- package/lib/common/shell-protocol.d.ts +19 -0
- package/lib/common/shell-protocol.d.ts.map +1 -0
- package/lib/common/shell-protocol.js +5 -0
- package/lib/common/shell-protocol.js.map +1 -0
- package/lib/node/index.d.ts +1 -0
- package/lib/node/index.d.ts.map +1 -0
- package/lib/node/index.js +1 -0
- package/lib/node/index.js.map +1 -0
- package/lib/node/module.d.ts +3 -0
- package/lib/node/module.d.ts.map +1 -0
- package/lib/node/module.js +5 -0
- package/lib/node/module.js.map +1 -0
- package/lib/package.spec.d.ts +1 -0
- package/lib/package.spec.d.ts.map +1 -0
- package/lib/package.spec.js +4 -0
- package/lib/package.spec.js.map +1 -0
- package/package.json +50 -0
- package/src/browser/annotation/index.ts +2 -0
- package/src/browser/annotation/left-area.ts +9 -0
- package/src/browser/annotation/top-area.ts +9 -0
- package/src/browser/apps/app-service.ts +40 -0
- package/src/browser/apps/apps.tsx +67 -0
- package/src/browser/apps/index.ts +2 -0
- package/src/browser/area/area-protocol.ts +18 -0
- package/src/browser/area/index.ts +3 -0
- package/src/browser/area/left/index.ts +1 -0
- package/src/browser/area/left/left.tsx +26 -0
- package/src/browser/area/top/index.ts +1 -0
- package/src/browser/area/top/top.tsx +24 -0
- package/src/browser/index.ts +4 -0
- package/src/browser/layout/index.ts +1 -0
- package/src/browser/layout/layout.tsx +63 -0
- package/src/browser/module.ts +5 -0
- package/src/browser/tool/account.tsx +61 -0
- package/src/browser/tool/app-set.tsx +47 -0
- package/src/browser/tool/index.ts +4 -0
- package/src/browser/tool/logo.tsx +14 -0
- package/src/browser/tool/settings.tsx +56 -0
- package/src/common/index.ts +1 -0
- package/src/common/shell-protocol.ts +21 -0
- package/src/node/index.ts +0 -0
- package/src/node/module.ts +4 -0
- package/src/package.spec.ts +4 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactComponent } from '@celljs/react';
|
|
2
|
+
import { LEFT_AREA } from '../area/area-protocol';
|
|
3
|
+
|
|
4
|
+
export const LeftArea =
|
|
5
|
+
function (component?: any, rebind: boolean = true): (target: any) => any {
|
|
6
|
+
return (t: any) => {
|
|
7
|
+
ReactComponent(LEFT_AREA, component || t, rebind)(t);
|
|
8
|
+
};
|
|
9
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactComponent } from '@celljs/react';
|
|
2
|
+
import { TOP_AREA } from '../area/area-protocol';
|
|
3
|
+
|
|
4
|
+
export const TopArea =
|
|
5
|
+
function (component?: any, rebind: boolean = true): (target: any) => any {
|
|
6
|
+
return (t: any) => {
|
|
7
|
+
ReactComponent(TOP_AREA, component || t, rebind)(t);
|
|
8
|
+
};
|
|
9
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AppService, Category, AppInfo } from '../../common';
|
|
2
|
+
import { Component, Prioritizeable, Value } from '@celljs/core';
|
|
3
|
+
|
|
4
|
+
@Component(AppService)
|
|
5
|
+
export class AppServiceImpl implements AppService {
|
|
6
|
+
|
|
7
|
+
@Value('cell.shell.apps')
|
|
8
|
+
protected readonly apps: { [id: string]: AppInfo };
|
|
9
|
+
|
|
10
|
+
@Value('cell.shell.categories')
|
|
11
|
+
protected readonly categories: { [id: string]: Category };
|
|
12
|
+
|
|
13
|
+
async load(): Promise<Category[]> {
|
|
14
|
+
const categoryMap = new Map<string, Category>();
|
|
15
|
+
const parsedCategories = Object.keys(this.categories || {}).map(key => {
|
|
16
|
+
const category = { ...this.categories[key] };
|
|
17
|
+
category.id = key;
|
|
18
|
+
category.priority = 500;
|
|
19
|
+
category.apps = category.apps || [];
|
|
20
|
+
categoryMap.set(key, category);
|
|
21
|
+
return category;
|
|
22
|
+
});
|
|
23
|
+
const parsedApps = Object.keys(this.apps || {}).map(key => {
|
|
24
|
+
const app = { ...this.apps[key] };
|
|
25
|
+
app.id = key;
|
|
26
|
+
app.priority = 500;
|
|
27
|
+
return app;
|
|
28
|
+
});
|
|
29
|
+
const sortedCategories = Prioritizeable.prioritizeAllSync(parsedCategories).map(c => c.value);
|
|
30
|
+
const sortedApps = Prioritizeable.prioritizeAllSync(parsedApps).map(c => c.value);
|
|
31
|
+
for (const app of sortedApps) {
|
|
32
|
+
const category = categoryMap.get(app.categoryId);
|
|
33
|
+
if (category) {
|
|
34
|
+
category.apps.push(app);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return sortedCategories;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Grid, Box, Text, ResponsiveContext } from 'grommet';
|
|
3
|
+
import { ContainerUtil } from '@celljs/core';
|
|
4
|
+
import { AppService, Category, AppInfo } from '../../common';
|
|
5
|
+
import { Icon } from '@celljs/grommet';
|
|
6
|
+
import { useIntl } from 'react-intl';
|
|
7
|
+
const { useState, useEffect, useContext } = React;
|
|
8
|
+
|
|
9
|
+
export function Apps({ size }: { size?: string }) {
|
|
10
|
+
size = size || useContext(ResponsiveContext);
|
|
11
|
+
const [categories, setCategories] = useState<Category[]>([]);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const loadApps = async () => {
|
|
14
|
+
const appService = ContainerUtil.get<AppService>(AppService);
|
|
15
|
+
const data = await appService.load();
|
|
16
|
+
setCategories(data);
|
|
17
|
+
};
|
|
18
|
+
loadApps();
|
|
19
|
+
}, []);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Box direction="column" pad="small" gap="small" alignContent="start"
|
|
23
|
+
>
|
|
24
|
+
{categories.map(c => (
|
|
25
|
+
<AppCategory key={c.id} size={size!} category={c}></AppCategory>
|
|
26
|
+
))}
|
|
27
|
+
</Box>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function AppCategory({ category, size }: { category: Category, size: string }) {
|
|
32
|
+
const intl = useIntl();
|
|
33
|
+
const apps = category.apps || [];
|
|
34
|
+
return (
|
|
35
|
+
<Box>
|
|
36
|
+
<Text weight="bold" textAlign={ size === 'small' ? 'center' : 'start' } size={size} margin={{ bottom: size }}>{ intl.formatMessage({ id: category.name}) }</Text>
|
|
37
|
+
<Box border={{ side: 'top', color: 'light-2' }}></Box>
|
|
38
|
+
<Grid
|
|
39
|
+
rows={size === 'small' ? 'xsmall' : 'small'}
|
|
40
|
+
columns={size === 'small' ? 'xsmall' : 'small'}
|
|
41
|
+
>
|
|
42
|
+
{apps.map(app => (
|
|
43
|
+
<AppItem key={app.id} size={size} app={app}></AppItem>
|
|
44
|
+
))}
|
|
45
|
+
|
|
46
|
+
</Grid>
|
|
47
|
+
</Box>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function AppItem({ app, size }: { app: AppInfo, size: string }) {
|
|
52
|
+
const intl = useIntl();
|
|
53
|
+
const onClick = () => {
|
|
54
|
+
window.location.href = app.url;
|
|
55
|
+
};
|
|
56
|
+
return (
|
|
57
|
+
<Box
|
|
58
|
+
justify="center"
|
|
59
|
+
align="center"
|
|
60
|
+
hoverIndicator
|
|
61
|
+
onClick={onClick}
|
|
62
|
+
>
|
|
63
|
+
<Icon icon={app.icon} size={size === 'small' ? 'medium' : 'large'}/>
|
|
64
|
+
<Text size={size} margin={{ top: size }}>{intl.formatMessage({ id: app.name})}</Text>
|
|
65
|
+
</Box>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const TOP_AREA = Symbol('TOP_AREA');
|
|
2
|
+
export const LEFT_AREA = Symbol('LEFT_AREA');
|
|
3
|
+
|
|
4
|
+
export enum AreaType {
|
|
5
|
+
TopArea = 'Top',
|
|
6
|
+
SecondaryTopArea = 'SecondaryTop',
|
|
7
|
+
TertiaryTopArea = 'TertiaryTop',
|
|
8
|
+
LeftArea = 'Left',
|
|
9
|
+
TopLeftArea = 'TopLeft',
|
|
10
|
+
TopRightArea = 'TopRight',
|
|
11
|
+
LeftHeaderArea = 'LeftHeader',
|
|
12
|
+
LeftFooterArea = 'LeftFooter',
|
|
13
|
+
LeftBodyArea = 'LeftBody',
|
|
14
|
+
NavArea = 'Nav',
|
|
15
|
+
SettingsArea = 'Settings',
|
|
16
|
+
AccountArea = 'Account',
|
|
17
|
+
BottomArea = 'Bottom'
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './left';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Nav, Sidebar, BoxProps } from 'grommet';
|
|
3
|
+
import { ConfigUtil } from '@celljs/core';
|
|
4
|
+
import { AreaType } from '../area-protocol';
|
|
5
|
+
import { Slot } from '@celljs/react';
|
|
6
|
+
import { Widget } from '@celljs/widget';
|
|
7
|
+
|
|
8
|
+
export function LeftArea(props: BoxProps) {
|
|
9
|
+
props = { ...(ConfigUtil.get('cell.shell.leftArea') || {}), ...props };
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Sidebar animation="fadeIn" pad="medium" background="white" width="250px"
|
|
13
|
+
footer={<Slot area={AreaType.LeftFooterArea} />}
|
|
14
|
+
{...props}
|
|
15
|
+
>
|
|
16
|
+
<Slot area={AreaType.LeftHeaderArea} />
|
|
17
|
+
<Nav gap="none">
|
|
18
|
+
<Slot area={AreaType.NavArea} />
|
|
19
|
+
<Slot area={AreaType.LeftBodyArea} />
|
|
20
|
+
</Nav>
|
|
21
|
+
</Sidebar>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Widget({ area: AreaType.LeftArea, component: LeftArea })
|
|
26
|
+
export default class {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './top';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Box, Nav, BoxProps } from 'grommet';
|
|
3
|
+
import { ConfigUtil } from '@celljs/core';
|
|
4
|
+
import { AreaType } from '../area-protocol';
|
|
5
|
+
import { Slot } from '@celljs/react';
|
|
6
|
+
import { Widget } from '@celljs/widget';
|
|
7
|
+
|
|
8
|
+
export function TopArea(props: BoxProps) {
|
|
9
|
+
props = { ...ConfigUtil.get('cell.shell.topArea'), ...props };
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Nav direction="row" pad={{ vertical: 'small', horizontal: 'medium' }} elevation="xsmall" justify="between" {...props}>
|
|
13
|
+
<Box direction="row" gap="small">
|
|
14
|
+
<Slot area={AreaType.TopLeftArea} />
|
|
15
|
+
</Box>
|
|
16
|
+
<Box direction="row" gap="small">
|
|
17
|
+
<Slot area={AreaType.TopRightArea} />
|
|
18
|
+
</Box>
|
|
19
|
+
</Nav>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Widget({ area: AreaType.TopArea, component: TopArea })
|
|
24
|
+
export default class {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './layout';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DefaultLayout, Slot } from '@celljs/react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { AreaType } from '../area';
|
|
4
|
+
import styled from 'styled-components';
|
|
5
|
+
import { Box } from 'grommet';
|
|
6
|
+
|
|
7
|
+
const StyledWraper = styled.div`
|
|
8
|
+
left: 0;
|
|
9
|
+
position: absolute;
|
|
10
|
+
right: 0;
|
|
11
|
+
top: 0;
|
|
12
|
+
bottom: 0;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
z-index: 2;
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const StyledSidebar = styled.div`
|
|
18
|
+
left: 0;
|
|
19
|
+
position: absolute;
|
|
20
|
+
top: 76px;
|
|
21
|
+
bottom: 0;
|
|
22
|
+
z-index: 1;
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const StyledMain = styled.div`
|
|
26
|
+
left: 250px;
|
|
27
|
+
position: absolute;
|
|
28
|
+
right: 0;
|
|
29
|
+
top: 70px;
|
|
30
|
+
bottom: 0;
|
|
31
|
+
overflow: auto;
|
|
32
|
+
z-index: 0;
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
export function TopLeftLayout({ children }: React.PropsWithChildren<any>) {
|
|
36
|
+
return (
|
|
37
|
+
<StyledWraper>
|
|
38
|
+
<Slot area={AreaType.TopArea}/>
|
|
39
|
+
<StyledSidebar>
|
|
40
|
+
<Slot area={AreaType.LeftArea}/>
|
|
41
|
+
</StyledSidebar>
|
|
42
|
+
<StyledMain>
|
|
43
|
+
{children}
|
|
44
|
+
<Slot area={AreaType.BottomArea}/>
|
|
45
|
+
</StyledMain>
|
|
46
|
+
</StyledWraper>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function MultiTopLayout({ children }: React.PropsWithChildren<any>) {
|
|
51
|
+
return (
|
|
52
|
+
<Box>
|
|
53
|
+
<Slot area={AreaType.TopArea}/>
|
|
54
|
+
<Slot area={AreaType.SecondaryTopArea}/>
|
|
55
|
+
<Slot area={AreaType.TertiaryTopArea}/>
|
|
56
|
+
{children}
|
|
57
|
+
<Slot area={AreaType.BottomArea}/>
|
|
58
|
+
</Box>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@DefaultLayout(TopLeftLayout)
|
|
63
|
+
export default class {}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Avatar, AvatarProps, Drop, Box } from 'grommet';
|
|
3
|
+
import { ConfigUtil, ContainerUtil } from '@celljs/core';
|
|
4
|
+
import { Widget } from '@celljs/widget';
|
|
5
|
+
import { AreaType } from '../area';
|
|
6
|
+
import styled from 'styled-components';
|
|
7
|
+
import { Slot } from '@celljs/react';
|
|
8
|
+
import { UserManager } from '@celljs/security/lib/browser';
|
|
9
|
+
import { User } from '@celljs/security';
|
|
10
|
+
import { NavItem, Icon } from '@celljs/grommet';
|
|
11
|
+
|
|
12
|
+
const StyledAccount = styled.div`
|
|
13
|
+
width: 200px;
|
|
14
|
+
max-height: 450px;
|
|
15
|
+
padding-top: 12px;
|
|
16
|
+
overflow: auto;
|
|
17
|
+
right: 0;
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
export function Account(props: AvatarProps) {
|
|
21
|
+
// eslint-disable-next-line no-null/no-null
|
|
22
|
+
const targetRef = React.useRef(null);
|
|
23
|
+
const loginUserManager = ContainerUtil.get<UserManager>(UserManager);
|
|
24
|
+
const [show, setShow] = React.useState(false);
|
|
25
|
+
const [user, setUser] = React.useState<User | undefined>(loginUserManager.userInfoSubject.value);
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
const subscription = loginUserManager.userInfoSubject.subscribe(u => setUser(u));
|
|
28
|
+
return () => subscription.unsubscribe();
|
|
29
|
+
}, []);
|
|
30
|
+
const { icon, login, ...rest } = ConfigUtil.get('cell.shell.account');
|
|
31
|
+
props = { ...rest, ...props };
|
|
32
|
+
if (!user) {
|
|
33
|
+
const { label, ...loginRest } = login;
|
|
34
|
+
return (<NavItem label={label} size="medium" {...loginRest}/>);
|
|
35
|
+
}
|
|
36
|
+
return (
|
|
37
|
+
<Box ref={targetRef}>
|
|
38
|
+
<Avatar
|
|
39
|
+
hoverIndicator title={user.nickname} style={{ margin: '12px' }} size='small' onClick={() => setShow(true)} {...props} src={user.avatar || props.src}>
|
|
40
|
+
{<Icon icon={user.avatar || icon}/>}
|
|
41
|
+
</Avatar>
|
|
42
|
+
{targetRef.current && show && (
|
|
43
|
+
<Drop
|
|
44
|
+
target={targetRef.current!}
|
|
45
|
+
style={{ margin: '20px 0' }}
|
|
46
|
+
elevation="large"
|
|
47
|
+
align={{ top: 'bottom', right: 'right'}}
|
|
48
|
+
onEsc={() => setShow(false)}
|
|
49
|
+
onClickOutside={() => setShow(false)}
|
|
50
|
+
>
|
|
51
|
+
<StyledAccount>
|
|
52
|
+
<Slot area={AreaType.AccountArea}/>
|
|
53
|
+
</StyledAccount>
|
|
54
|
+
</Drop>
|
|
55
|
+
)}
|
|
56
|
+
</Box>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Widget({ area: AreaType.TopRightArea, component: Account, priority: 100 })
|
|
61
|
+
export default class {}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Button, ButtonProps, Drop } from 'grommet';
|
|
3
|
+
import { ConfigUtil } from '@celljs/core';
|
|
4
|
+
import { Icon } from '@celljs/grommet';
|
|
5
|
+
import { Widget } from '@celljs/widget';
|
|
6
|
+
import { AreaType } from '../area';
|
|
7
|
+
import { Apps } from '../apps';
|
|
8
|
+
import styled from 'styled-components';
|
|
9
|
+
|
|
10
|
+
const { Fragment } = React;
|
|
11
|
+
|
|
12
|
+
const StyledAppSet = styled.div`
|
|
13
|
+
width: 320px;
|
|
14
|
+
max-height: 450px;
|
|
15
|
+
padding-top: 12px;
|
|
16
|
+
overflow: auto;
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export function AppSet(props: ButtonProps) {
|
|
20
|
+
// eslint-disable-next-line no-null/no-null
|
|
21
|
+
const targetRef = React.useRef(null);
|
|
22
|
+
const [show, setShow] = React.useState(false);
|
|
23
|
+
const { icon, ...rest } = ConfigUtil.get('cell.shell.appSet');
|
|
24
|
+
props = { ...rest, ...props };
|
|
25
|
+
return (
|
|
26
|
+
<Fragment>
|
|
27
|
+
<Button ref={targetRef} hoverIndicator onClick={() => setShow(true)} {...props} icon={<Icon icon={icon}/>}/>
|
|
28
|
+
{targetRef.current && show && (
|
|
29
|
+
<Drop
|
|
30
|
+
target={targetRef.current!}
|
|
31
|
+
style={{ marginTop: '20px' }}
|
|
32
|
+
elevation="large"
|
|
33
|
+
align={{ top: 'bottom', right: 'right'}}
|
|
34
|
+
onEsc={() => setShow(false)}
|
|
35
|
+
onClickOutside={() => setShow(false)}
|
|
36
|
+
>
|
|
37
|
+
<StyledAppSet>
|
|
38
|
+
<Apps size="small"/>
|
|
39
|
+
</StyledAppSet>
|
|
40
|
+
</Drop>
|
|
41
|
+
)}
|
|
42
|
+
</Fragment>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Widget({ area: AreaType.TopRightArea, component: AppSet, priority: 200 })
|
|
47
|
+
export default class {}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ConfigUtil } from '@celljs/core';
|
|
3
|
+
import { Widget } from '@celljs/widget';
|
|
4
|
+
import { AreaType } from '../area';
|
|
5
|
+
import { NavItemProps, NavItem, Icon } from '@celljs/grommet';
|
|
6
|
+
|
|
7
|
+
export function Logo(props: NavItemProps) {
|
|
8
|
+
const { label, icon, ...rest } = ConfigUtil.get('cell.shell.logo');
|
|
9
|
+
props = { ...rest, ...props };
|
|
10
|
+
return (<NavItem size="medium" gap="xsmall" label={label} icon={<Icon icon={icon}/>} hoverIndicator={false} activatable={false} {...props}/>);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@Widget({ area: AreaType.TopLeftArea, component: Logo, priority: 1000 })
|
|
14
|
+
export default class {}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Button, ButtonProps, Drop, ThemeType, Box } from 'grommet';
|
|
3
|
+
import { ConfigUtil, ContainerUtil } from '@celljs/core';
|
|
4
|
+
import { Icon, ThemeBox, LocaleMenu } from '@celljs/grommet';
|
|
5
|
+
import { Widget, ThemeManager } from '@celljs/widget';
|
|
6
|
+
import { AreaType } from '../area';
|
|
7
|
+
import styled from 'styled-components';
|
|
8
|
+
import { Slot } from '@celljs/react';
|
|
9
|
+
|
|
10
|
+
const { Fragment } = React;
|
|
11
|
+
|
|
12
|
+
const StyledSettings = styled.div`
|
|
13
|
+
width: 300px;
|
|
14
|
+
max-height: 450px;
|
|
15
|
+
padding-top: 12px;
|
|
16
|
+
overflow: auto;
|
|
17
|
+
right: 0;
|
|
18
|
+
`;
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
export function Settings(props: ButtonProps) {
|
|
21
|
+
// eslint-disable-next-line no-null/no-null
|
|
22
|
+
const targetRef = React.useRef(null);
|
|
23
|
+
const [show, setShow] = React.useState(false);
|
|
24
|
+
const { icon, ...rest } = ConfigUtil.get<any>('cell.shell.settings');
|
|
25
|
+
props = { ...rest, ...props };
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
const themeManager = ContainerUtil.get<ThemeManager<ThemeType>>(ThemeManager);
|
|
28
|
+
const subscription = themeManager.currentSubject.subscribe(t => setShow(false));
|
|
29
|
+
return () => subscription.unsubscribe();
|
|
30
|
+
}, []);
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
return (<Fragment>
|
|
33
|
+
<Button ref={targetRef} hoverIndicator onClick={() => setShow(true)} {...props} icon={<Icon icon={icon}/>}/>
|
|
34
|
+
{targetRef.current && show && (
|
|
35
|
+
<Drop
|
|
36
|
+
target={targetRef.current!}
|
|
37
|
+
style={{ marginTop: '20px' }}
|
|
38
|
+
elevation="large"
|
|
39
|
+
align={{ top: 'bottom', right: 'right'}}
|
|
40
|
+
onEsc={() => setShow(false)}
|
|
41
|
+
onClickOutside={() => setShow(false)}
|
|
42
|
+
>
|
|
43
|
+
<StyledSettings>
|
|
44
|
+
<Box>
|
|
45
|
+
<Slot area={AreaType.SettingsArea}/>
|
|
46
|
+
</Box>
|
|
47
|
+
</StyledSettings>
|
|
48
|
+
</Drop>
|
|
49
|
+
)}
|
|
50
|
+
</Fragment>);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Widget({ area: AreaType.SettingsArea, component: LocaleMenu, priority: 200 })
|
|
54
|
+
@Widget({ area: AreaType.SettingsArea, component: ThemeBox, priority: 300 })
|
|
55
|
+
@Widget({ area: AreaType.TopRightArea, component: Settings, priority: 300 })
|
|
56
|
+
export default class {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './shell-protocol';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const AppService = Symbol('AppService');
|
|
2
|
+
|
|
3
|
+
export interface AppInfo {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
icon: string;
|
|
7
|
+
categoryId: string;
|
|
8
|
+
priority: number;
|
|
9
|
+
url: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Category {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
priority: number;
|
|
16
|
+
apps: AppInfo[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface AppService {
|
|
20
|
+
load(): Promise<Category[]>;
|
|
21
|
+
}
|
|
File without changes
|