@ossy/workspaces 1.16.6 → 1.17.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/package.json +3 -3
- package/src/AuthenticationGuard.jsx +7 -6
- package/src/CreateWorkspacePage.jsx +8 -6
- package/src/Definition.js +1 -17
- package/src/GeneralSettings.jsx +21 -67
- package/src/Invitations.jsx +8 -18
- package/src/Invite.jsx +12 -11
- package/src/SelectWorkspacePage.jsx +18 -25
- package/src/Users.jsx +7 -14
- package/src/en.translations.json +72 -0
- package/src/sv.translations.json +72 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/workspaces",
|
|
3
3
|
"description": "Workspaces feature package — create, select, and manage workspaces, users, and invitations",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.17.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"module": "./src/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@jest/globals": "^30.2.0",
|
|
28
|
-
"@ossy/platform": "^1.
|
|
28
|
+
"@ossy/platform": "^1.39.0",
|
|
29
29
|
"casual": "^1.6.2",
|
|
30
30
|
"jest": "^30.2.0"
|
|
31
31
|
},
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"/src",
|
|
38
38
|
"README.md"
|
|
39
39
|
],
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "d9d31182be64a448d575da432af2830d909ad4b9"
|
|
41
41
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { AuthenticationStatus, useAuthentication } from '@ossy/sdk-react'
|
|
3
|
-
import { Switch, View, Guide, Icon } from '@ossy/design-system'
|
|
3
|
+
import { Switch, View, Guide, Icon, useLocale } from '@ossy/design-system'
|
|
4
4
|
|
|
5
5
|
export const AuthenticationGuard = ({ children }) => {
|
|
6
|
+
const { t } = useLocale()
|
|
6
7
|
const { status } = useAuthentication()
|
|
7
8
|
|
|
8
9
|
return (
|
|
@@ -13,8 +14,8 @@ export const AuthenticationGuard = ({ children }) => {
|
|
|
13
14
|
<Guide
|
|
14
15
|
style={{ width: '100vw', maxWidth: '300px' }}
|
|
15
16
|
slot="content"
|
|
16
|
-
title=
|
|
17
|
-
text=
|
|
17
|
+
title={t('authentication.guard.notAuthenticated.title')}
|
|
18
|
+
text={t('authentication.guard.notAuthenticated.text')}
|
|
18
19
|
/>
|
|
19
20
|
</View>
|
|
20
21
|
</Switch.Case>
|
|
@@ -24,8 +25,8 @@ export const AuthenticationGuard = ({ children }) => {
|
|
|
24
25
|
<Guide
|
|
25
26
|
style={{ width: '100vw', maxWidth: '300px' }}
|
|
26
27
|
slot="content"
|
|
27
|
-
title=
|
|
28
|
-
text=
|
|
28
|
+
title={t('authentication.guard.error.title')}
|
|
29
|
+
text={t('authentication.guard.error.text')}
|
|
29
30
|
/>
|
|
30
31
|
</View>
|
|
31
32
|
</Switch.Case>
|
|
@@ -33,7 +34,7 @@ export const AuthenticationGuard = ({ children }) => {
|
|
|
33
34
|
<Switch.Case match={[AuthenticationStatus.Verifying, AuthenticationStatus.NoInitialized]}>
|
|
34
35
|
<View layout="off-center" style={{ height: '100%' }}>
|
|
35
36
|
<Icon
|
|
36
|
-
name="
|
|
37
|
+
name="spinner"
|
|
37
38
|
style={{ width: '64px', height: '64px' }}
|
|
38
39
|
className="rotate fill-50"
|
|
39
40
|
slot="content"
|
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
useInputValue,
|
|
6
6
|
Title,
|
|
7
7
|
Input,
|
|
8
|
-
View
|
|
8
|
+
View,
|
|
9
|
+
useLocale,
|
|
9
10
|
} from '@ossy/design-system'
|
|
10
11
|
import { useRouter } from '@ossy/router-react'
|
|
11
12
|
import { AuthenticationGuard } from './AuthenticationGuard.jsx'
|
|
@@ -13,6 +14,7 @@ import { patchUserWorkspaceId } from './patchUserWorkspaceId.js'
|
|
|
13
14
|
|
|
14
15
|
export const CreateWorkspacePage = () => {
|
|
15
16
|
const router = useRouter()
|
|
17
|
+
const { t } = useLocale()
|
|
16
18
|
const [error, setError] = useState()
|
|
17
19
|
const [workspaceName, setWorkspaceName] = useInputValue()
|
|
18
20
|
const { createWorkspace } = useWorkspaces()
|
|
@@ -34,14 +36,14 @@ export const CreateWorkspacePage = () => {
|
|
|
34
36
|
<AuthenticationGuard>
|
|
35
37
|
<View gap="m">
|
|
36
38
|
|
|
37
|
-
<title>
|
|
38
|
-
<Title variant="primary" className="stack-m">
|
|
39
|
+
<title>{t('workspaces.create.documentTitle')}</title>
|
|
40
|
+
<Title variant="primary" className="stack-m">{t('workspaces.create.title')}</Title>
|
|
39
41
|
|
|
40
42
|
<Input
|
|
41
43
|
id="workspaceName"
|
|
42
44
|
className={error ? 'stack-s' : 'stack-m'}
|
|
43
45
|
type="text"
|
|
44
|
-
placeholder=
|
|
46
|
+
placeholder={t('workspaces.create.namePlaceholder')}
|
|
45
47
|
required
|
|
46
48
|
onChange={setWorkspaceName}
|
|
47
49
|
style={{ width: '100%' }}
|
|
@@ -54,13 +56,13 @@ export const CreateWorkspacePage = () => {
|
|
|
54
56
|
<Button
|
|
55
57
|
variant="link"
|
|
56
58
|
id="cancel"
|
|
57
|
-
href={() => router.back()}>
|
|
59
|
+
href={() => router.back()}>{t('workspaces.create.cancel')}
|
|
58
60
|
</Button>
|
|
59
61
|
|
|
60
62
|
<Button
|
|
61
63
|
id="createWorkspace"
|
|
62
64
|
variant="cta"
|
|
63
|
-
onClick={() => onCreateWorkspace(workspaceName)}>
|
|
65
|
+
onClick={() => onCreateWorkspace(workspaceName)}>{t('workspaces.create.submit')}
|
|
64
66
|
</Button>
|
|
65
67
|
|
|
66
68
|
</View>
|
package/src/Definition.js
CHANGED
|
@@ -2,22 +2,6 @@ export const Definition = {
|
|
|
2
2
|
id: 'workspaces',
|
|
3
3
|
title: 'Workspaces',
|
|
4
4
|
description: 'Workspace lifecycle, members, invitations, and services.',
|
|
5
|
-
|
|
6
|
-
id: 'workspaces',
|
|
7
|
-
enabled: true
|
|
8
|
-
},
|
|
5
|
+
icon: 'users',
|
|
9
6
|
statuses: ['beta'],
|
|
10
|
-
actions: [
|
|
11
|
-
'workspaces.create',
|
|
12
|
-
'workspaces.invite-user',
|
|
13
|
-
'workspaces.enable-service',
|
|
14
|
-
'workspaces.disable-service'
|
|
15
|
-
],
|
|
16
|
-
views: [
|
|
17
|
-
'workspaces.get-all',
|
|
18
|
-
'workspaces.get',
|
|
19
|
-
'workspaces.get-current',
|
|
20
|
-
'workspaces.get-users'
|
|
21
|
-
],
|
|
22
|
-
tasks: []
|
|
23
7
|
}
|
package/src/GeneralSettings.jsx
CHANGED
|
@@ -1,87 +1,41 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import { useWorkspace, useUser, AsyncStatus } from '@ossy/sdk-react'
|
|
3
|
-
import { Switch, Title, Button, View, Text } from '@ossy/design-system'
|
|
3
|
+
import { Switch, Title, Button, View, Text, useLocale } from '@ossy/design-system'
|
|
4
4
|
|
|
5
|
-
const formatDate = (timestamp) =>
|
|
6
|
-
|
|
7
|
-
const date = new Date(timestamp)
|
|
8
|
-
return date.toLocaleDateString()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const FlowStage = {
|
|
12
|
-
View: 'View',
|
|
13
|
-
Edit: 'Edit'
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const availableServices = [
|
|
17
|
-
'@ossy/jobs/visual-content-descriptors',
|
|
18
|
-
'@ossy/jobs/resize-common-web',
|
|
19
|
-
'@ossy/resumes',
|
|
20
|
-
'@ossy/consultancy',
|
|
21
|
-
'@ossy/apps',
|
|
22
|
-
'@ossy/domains',
|
|
23
|
-
]
|
|
5
|
+
const formatDate = (timestamp) => timestamp ? new Date(timestamp).toLocaleDateString() : ''
|
|
6
|
+
const FlowStage = { View: 'View', Edit: 'Edit' }
|
|
24
7
|
|
|
25
8
|
export const GeneralSettings = () => {
|
|
9
|
+
const { t } = useLocale()
|
|
26
10
|
const { workspace } = useWorkspace()
|
|
27
11
|
const { status: userStatus, user } = useUser()
|
|
28
12
|
const [flowStage, setFlowStage] = useState(FlowStage.View)
|
|
29
|
-
|
|
30
13
|
const services = workspace?.services || {}
|
|
31
14
|
|
|
32
|
-
const isWorkspaceCreator =
|
|
33
|
-
userStatus === AsyncStatus.Success &&
|
|
34
|
-
Boolean(workspace?.createdBy) &&
|
|
35
|
-
Boolean(user?.id) &&
|
|
36
|
-
workspace.createdBy === user.id
|
|
37
|
-
|
|
38
15
|
return (
|
|
39
16
|
<View gap="l" inset="m">
|
|
40
17
|
<View layout="row" gap="s" justifyContent="space-between">
|
|
41
|
-
<Title>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Edit
|
|
48
|
-
</Button>
|
|
49
|
-
</Switch.Case>
|
|
50
|
-
</Switch>
|
|
51
|
-
</View>
|
|
18
|
+
<Title>{t('workspace.settings.detailsTitle')}</Title>
|
|
19
|
+
<Switch on={flowStage}>
|
|
20
|
+
<Switch.Case match={[FlowStage.View]}>
|
|
21
|
+
<Button prefix={{ size: 's', name: 'pen' }} variant="cta" disabled>{t('workspace.settings.edit')}</Button>
|
|
22
|
+
</Switch.Case>
|
|
23
|
+
</Switch>
|
|
52
24
|
</View>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<Text style={{ fontWeight: 'bold' }}>Id:</Text>
|
|
57
|
-
<Text>{workspace.id}</Text>
|
|
58
|
-
</View>
|
|
59
|
-
<View layout="row" gap="s">
|
|
60
|
-
<Text style={{ fontWeight: 'bold' }}>Name:</Text>
|
|
61
|
-
<Text>{workspace.name}</Text>
|
|
62
|
-
</View>
|
|
63
|
-
<View layout="row" gap="s">
|
|
64
|
-
<Text style={{ fontWeight: 'bold' }}>Created:</Text>
|
|
65
|
-
<Text>{formatDate(workspace?.created)}</Text>
|
|
66
|
-
</View>
|
|
67
|
-
</View>
|
|
68
|
-
|
|
69
|
-
{isWorkspaceCreator && (
|
|
25
|
+
{userStatus === AsyncStatus.Loading ? (
|
|
26
|
+
<Text>{t('workspace.settings.loading')}</Text>
|
|
27
|
+
) : (
|
|
70
28
|
<View gap="s">
|
|
71
|
-
<
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
</Text>
|
|
80
|
-
</View>
|
|
81
|
-
))}
|
|
29
|
+
<View layout="row" gap="s"><Text style={{ fontWeight: 'bold' }}>{t('workspace.settings.name')}</Text><Text>{workspace?.name}</Text></View>
|
|
30
|
+
<View layout="row" gap="s"><Text style={{ fontWeight: 'bold' }}>{t('workspace.settings.created')}</Text><Text>{formatDate(workspace?.created)}</Text></View>
|
|
31
|
+
<Title variant="tertiary">{t('workspace.settings.services')}</Title>
|
|
32
|
+
<View gap="xs">
|
|
33
|
+
{Object.entries(services).map(([key, enabled]) => (
|
|
34
|
+
<Text key={key}>{key}: {enabled ? 'on' : 'off'}</Text>
|
|
35
|
+
))}
|
|
36
|
+
</View>
|
|
82
37
|
</View>
|
|
83
38
|
)}
|
|
84
|
-
|
|
85
39
|
</View>
|
|
86
40
|
)
|
|
87
41
|
}
|
package/src/Invitations.jsx
CHANGED
|
@@ -1,44 +1,34 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { useWorkspace } from '@ossy/sdk-react'
|
|
3
|
-
import { Title, Text, Button, View,
|
|
3
|
+
import { Title, Text, Button, View, Icon, useLocale } from '@ossy/design-system'
|
|
4
4
|
import { useRouter } from '@ossy/router-react'
|
|
5
5
|
|
|
6
6
|
export const Invitations = () => {
|
|
7
|
+
const { t } = useLocale()
|
|
7
8
|
const router = useRouter()
|
|
8
9
|
const { workspace } = useWorkspace()
|
|
9
10
|
const invitations = workspace?.invitations || []
|
|
10
11
|
|
|
11
12
|
return (
|
|
12
13
|
<View gap="m">
|
|
13
|
-
|
|
14
14
|
<View inset="s" gap="s">
|
|
15
|
-
|
|
16
15
|
<View layout="row" justifyContent="space-between" alignItems="center">
|
|
17
|
-
<Title>
|
|
16
|
+
<Title>{t('workspace.invitations.title')}</Title>
|
|
18
17
|
<Button variant="cta" href={router.getHref('@workspace/invitations/add')} prefix="user-add">
|
|
19
|
-
|
|
18
|
+
{t('workspace.invitations.invite')}
|
|
20
19
|
</Button>
|
|
21
20
|
</View>
|
|
22
|
-
|
|
23
|
-
<Text style={{ maxWidth: '400px' }}>
|
|
24
|
-
Invite users to your workspace to collaborate.
|
|
25
|
-
</Text>
|
|
26
|
-
|
|
21
|
+
<Text style={{ maxWidth: '400px' }}>{t('workspace.invitations.description')}</Text>
|
|
27
22
|
</View>
|
|
28
|
-
|
|
29
23
|
<View gap="xs">
|
|
30
24
|
{invitations.map(invite => (
|
|
31
25
|
<View layout="row" roundness="s" alignItems="center" inset="m" gap="m" selectable key={invite.email}>
|
|
32
|
-
<
|
|
33
|
-
<View>
|
|
34
|
-
<Text variant="small" as="span">{invite.email}</Text>
|
|
35
|
-
</View>
|
|
26
|
+
<Icon name="mail" />
|
|
27
|
+
<View><Text variant="small" as="span">{invite.email}</Text></View>
|
|
36
28
|
</View>
|
|
37
29
|
))}
|
|
38
30
|
</View>
|
|
39
|
-
|
|
40
|
-
{invitations.length === 0 && <Text>No invitations</Text>}
|
|
41
|
-
|
|
31
|
+
{invitations.length === 0 && <Text>{t('workspace.invitations.empty')}</Text>}
|
|
42
32
|
</View>
|
|
43
33
|
)
|
|
44
34
|
}
|
package/src/Invite.jsx
CHANGED
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
Switch,
|
|
10
10
|
Guide,
|
|
11
11
|
Text,
|
|
12
|
-
View
|
|
12
|
+
View,
|
|
13
|
+
useLocale,
|
|
13
14
|
} from '@ossy/design-system'
|
|
14
15
|
|
|
15
16
|
const FlowStage = {
|
|
@@ -19,6 +20,7 @@ const FlowStage = {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export const Invite = () => {
|
|
23
|
+
const { t } = useLocale()
|
|
22
24
|
const router = useRouter()
|
|
23
25
|
const { inviteUser } = useWorkspace()
|
|
24
26
|
const [flowStage, setFlowStage] = useState(FlowStage.EnterEmail)
|
|
@@ -35,13 +37,13 @@ export const Invite = () => {
|
|
|
35
37
|
return (
|
|
36
38
|
<Switch on={flowStage}>
|
|
37
39
|
|
|
38
|
-
<title>
|
|
40
|
+
<title>{t('workspace.invitations.add.documentTitle')}</title>
|
|
39
41
|
|
|
40
42
|
<Switch.Case match={[FlowStage.EnterEmail]}>
|
|
41
43
|
<View gap="m">
|
|
42
|
-
<Title variant="primary">
|
|
44
|
+
<Title variant="primary">{t('workspace.invite.title')}</Title>
|
|
43
45
|
<Text>
|
|
44
|
-
|
|
46
|
+
{t('workspace.invite.description')}
|
|
45
47
|
</Text>
|
|
46
48
|
<form
|
|
47
49
|
ref={formRef}
|
|
@@ -54,7 +56,7 @@ export const Invite = () => {
|
|
|
54
56
|
id="registerField"
|
|
55
57
|
className="stack-m"
|
|
56
58
|
type="email"
|
|
57
|
-
placeholder=
|
|
59
|
+
placeholder={t('workspace.invite.emailPlaceholder')}
|
|
58
60
|
required
|
|
59
61
|
value={email}
|
|
60
62
|
onChange={e => setEmail(e.target.value)}
|
|
@@ -65,14 +67,14 @@ export const Invite = () => {
|
|
|
65
67
|
<Button
|
|
66
68
|
variant="link"
|
|
67
69
|
id="cancelButton"
|
|
68
|
-
href={() => router.back()}>
|
|
70
|
+
href={() => router.back()}>{t('design-system.cancel')}
|
|
69
71
|
</Button>
|
|
70
72
|
|
|
71
73
|
<Button
|
|
72
74
|
variant="cta"
|
|
73
75
|
id="registerButton"
|
|
74
76
|
type="submit"
|
|
75
|
-
onClick={sendInvite}>
|
|
77
|
+
onClick={sendInvite}>{t('workspace.invite.submit')}
|
|
76
78
|
</Button>
|
|
77
79
|
</View>
|
|
78
80
|
</View>
|
|
@@ -82,12 +84,11 @@ export const Invite = () => {
|
|
|
82
84
|
|
|
83
85
|
<Switch.Case match={[FlowStage.Success]}>
|
|
84
86
|
<Guide
|
|
85
|
-
title=
|
|
87
|
+
title={t('workspace.invite.successTitle')}
|
|
86
88
|
titleVariant="primary"
|
|
87
89
|
>
|
|
88
90
|
<Text>
|
|
89
|
-
|
|
90
|
-
When they have accepted they will show up in the list of users.
|
|
91
|
+
{t('workspace.invite.successBody')}
|
|
91
92
|
<br/>
|
|
92
93
|
✌️
|
|
93
94
|
</Text>
|
|
@@ -96,7 +97,7 @@ export const Invite = () => {
|
|
|
96
97
|
|
|
97
98
|
<Switch.Case match={[FlowStage.Error]}>
|
|
98
99
|
<Text>
|
|
99
|
-
|
|
100
|
+
{t('workspace.invite.error')}
|
|
100
101
|
</Text>
|
|
101
102
|
</Switch.Case>
|
|
102
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { useWorkspaces, AsyncStatus } from '@ossy/sdk-react'
|
|
3
|
-
import { Title, Text, Switch, Button, View, Guide,
|
|
3
|
+
import { Title, Text, Switch, Button, View, Guide, Icon, useLocale } from '@ossy/design-system'
|
|
4
4
|
import { useRouter } from '@ossy/router-react'
|
|
5
5
|
import { AuthenticationGuard } from './AuthenticationGuard.jsx'
|
|
6
6
|
import { patchUserWorkspaceId } from './patchUserWorkspaceId.js'
|
|
@@ -14,6 +14,7 @@ const PageFlow = {
|
|
|
14
14
|
|
|
15
15
|
export const SelectWorkspacePage = () => {
|
|
16
16
|
const router = useRouter()
|
|
17
|
+
const { t } = useLocale()
|
|
17
18
|
const { status: asyncStatus, workspaces } = useWorkspaces()
|
|
18
19
|
|
|
19
20
|
const pageFlow = (asyncStatus === AsyncStatus.Success && workspaces.length === 0)
|
|
@@ -30,7 +31,7 @@ export const SelectWorkspacePage = () => {
|
|
|
30
31
|
return (
|
|
31
32
|
<AuthenticationGuard>
|
|
32
33
|
|
|
33
|
-
<title>
|
|
34
|
+
<title>{t('workspaces.select.documentTitle')}</title>
|
|
34
35
|
|
|
35
36
|
<Switch on={pageFlow}>
|
|
36
37
|
<Switch.Case match={[PageFlow.Success]}>
|
|
@@ -41,14 +42,14 @@ export const SelectWorkspacePage = () => {
|
|
|
41
42
|
marginBottom: 'var(--space-m)',
|
|
42
43
|
}}>
|
|
43
44
|
<Title variant="primary">
|
|
44
|
-
|
|
45
|
+
{t('workspaces.select.title')}
|
|
45
46
|
</Title>
|
|
46
47
|
<Button
|
|
47
48
|
prefix="math-plus"
|
|
48
49
|
variant="cta"
|
|
49
50
|
href={router.getHref('@profile/workspaces/create')}
|
|
50
51
|
className="mobile:d-none">
|
|
51
|
-
|
|
52
|
+
{t('workspaces.select.newWorkspace')}
|
|
52
53
|
</Button>
|
|
53
54
|
</div>
|
|
54
55
|
</Switch.Case>
|
|
@@ -61,41 +62,37 @@ export const SelectWorkspacePage = () => {
|
|
|
61
62
|
<Guide
|
|
62
63
|
slot="content"
|
|
63
64
|
style={{ width: '100vw', maxWidth: '500px' }}
|
|
64
|
-
title=
|
|
65
|
-
text={
|
|
66
|
-
Something went wrong when loading your workspaces.
|
|
67
|
-
Maybe your session have expired, or we messed up somehow.
|
|
68
|
-
Try starting over from our home page.
|
|
69
|
-
`}
|
|
65
|
+
title={t('workspaces.select.errorTitle')}
|
|
66
|
+
text={t('workspaces.select.errorText')}
|
|
70
67
|
actions={[{
|
|
71
68
|
variant: 'cta',
|
|
72
69
|
href: '/',
|
|
73
|
-
label: '
|
|
70
|
+
label: t('workspaces.select.errorAction')
|
|
74
71
|
}]}
|
|
75
72
|
/>
|
|
76
73
|
</View>
|
|
77
74
|
</Switch.Case>
|
|
78
75
|
|
|
79
76
|
<Switch.Case match={[PageFlow.Loading]}>
|
|
80
|
-
<
|
|
77
|
+
<Icon
|
|
81
78
|
slot="content"
|
|
82
79
|
name="spinner"
|
|
83
80
|
style={{ width: '64px', height: '64px' }}
|
|
84
81
|
className="rotate"
|
|
85
82
|
/>
|
|
86
|
-
<Text>
|
|
83
|
+
<Text>{t('workspaces.select.loading')}</Text>
|
|
87
84
|
</Switch.Case>
|
|
88
85
|
|
|
89
86
|
<Switch.Case match={[PageFlow.Success]}>
|
|
90
87
|
<View gap="m">
|
|
91
88
|
|
|
92
89
|
<Text style={{ maxWidth: '400px' }}>
|
|
93
|
-
|
|
90
|
+
{t('workspaces.select.description')}
|
|
94
91
|
</Text>
|
|
95
92
|
|
|
96
|
-
<
|
|
93
|
+
<View stack gap="xs" style={{ overflowY: 'auto' }}>
|
|
97
94
|
{workspaces.map(workspace => (
|
|
98
|
-
<
|
|
95
|
+
<View.Item
|
|
99
96
|
key={workspace.id}
|
|
100
97
|
layout="row"
|
|
101
98
|
style={{ alignItems: 'center' }}
|
|
@@ -111,9 +108,9 @@ export const SelectWorkspacePage = () => {
|
|
|
111
108
|
</View>
|
|
112
109
|
<div style={{ flexGrow: '1' }} />
|
|
113
110
|
<Button prefix="more-vertical-alt" variant="command" style={{ cursor: 'not-allowed' }} />
|
|
114
|
-
</
|
|
111
|
+
</View.Item>
|
|
115
112
|
))}
|
|
116
|
-
</
|
|
113
|
+
</View>
|
|
117
114
|
</View>
|
|
118
115
|
</Switch.Case>
|
|
119
116
|
|
|
@@ -122,15 +119,11 @@ export const SelectWorkspacePage = () => {
|
|
|
122
119
|
<Guide
|
|
123
120
|
slot="content"
|
|
124
121
|
style={{ padding: 'var(--space-xl) var(--space-m)', width: '100vw', maxWidth: '500px' }}
|
|
125
|
-
title=
|
|
126
|
-
text={
|
|
127
|
-
To get started we need to create a workspace.
|
|
128
|
-
A workspace is an encapsulation of resources, resource templates,
|
|
129
|
-
billing information, and what users have access to these things.
|
|
130
|
-
`}
|
|
122
|
+
title={`🎉 ${t('workspaces.select.emptyTitle')} 🎉`}
|
|
123
|
+
text={t('workspaces.select.emptyText')}
|
|
131
124
|
actions={[{
|
|
132
125
|
variant: 'cta',
|
|
133
|
-
label: '
|
|
126
|
+
label: t('workspaces.select.emptyAction'),
|
|
134
127
|
href: router.getHref('@profile/workspaces/create')
|
|
135
128
|
}]}
|
|
136
129
|
/>
|
package/src/Users.jsx
CHANGED
|
@@ -1,36 +1,30 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { useUsers, AsyncStatus } from '@ossy/sdk-react'
|
|
3
|
-
import { Text, View,
|
|
3
|
+
import { Text, View, Icon, Title, Button, useLocale } from '@ossy/design-system'
|
|
4
4
|
import { useRouter } from '@ossy/router-react'
|
|
5
5
|
|
|
6
6
|
export const Users = () => {
|
|
7
|
+
const { t } = useLocale()
|
|
7
8
|
const router = useRouter()
|
|
8
9
|
const { users = [], status } = useUsers()
|
|
9
10
|
|
|
10
|
-
if (status === AsyncStatus.Loading) return <>
|
|
11
|
+
if (status === AsyncStatus.Loading) return <>{t('workspace.users.loading')}</>
|
|
11
12
|
|
|
12
13
|
return (
|
|
13
14
|
<View gap="m">
|
|
14
|
-
|
|
15
15
|
<View inset="s" gap="s">
|
|
16
|
-
|
|
17
16
|
<View layout="row" justifyContent="space-between" alignItems="center">
|
|
18
|
-
<Title>
|
|
17
|
+
<Title>{t('workspace.users.title')}</Title>
|
|
19
18
|
<Button variant="cta" href={router.getHref('@workspace/invitations/add')} prefix="user-add">
|
|
20
|
-
|
|
19
|
+
{t('workspace.users.invite')}
|
|
21
20
|
</Button>
|
|
22
21
|
</View>
|
|
23
|
-
|
|
24
|
-
<Text style={{ maxWidth: '400px' }}>
|
|
25
|
-
Manage users in your workspace.
|
|
26
|
-
</Text>
|
|
27
|
-
|
|
22
|
+
<Text style={{ maxWidth: '400px' }}>{t('workspace.users.description')}</Text>
|
|
28
23
|
</View>
|
|
29
|
-
|
|
30
24
|
<View gap="xs">
|
|
31
25
|
{users.map(user => (
|
|
32
26
|
<View layout="row" roundness="s" alignItems="center" inset="m" gap="m" selectable key={user.id}>
|
|
33
|
-
<
|
|
27
|
+
<Icon name={user.type === 'Bot' ? 'bot' : 'user'} />
|
|
34
28
|
<View>
|
|
35
29
|
<View layout="row" gap="s">
|
|
36
30
|
<Text as="span" style={{ fontWeight: 'bold' }}>{user.firstName}</Text>
|
|
@@ -41,7 +35,6 @@ export const Users = () => {
|
|
|
41
35
|
</View>
|
|
42
36
|
))}
|
|
43
37
|
</View>
|
|
44
|
-
|
|
45
38
|
</View>
|
|
46
39
|
)
|
|
47
40
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workspaces.create.documentTitle": "Create workspace",
|
|
3
|
+
"workspaces.create.title": "Create a new workspace",
|
|
4
|
+
"workspaces.create.namePlaceholder": "Workspace name",
|
|
5
|
+
"workspaces.create.cancel": "Cancel",
|
|
6
|
+
"workspaces.create.submit": "Create",
|
|
7
|
+
"workspaces.select.documentTitle": "Select workspace",
|
|
8
|
+
"workspaces.select.title": "My workspaces",
|
|
9
|
+
"workspaces.select.newWorkspace": "New workspace",
|
|
10
|
+
"workspaces.select.loading": "Loading...",
|
|
11
|
+
"workspaces.select.description": "Workspaces are separate environments where you can manage resources, templates, services and billing.",
|
|
12
|
+
"workspaces.select.errorTitle": "We could not load your workspaces",
|
|
13
|
+
"workspaces.select.errorText": "Something went wrong when loading your workspaces. Maybe your session has expired, or we messed up somehow. Try starting over from our home page.",
|
|
14
|
+
"workspaces.select.errorAction": "Go to our home page",
|
|
15
|
+
"workspaces.select.emptyTitle": "Let's get the party started",
|
|
16
|
+
"workspaces.select.emptyText": "To get started we need to create a workspace. A workspace is an encapsulation of resources, resource templates, billing information, and what users have access to these things.",
|
|
17
|
+
"workspaces.select.emptyAction": "Create a workspace",
|
|
18
|
+
"workspaces/create.label": "Create workspace",
|
|
19
|
+
"workspaces/create.description": "Create a new workspace for the authenticated user",
|
|
20
|
+
"workspaces/accept-invitation.label": "Accept invitation",
|
|
21
|
+
"workspaces/accept-invitation.description": "Accept a workspace invitation",
|
|
22
|
+
"workspaces/create-api-token.label": "Create workspace API token",
|
|
23
|
+
"workspaces/create-api-token.description": "Create an API token scoped to the workspace",
|
|
24
|
+
"workspaces/disable-service.label": "Disable service",
|
|
25
|
+
"workspaces/disable-service.description": "Disable a service for the workspace",
|
|
26
|
+
"workspaces/enable-service.label": "Enable service",
|
|
27
|
+
"workspaces/enable-service.description": "Enable a service for the workspace",
|
|
28
|
+
"workspaces/get-api-tokens.label": "Get workspace API tokens",
|
|
29
|
+
"workspaces/get-api-tokens.description": "List API tokens for the workspace",
|
|
30
|
+
"workspaces/get-invitations.label": "Get invitations",
|
|
31
|
+
"workspaces/get-invitations.description": "List pending workspace invitations",
|
|
32
|
+
"workspaces/get-resource-templates.label": "Get resource templates",
|
|
33
|
+
"workspaces/get-resource-templates.description": "List resource templates available to the workspace",
|
|
34
|
+
"workspaces/get-users.label": "Get workspace users",
|
|
35
|
+
"workspaces/get-users.description": "List members of the workspace",
|
|
36
|
+
"workspaces/get.label": "Get workspace",
|
|
37
|
+
"workspaces/get.description": "Load a workspace by id",
|
|
38
|
+
"workspaces/import-resource-templates.label": "Import resource templates",
|
|
39
|
+
"workspaces/import-resource-templates.description": "Import resource templates into the workspace",
|
|
40
|
+
"workspaces/invite-user.label": "Invite user",
|
|
41
|
+
"workspaces/invite-user.description": "Send a workspace invitation to a user",
|
|
42
|
+
"workspaces/remove-member.label": "Remove member",
|
|
43
|
+
"workspaces/remove-member.description": "Remove a user from the workspace",
|
|
44
|
+
"workspaces/list.label": "List workspaces",
|
|
45
|
+
"workspaces/list.description": "List workspaces for the authenticated user",
|
|
46
|
+
"workspace.settings.documentTitle": "Workspace settings",
|
|
47
|
+
"workspace.settings.title": "Workspace settings",
|
|
48
|
+
"workspace.users.documentTitle": "Users",
|
|
49
|
+
"workspace.users.title": "Users",
|
|
50
|
+
"workspace.users.description": "Manage users in your workspace.",
|
|
51
|
+
"workspace.users.invite": "Invite user",
|
|
52
|
+
"workspace.users.loading": "Loading",
|
|
53
|
+
"workspace.invitations.documentTitle": "Invitations",
|
|
54
|
+
"workspace.invitations.add.documentTitle": "Invite user",
|
|
55
|
+
"workspace.invitations.title": "Invitations",
|
|
56
|
+
"workspace.settings.detailsTitle": "Workspace details",
|
|
57
|
+
"workspace.settings.edit": "Edit",
|
|
58
|
+
"workspace.settings.name": "Name",
|
|
59
|
+
"workspace.settings.created": "Created",
|
|
60
|
+
"workspace.settings.services": "Services",
|
|
61
|
+
"workspace.settings.loading": "Loading...",
|
|
62
|
+
"workspace.invitations.description": "Invite users to your workspace to collaborate.",
|
|
63
|
+
"workspace.invitations.invite": "Invite user",
|
|
64
|
+
"workspace.invitations.empty": "No invitations",
|
|
65
|
+
"workspace.invite.title": "Invite user",
|
|
66
|
+
"workspace.invite.description": "Invite a user to manage and contribute content to this workspace",
|
|
67
|
+
"workspace.invite.emailPlaceholder": "Email address",
|
|
68
|
+
"workspace.invite.submit": "Send invite",
|
|
69
|
+
"workspace.invite.successTitle": "Success",
|
|
70
|
+
"workspace.invite.successBody": "We sent them an invitation over email. When they have accepted they will show up in the list of users.",
|
|
71
|
+
"workspace.invite.error": "Something went wrong, try again in a couple of minutes"
|
|
72
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workspaces.create.documentTitle": "Skapa workspace",
|
|
3
|
+
"workspaces.create.title": "Skapa ett nytt workspace",
|
|
4
|
+
"workspaces.create.namePlaceholder": "Workspace-namn",
|
|
5
|
+
"workspaces.create.cancel": "Avbryt",
|
|
6
|
+
"workspaces.create.submit": "Skapa",
|
|
7
|
+
"workspaces.select.documentTitle": "Välj workspace",
|
|
8
|
+
"workspaces.select.title": "Mina workspaces",
|
|
9
|
+
"workspaces.select.newWorkspace": "Nytt workspace",
|
|
10
|
+
"workspaces.select.loading": "Laddar...",
|
|
11
|
+
"workspaces.select.description": "Workspaces är separata miljöer där du kan hantera resurser, mallar, tjänster och fakturering.",
|
|
12
|
+
"workspaces.select.errorTitle": "Vi kunde inte ladda dina workspaces",
|
|
13
|
+
"workspaces.select.errorText": "Något gick fel när dina workspaces skulle laddas. Kanske har din session gått ut, eller så har vi klantat till det. Prova att börja om från startsidan.",
|
|
14
|
+
"workspaces.select.errorAction": "Gå till startsidan",
|
|
15
|
+
"workspaces.select.emptyTitle": "Nu sätter vi igång",
|
|
16
|
+
"workspaces.select.emptyText": "För att komma igång behöver vi skapa ett workspace. Ett workspace kapslar in resurser, resursmallar, faktureringsinformation och vilka användare som har tillgång.",
|
|
17
|
+
"workspaces.select.emptyAction": "Skapa ett workspace",
|
|
18
|
+
"workspaces/create.label": "Skapa workspace",
|
|
19
|
+
"workspaces/create.description": "Skapa ett nytt workspace för den inloggade användaren",
|
|
20
|
+
"workspaces/accept-invitation.label": "Acceptera inbjudan",
|
|
21
|
+
"workspaces/accept-invitation.description": "Acceptera en workspace-inbjudan",
|
|
22
|
+
"workspaces/create-api-token.label": "Skapa workspace API-nyckel",
|
|
23
|
+
"workspaces/create-api-token.description": "Skapa en API-nyckel kopplad till workspace",
|
|
24
|
+
"workspaces/disable-service.label": "Inaktivera tjänst",
|
|
25
|
+
"workspaces/disable-service.description": "Inaktivera en tjänst för workspace",
|
|
26
|
+
"workspaces/enable-service.label": "Aktivera tjänst",
|
|
27
|
+
"workspaces/enable-service.description": "Aktivera en tjänst för workspace",
|
|
28
|
+
"workspaces/get-api-tokens.label": "Hämta workspace API-nycklar",
|
|
29
|
+
"workspaces/get-api-tokens.description": "Lista API-nycklar för workspace",
|
|
30
|
+
"workspaces/get-invitations.label": "Hämta inbjudningar",
|
|
31
|
+
"workspaces/get-invitations.description": "Lista väntande workspace-inbjudningar",
|
|
32
|
+
"workspaces/get-resource-templates.label": "Hämta resursmallar",
|
|
33
|
+
"workspaces/get-resource-templates.description": "Lista resursmallar tillgängliga för workspace",
|
|
34
|
+
"workspaces/get-users.label": "Hämta workspace-användare",
|
|
35
|
+
"workspaces/get-users.description": "Lista medlemmar i workspace",
|
|
36
|
+
"workspaces/get.label": "Hämta workspace",
|
|
37
|
+
"workspaces/get.description": "Ladda ett workspace via id",
|
|
38
|
+
"workspaces/import-resource-templates.label": "Importera resursmallar",
|
|
39
|
+
"workspaces/import-resource-templates.description": "Importera resursmallar till workspace",
|
|
40
|
+
"workspaces/invite-user.label": "Bjud in användare",
|
|
41
|
+
"workspaces/invite-user.description": "Skicka en workspace-inbjudan till en användare",
|
|
42
|
+
"workspaces/remove-member.label": "Ta bort medlem",
|
|
43
|
+
"workspaces/remove-member.description": "Ta bort en användare från workspace",
|
|
44
|
+
"workspaces/list.label": "Lista workspaces",
|
|
45
|
+
"workspaces/list.description": "Lista workspaces för den inloggade användaren",
|
|
46
|
+
"workspace.settings.documentTitle": "Workspace-inställningar",
|
|
47
|
+
"workspace.settings.title": "Workspace-inställningar",
|
|
48
|
+
"workspace.users.documentTitle": "Användare",
|
|
49
|
+
"workspace.users.title": "Användare",
|
|
50
|
+
"workspace.users.description": "Hantera användare i ditt workspace.",
|
|
51
|
+
"workspace.users.invite": "Bjud in användare",
|
|
52
|
+
"workspace.users.loading": "Laddar",
|
|
53
|
+
"workspace.invitations.documentTitle": "Inbjudningar",
|
|
54
|
+
"workspace.invitations.add.documentTitle": "Bjud in användare",
|
|
55
|
+
"workspace.invitations.title": "Inbjudningar",
|
|
56
|
+
"workspace.settings.detailsTitle": "Workspace-detaljer",
|
|
57
|
+
"workspace.settings.edit": "Redigera",
|
|
58
|
+
"workspace.settings.name": "Namn",
|
|
59
|
+
"workspace.settings.created": "Skapad",
|
|
60
|
+
"workspace.settings.services": "Tjänster",
|
|
61
|
+
"workspace.settings.loading": "Laddar...",
|
|
62
|
+
"workspace.invitations.description": "Bjud in användare till ditt workspace för att samarbeta.",
|
|
63
|
+
"workspace.invitations.invite": "Bjud in användare",
|
|
64
|
+
"workspace.invitations.empty": "Inga inbjudningar",
|
|
65
|
+
"workspace.invite.title": "Bjud in användare",
|
|
66
|
+
"workspace.invite.description": "Bjud in en användare att hantera och bidra med innehåll i detta workspace",
|
|
67
|
+
"workspace.invite.emailPlaceholder": "E-postadress",
|
|
68
|
+
"workspace.invite.submit": "Skicka inbjudan",
|
|
69
|
+
"workspace.invite.successTitle": "Klart",
|
|
70
|
+
"workspace.invite.successBody": "Vi skickade en inbjudan via e-post. När de har accepterat visas de i användarlistan.",
|
|
71
|
+
"workspace.invite.error": "Något gick fel — försök igen om några minuter"
|
|
72
|
+
}
|