@ossy/resources 1.12.2 → 3.0.1
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 +16 -4
- package/src/AudioResource.jsx +2 -2
- package/src/CreateDirectory.jsx +2 -10
- package/src/CreateDirectory.page.jsx +1 -1
- package/src/CreateDocument.jsx +2 -2
- package/src/CreateDocument.page.jsx +1 -1
- package/src/Definition.js +3 -2
- package/src/DocumentEdit.jsx +10 -38
- package/src/DocumentView.jsx +11 -22
- package/src/GenericResourceCard.jsx +25 -7
- package/src/GenericResourceDetail.jsx +6 -60
- package/src/GenericResourceForm.jsx +171 -37
- package/src/ImageResource.jsx +1 -1
- package/src/PDFResource.jsx +1 -1
- package/src/PlatformFileField.jsx +239 -0
- package/src/ResourceContentPage.jsx +5 -5
- package/src/ResourceDescription.jsx +1 -1
- package/src/ResourceDetails.jsx +3 -4
- package/src/ResourceDialogMove.jsx +3 -3
- package/src/ResourceFactory.jsx +11 -64
- package/src/ResourceGenericView.jsx +1 -1
- package/src/ResourceList.jsx +89 -106
- package/src/ResourcePanel.jsx +40 -57
- package/src/ResourceTags.jsx +1 -1
- package/src/ResourcesPage.jsx +26 -35
- package/src/SchemaDetailView.jsx +97 -0
- package/src/SchemaFormDefault.jsx +86 -0
- package/src/SchemaPresenter.jsx +207 -0
- package/src/Upload.jsx +6 -25
- package/src/Upload.page.jsx +1 -1
- package/src/UploadResources.jsx +2 -2
- package/src/VideoResource.jsx +1 -1
- package/src/access-filter.spec.js +1 -1
- package/src/create-page-view.action.js +1 -1
- package/src/create-page-view.task.js +10 -9
- package/src/create.action.js +1 -1
- package/src/create.task.js +27 -29
- package/src/delete.action.js +1 -1
- package/src/delete.task.js +9 -13
- package/src/en.translations.json +25 -24
- package/src/get-page-view-stats.action.js +1 -1
- package/src/get-page-view-stats.task.js +3 -4
- package/src/get-resource-alias.api.js +8 -0
- package/src/get-resource-info-alias.api.js +8 -0
- package/src/get-resource-info.api.js +36 -0
- package/src/get-resource-variant.api.js +8 -0
- package/src/get-resource.api.js +51 -0
- package/src/get.action.js +1 -1
- package/src/get.task.js +6 -6
- package/src/index.js +10 -0
- package/src/list.action.js +1 -1
- package/src/list.task.js +1 -1
- package/src/platform-file-field.component.jsx +5 -0
- package/src/platform-image-field.component.jsx +5 -0
- package/src/resource-create.page.jsx +5 -5
- package/src/resource-detail.page.jsx +1 -1
- package/src/resource-read.helpers.js +151 -0
- package/src/resource-stream.helpers.js +20 -0
- package/src/resource-stream.js +108 -0
- package/src/resource.helpers.js +9 -9
- package/src/resources.attach-media-urls.js +9 -3
- package/src/resources.events.js +42 -81
- package/src/{resources.spec.js → resources.integration.spec.js} +19 -19
- package/src/resources.queries.js +5 -2
- package/src/schema-detail.component.jsx +24 -0
- package/src/schema-form-default.component.jsx +14 -0
- package/src/schemaFormSlots.js +6 -0
- package/src/schemaViewSlots.js +6 -0
- package/src/search.action.js +1 -1
- package/src/search.task.js +1 -1
- package/src/server.js +2 -1
- package/src/sv.translations.json +25 -24
- package/src/update-access.action.js +1 -1
- package/src/update-access.task.js +9 -8
- package/src/update-content.action.js +1 -1
- package/src/update-content.task.js +25 -27
- package/src/update-location.action.js +1 -1
- package/src/update-location.task.js +9 -8
- package/src/update-name.action.js +1 -1
- package/src/update-name.task.js +9 -8
- package/src/upload-named-version.action.js +1 -1
- package/src/upload-named-version.task.js +16 -22
- package/src/useActivePath.jsx +3 -8
- package/src/useDocumentValidator.js +16 -0
- package/src/useSchemaEngine.js +9 -0
- package/src/useSchemas.js +29 -0
- package/src/useSelectedResourceId.jsx +36 -0
- package/src/ResourceContentPage.stories.jsx +0 -19
- package/src/resource.aggregate.js +0 -86
|
@@ -4,8 +4,8 @@ import { Workspace } from '@ossy/workspaces/server'
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Adds `content.src` (and `content.sizes[*]` URLs) for file resources, respecting
|
|
7
|
-
* `access` and workspace membership.
|
|
8
|
-
*
|
|
7
|
+
* `access` and workspace membership. All backends expose the same read URL shape:
|
|
8
|
+
* `/r/{resourceId}` (derivatives: `/r/{resourceId}/{variant}`).
|
|
9
9
|
*
|
|
10
10
|
* @param {object} resource - Resource view
|
|
11
11
|
* @param {{ userId?: string, workspaceId?: string }} context
|
|
@@ -22,7 +22,13 @@ export async function attachResourceMediaUrls(resource, { userId, workspaceId }
|
|
|
22
22
|
|
|
23
23
|
const access = resource.access || 'restricted'
|
|
24
24
|
const isMember = Boolean(userId && workspace?.users?.includes(userId))
|
|
25
|
-
const
|
|
25
|
+
const inWorkspaceContext = Boolean(
|
|
26
|
+
userId && workspaceId && resource.belongsTo === workspaceId,
|
|
27
|
+
)
|
|
28
|
+
const allowMedia =
|
|
29
|
+
access === 'public' ||
|
|
30
|
+
(access === 'workspace' && inWorkspaceContext) ||
|
|
31
|
+
(access === 'restricted' && isMember)
|
|
26
32
|
|
|
27
33
|
const nextContent = { ...resource.content }
|
|
28
34
|
|
package/src/resources.events.js
CHANGED
|
@@ -1,98 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
2
|
+
* ADR 0008 resource lifecycle events.
|
|
3
|
+
*/
|
|
5
4
|
export class ResourcesEvents {
|
|
6
5
|
|
|
7
|
-
static Created({
|
|
8
|
-
|
|
6
|
+
static Created ({
|
|
7
|
+
resourceId,
|
|
8
|
+
schemaId,
|
|
9
9
|
createdBy,
|
|
10
10
|
belongsTo,
|
|
11
11
|
location,
|
|
12
|
-
type,
|
|
13
12
|
name,
|
|
14
|
-
|
|
13
|
+
access,
|
|
14
|
+
content,
|
|
15
|
+
...rest
|
|
15
16
|
}) {
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
createdBy
|
|
17
|
+
return {
|
|
18
|
+
type: schemaId,
|
|
19
|
+
resourceId,
|
|
20
|
+
event: 'Created',
|
|
21
|
+
createdBy,
|
|
21
22
|
payload: {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
belongsTo,
|
|
24
|
+
location,
|
|
25
|
+
name,
|
|
26
|
+
access,
|
|
27
|
+
content: content ?? {},
|
|
28
|
+
...rest,
|
|
29
|
+
},
|
|
30
|
+
}
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
static
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
createdBy
|
|
35
|
-
payload:
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static NameUpdated({ createdBy, name }) {
|
|
42
|
-
return ({
|
|
43
|
-
type: 'NameUpdated',
|
|
44
|
-
createdBy: createdBy,
|
|
45
|
-
payload: {
|
|
46
|
-
name: name
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
static AccessUpdated({ createdBy, access }) {
|
|
52
|
-
return ({
|
|
53
|
-
type: 'AccessUpdated',
|
|
54
|
-
createdBy: createdBy,
|
|
55
|
-
payload: {
|
|
56
|
-
access: access
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
static LocationUpdated({ createdBy, location }) {
|
|
62
|
-
return ({
|
|
63
|
-
type: 'LocationUpdated',
|
|
64
|
-
createdBy: createdBy,
|
|
65
|
-
payload: {
|
|
66
|
-
location: location
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
static Deleted({ createdBy }) {
|
|
72
|
-
return ({
|
|
73
|
-
type: 'Deleted',
|
|
74
|
-
createdBy: createdBy
|
|
75
|
-
})
|
|
33
|
+
static Patched ({ createdBy, ...partial }) {
|
|
34
|
+
return {
|
|
35
|
+
event: 'Patched',
|
|
36
|
+
createdBy,
|
|
37
|
+
payload: partial,
|
|
38
|
+
}
|
|
76
39
|
}
|
|
77
40
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
ContentLength,
|
|
83
|
-
ContentType,
|
|
84
|
-
Key
|
|
85
|
-
}) {
|
|
86
|
-
return ({
|
|
87
|
-
type: 'NamedVersionUploaded',
|
|
88
|
-
createdBy: createdBy,
|
|
41
|
+
static Updated ({ createdBy, content, name }) {
|
|
42
|
+
return {
|
|
43
|
+
event: 'Updated',
|
|
44
|
+
createdBy,
|
|
89
45
|
payload: {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
})
|
|
46
|
+
...(content !== undefined ? { content } : {}),
|
|
47
|
+
...(name !== undefined ? { name } : {}),
|
|
48
|
+
},
|
|
49
|
+
}
|
|
96
50
|
}
|
|
97
51
|
|
|
52
|
+
static Deleted ({ createdBy }) {
|
|
53
|
+
return {
|
|
54
|
+
event: 'Deleted',
|
|
55
|
+
createdBy,
|
|
56
|
+
payload: {},
|
|
57
|
+
}
|
|
58
|
+
}
|
|
98
59
|
}
|
|
@@ -9,58 +9,58 @@ function workspaceHeaders(userToken, workspaceId) {
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
describe('[resources/create]', () => {
|
|
12
|
+
describe('[resources/actions/create]', () => {
|
|
13
13
|
|
|
14
14
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
15
|
-
actionId: 'resources/create',
|
|
15
|
+
actionId: '@ossy/resources/actions/create',
|
|
16
16
|
payload: { type: 'directory', location: '/', name: 'test' },
|
|
17
17
|
headers: { workspaceId: 'ws-test' },
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
describe('[resources/list]', () => {
|
|
22
|
+
describe('[resources/actions/list]', () => {
|
|
23
23
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
24
|
-
actionId: 'resources/list',
|
|
24
|
+
actionId: '@ossy/resources/actions/list',
|
|
25
25
|
headers: { workspaceId: 'ws-test' },
|
|
26
26
|
})
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
describe('[resources/get]', () => {
|
|
29
|
+
describe('[resources/actions/get]', () => {
|
|
30
30
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
31
|
-
actionId: 'resources/get',
|
|
31
|
+
actionId: '@ossy/resources/actions/get',
|
|
32
32
|
payload: { resourceId: 'r1' },
|
|
33
33
|
headers: { workspaceId: 'ws-test' },
|
|
34
34
|
})
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
describe('[resources/update-name]', () => {
|
|
37
|
+
describe('[resources/actions/update-name]', () => {
|
|
38
38
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
39
|
-
actionId: 'resources/update-name',
|
|
39
|
+
actionId: '@ossy/resources/actions/update-name',
|
|
40
40
|
payload: { resourceId: 'r1', name: 'x' },
|
|
41
41
|
headers: { workspaceId: 'ws-test' },
|
|
42
42
|
})
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
describe('[resources/update-location]', () => {
|
|
45
|
+
describe('[resources/actions/update-location]', () => {
|
|
46
46
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
47
|
-
actionId: 'resources/update-location',
|
|
47
|
+
actionId: '@ossy/resources/actions/update-location',
|
|
48
48
|
payload: { resourceId: 'r1', target: '/other/' },
|
|
49
49
|
headers: { workspaceId: 'ws-test' },
|
|
50
50
|
})
|
|
51
51
|
})
|
|
52
52
|
|
|
53
|
-
describe('[resources/update-content]', () => {
|
|
53
|
+
describe('[resources/actions/update-content]', () => {
|
|
54
54
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
55
|
-
actionId: 'resources/update-content',
|
|
55
|
+
actionId: '@ossy/resources/actions/update-content',
|
|
56
56
|
payload: { resourceId: 'r1', content: {} },
|
|
57
57
|
headers: { workspaceId: 'ws-test' },
|
|
58
58
|
})
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
describe('[resources/delete]', () => {
|
|
61
|
+
describe('[resources/actions/delete]', () => {
|
|
62
62
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
63
|
-
actionId: 'resources/delete',
|
|
63
|
+
actionId: '@ossy/resources/actions/delete',
|
|
64
64
|
payload: { resourceId: 'r1' },
|
|
65
65
|
headers: { workspaceId: 'ws-test' },
|
|
66
66
|
})
|
|
@@ -70,7 +70,7 @@ describe('E2E: template-backed resource (workspaceId header)', () => {
|
|
|
70
70
|
it('create → update content → delete', async () => {
|
|
71
71
|
const user = await TestUtil.GetAuthenticatedTestUser()
|
|
72
72
|
const workspace = await TestUtil.InvokeAction({
|
|
73
|
-
actionId: 'workspaces/create',
|
|
73
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
74
74
|
headers: { 'Content-Type': 'application/json', Authorization: user.token },
|
|
75
75
|
payload: { name: casual.word },
|
|
76
76
|
}).then(r => r.json())
|
|
@@ -88,7 +88,7 @@ describe('E2E: template-backed resource (workspaceId header)', () => {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const createRes = await TestUtil.InvokeAction({
|
|
91
|
-
actionId: 'resources/create',
|
|
91
|
+
actionId: '@ossy/resources/actions/create',
|
|
92
92
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
93
93
|
payload: createBody,
|
|
94
94
|
})
|
|
@@ -103,7 +103,7 @@ describe('E2E: template-backed resource (workspaceId header)', () => {
|
|
|
103
103
|
})
|
|
104
104
|
|
|
105
105
|
const updateRes = await TestUtil.InvokeAction({
|
|
106
|
-
actionId: 'resources/update-content',
|
|
106
|
+
actionId: '@ossy/resources/actions/update-content',
|
|
107
107
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
108
108
|
payload: {
|
|
109
109
|
resourceId: created.id,
|
|
@@ -124,7 +124,7 @@ describe('E2E: template-backed resource (workspaceId header)', () => {
|
|
|
124
124
|
})
|
|
125
125
|
|
|
126
126
|
const deleteRes = await TestUtil.InvokeAction({
|
|
127
|
-
actionId: 'resources/delete',
|
|
127
|
+
actionId: '@ossy/resources/actions/delete',
|
|
128
128
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
129
129
|
payload: { resourceId: created.id },
|
|
130
130
|
})
|
|
@@ -134,7 +134,7 @@ describe('E2E: template-backed resource (workspaceId header)', () => {
|
|
|
134
134
|
expect(deleteBody).toEqual({ ok: true })
|
|
135
135
|
|
|
136
136
|
const listRes = await TestUtil.InvokeAction({
|
|
137
|
-
actionId: 'resources/list',
|
|
137
|
+
actionId: '@ossy/resources/actions/list',
|
|
138
138
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
139
139
|
payload: { query: { location: '/' } },
|
|
140
140
|
})
|
package/src/resources.queries.js
CHANGED
|
@@ -36,7 +36,7 @@ export function accessFilter(user) {
|
|
|
36
36
|
if (!user?.anonymous) {
|
|
37
37
|
if (user?.workspaces?.length) {
|
|
38
38
|
conditions.push({
|
|
39
|
-
'state.access': { $in: ['public', 'workspace'] },
|
|
39
|
+
'state.access': { $in: ['public', 'workspace', 'restricted'] },
|
|
40
40
|
'state.belongsTo': { $in: user.workspaces },
|
|
41
41
|
})
|
|
42
42
|
}
|
|
@@ -73,7 +73,10 @@ export class ResourcesQueries {
|
|
|
73
73
|
const workspaceScope = query['state.belongsTo'] ?? '(no workspace scope)'
|
|
74
74
|
log.info(`[ResourcesQueries][GetResources] Fetching resources for ${workspaceScope}`)
|
|
75
75
|
|
|
76
|
-
const baseQuery = {
|
|
76
|
+
const baseQuery = {
|
|
77
|
+
...query,
|
|
78
|
+
type: { $regex: /^@[^/]+\/[^/]+\/schema\// },
|
|
79
|
+
}
|
|
77
80
|
const mongoQuery = user ? { $and: [baseQuery, accessFilter(user)] } : baseQuery
|
|
78
81
|
|
|
79
82
|
return Aggregate.Collection.find(mongoQuery, { state: true }).toArray()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Text, View } from '@ossy/design-system'
|
|
3
|
+
import { SchemaDetailView } from './SchemaDetailView.jsx'
|
|
4
|
+
|
|
5
|
+
export const metadata = { id: '@ossy/resources/view/detail' }
|
|
6
|
+
|
|
7
|
+
/** Generic schema detail view — `@ossy/resources/view/detail`. */
|
|
8
|
+
export default function SchemaDetailViewComponent ({ resource, schemaId, fields, projection }) {
|
|
9
|
+
if (!resource) return null
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<View inset="m">
|
|
13
|
+
<SchemaDetailView
|
|
14
|
+
schemaId={schemaId ?? resource.type}
|
|
15
|
+
fields={fields}
|
|
16
|
+
data={resource.content ?? {}}
|
|
17
|
+
title={resource.name}
|
|
18
|
+
/>
|
|
19
|
+
{projection && (
|
|
20
|
+
<Text size="s" color="secondary">projection: {projection}</Text>
|
|
21
|
+
)}
|
|
22
|
+
</View>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View } from '@ossy/design-system'
|
|
3
|
+
import { SchemaFormDefault } from './SchemaFormDefault.jsx'
|
|
4
|
+
|
|
5
|
+
export const metadata = { id: '@ossy/resources/form/default' }
|
|
6
|
+
|
|
7
|
+
/** Generic schema form — `@ossy/resources/form/default`. */
|
|
8
|
+
export default function SchemaFormDefaultComponent (props) {
|
|
9
|
+
return (
|
|
10
|
+
<View inset="m">
|
|
11
|
+
<SchemaFormDefault {...props} />
|
|
12
|
+
</View>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import SchemaFormDefaultComponent from './schema-form-default.component.jsx'
|
|
2
|
+
|
|
3
|
+
/** Default schema form slots merged into {@link ComponentSlotsProvider} at app bootstrap. */
|
|
4
|
+
export const DEFAULT_SCHEMA_FORM_SLOTS = {
|
|
5
|
+
'@ossy/resources/form/default': SchemaFormDefaultComponent,
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import SchemaDetailViewComponent from './schema-detail.component.jsx'
|
|
2
|
+
|
|
3
|
+
/** Default schema view slots merged into {@link ComponentSlotsProvider} at app bootstrap. */
|
|
4
|
+
export const DEFAULT_SCHEMA_VIEW_SLOTS = {
|
|
5
|
+
'@ossy/resources/view/detail': SchemaDetailViewComponent,
|
|
6
|
+
}
|
package/src/search.action.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const metadata = { id: 'resources/search', access: 'workspace' }
|
|
1
|
+
export const metadata = { id: '@ossy/resources/actions/search', access: 'workspace' }
|
package/src/search.task.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ResourcesQueries } from './resources.queries.js'
|
|
2
2
|
import { mediaContextFromRun, withResourceMedia } from './resources.action-media.js'
|
|
3
3
|
|
|
4
|
-
export const metadata = { id: 'resources/search' }
|
|
4
|
+
export const metadata = { id: '@ossy/resources/tasks/search' }
|
|
5
5
|
|
|
6
6
|
export async function run({ payload, req }) {
|
|
7
7
|
const query = { ...(payload ?? {}) }
|
package/src/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export * from './resource.
|
|
1
|
+
export * from './resource-stream.js'
|
|
2
|
+
export * from './resource-stream.helpers.js'
|
|
2
3
|
export * from './resources.events.js'
|
|
3
4
|
export * from './resources.queries.js'
|
|
4
5
|
export { attachResourceMediaUrls } from './resources.attach-media-urls.js'
|
package/src/sv.translations.json
CHANGED
|
@@ -7,30 +7,31 @@
|
|
|
7
7
|
"resources.form.selectType": "Välj en resurstyp för att fortsätta.",
|
|
8
8
|
"resources.form.createFailed": "Skapandet misslyckades",
|
|
9
9
|
"resources.form.createResource": "Skapa resurs",
|
|
10
|
-
"resources
|
|
11
|
-
"resources/create.
|
|
12
|
-
"resources/
|
|
13
|
-
"resources/list.
|
|
14
|
-
"resources/
|
|
15
|
-
"resources/get.
|
|
16
|
-
"resources/
|
|
17
|
-
"resources/search.
|
|
18
|
-
"resources/
|
|
19
|
-
"resources/delete.
|
|
20
|
-
"resources/
|
|
21
|
-
"resources/update-name.
|
|
22
|
-
"resources/update-
|
|
23
|
-
"resources/update-content.
|
|
24
|
-
"resources/update-
|
|
25
|
-
"resources/update-location.
|
|
26
|
-
"resources/update-
|
|
27
|
-
"resources/update-access.
|
|
28
|
-
"resources/
|
|
29
|
-
"resources/upload-named-version.
|
|
30
|
-
"resources/
|
|
31
|
-
"resources/create-page-view.
|
|
32
|
-
"resources/
|
|
33
|
-
"resources/get-page-view-stats.
|
|
10
|
+
"resources.form.typeRemoved": "Den här dokumenttypen har tagits bort och kan inte redigeras.",
|
|
11
|
+
"@ossy/resources/actions/create.label": "Skapa resurs",
|
|
12
|
+
"@ossy/resources/actions/create.description": "Skapa en ny resurs i workspace",
|
|
13
|
+
"@ossy/resources/actions/list.label": "Lista resurser",
|
|
14
|
+
"@ossy/resources/actions/list.description": "Lista resurser på en plats i workspace",
|
|
15
|
+
"@ossy/resources/actions/get.label": "Hämta resurs",
|
|
16
|
+
"@ossy/resources/actions/get.description": "Hämta en enskild resurs via id",
|
|
17
|
+
"@ossy/resources/actions/search.label": "Sök resurser",
|
|
18
|
+
"@ossy/resources/actions/search.description": "Sök resurser i en workspace",
|
|
19
|
+
"@ossy/resources/actions/delete.label": "Ta bort resurs",
|
|
20
|
+
"@ossy/resources/actions/delete.description": "Ta bort en resurs från workspace",
|
|
21
|
+
"@ossy/resources/actions/update-name.label": "Uppdatera resursnamn",
|
|
22
|
+
"@ossy/resources/actions/update-name.description": "Byt namn på en resurs i workspace",
|
|
23
|
+
"@ossy/resources/actions/update-content.label": "Uppdatera resursinnehåll",
|
|
24
|
+
"@ossy/resources/actions/update-content.description": "Uppdatera innehållet i en resurs",
|
|
25
|
+
"@ossy/resources/actions/update-location.label": "Uppdatera resursplats",
|
|
26
|
+
"@ossy/resources/actions/update-location.description": "Flytta en resurs till en ny plats",
|
|
27
|
+
"@ossy/resources/actions/update-access.label": "Uppdatera resursåtkomst",
|
|
28
|
+
"@ossy/resources/actions/update-access.description": "Ändra åtkomstinställningar för en resurs",
|
|
29
|
+
"@ossy/resources/actions/upload-named-version.label": "Ladda upp namngiven version",
|
|
30
|
+
"@ossy/resources/actions/upload-named-version.description": "Ladda upp en namngiven version av en resursfil",
|
|
31
|
+
"@ossy/resources/actions/create-page-view.label": "Skapa sidvisning",
|
|
32
|
+
"@ossy/resources/actions/create-page-view.description": "Registrera en sidvisningshändelse för analys",
|
|
33
|
+
"@ossy/resources/actions/get-page-view-stats.label": "Hämta sidvisningsstatistik",
|
|
34
|
+
"@ossy/resources/actions/get-page-view-stats.description": "Hämta aggregerad statistik för sidvisningar",
|
|
34
35
|
"resources/create/generic.documentTitle": "Skapa resurs",
|
|
35
36
|
"create-directory.documentTitle": "Skapa mapp",
|
|
36
37
|
"create-document.documentTitle": "Skapa dokument",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const metadata = { id: 'resources/update-access', access: 'workspace' }
|
|
1
|
+
export const metadata = { id: '@ossy/resources/actions/update-access', access: 'workspace' }
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Aggregate } from '@ossy/event-store'
|
|
2
|
-
import { Resource } from './resource.aggregate.js'
|
|
3
1
|
import { ResourcesEvents } from './resources.events.js'
|
|
2
|
+
import { mutateResource } from './resource-stream.helpers.js'
|
|
3
|
+
import { resolveResourceId } from './resource-read.helpers.js'
|
|
4
4
|
import { mediaContextFromRun, withResourceMedia } from './resources.action-media.js'
|
|
5
5
|
|
|
6
|
-
export const metadata = { id: 'resources/update-access' }
|
|
6
|
+
export const metadata = { id: '@ossy/resources/tasks/update-access' }
|
|
7
7
|
|
|
8
|
-
export async function run({ payload, req }) {
|
|
8
|
+
export async function run ({ payload, req }) {
|
|
9
9
|
const createdBy = payload?.userId ?? req?.userId
|
|
10
|
-
const resourceId = payload
|
|
10
|
+
const resourceId = resolveResourceId({ payload, req })
|
|
11
11
|
const resourceAccess = payload?.access
|
|
12
12
|
|
|
13
13
|
if (!resourceId) throw Object.assign(new Error('resourceId is required'), { status: 400 })
|
|
@@ -15,8 +15,9 @@ export async function run({ payload, req }) {
|
|
|
15
15
|
throw Object.assign(new Error(`Invalid access value: ${resourceAccess}`), { status: 400 })
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const resource = await
|
|
19
|
-
|
|
20
|
-
.
|
|
18
|
+
const resource = await mutateResource(
|
|
19
|
+
resourceId,
|
|
20
|
+
ResourcesEvents.Patched({ createdBy, access: resourceAccess }),
|
|
21
|
+
)
|
|
21
22
|
return withResourceMedia(resource, mediaContextFromRun({ payload, req }))
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const metadata = { id: 'resources/update-content', access: 'workspace' }
|
|
1
|
+
export const metadata = { id: '@ossy/resources/actions/update-content', access: 'workspace' }
|
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
import { Aggregate } from '@ossy/event-store'
|
|
2
|
-
import { Resource } from './resource.aggregate.js'
|
|
3
|
-
import { ResourcesEvents } from './resources.events.js'
|
|
4
2
|
import { Workspace } from '@ossy/workspaces/server'
|
|
5
|
-
import {
|
|
3
|
+
import { schemaForWorkspace } from '@ossy/platform'
|
|
4
|
+
import { ResourcesEvents } from './resources.events.js'
|
|
5
|
+
import { mutateResource, viewResource } from './resource-stream.helpers.js'
|
|
6
6
|
import { mediaContextFromRun, withResourceMedia } from './resources.action-media.js'
|
|
7
|
+
import { resolveResourceId } from './resource-read.helpers.js'
|
|
7
8
|
|
|
8
|
-
export const metadata = { id: 'resources/update-content' }
|
|
9
|
+
export const metadata = { id: '@ossy/resources/tasks/update-content' }
|
|
9
10
|
|
|
10
|
-
export async function run({ payload, req }) {
|
|
11
|
+
export async function run ({ payload, req }) {
|
|
11
12
|
const createdBy = payload?.userId ?? req?.userId
|
|
12
|
-
const resourceId = payload
|
|
13
|
+
const resourceId = resolveResourceId({ payload, req })
|
|
13
14
|
const content = payload?.content
|
|
14
15
|
const workspaceId = payload?.workspaceId ?? req?.workspaceId
|
|
15
16
|
|
|
16
17
|
if (!resourceId) throw Object.assign(new Error('resourceId is required'), { status: 400 })
|
|
17
18
|
|
|
18
19
|
const workspace = await Aggregate.Of(Workspace, workspaceId).then(Aggregate.View())
|
|
20
|
+
const current = await viewResource(resourceId)
|
|
21
|
+
|
|
22
|
+
const engine = schemaForWorkspace(workspace.schemas)
|
|
23
|
+
const schema = engine.has(current.type) ? engine.resolve(current.type) : null
|
|
24
|
+
let finalContent = content
|
|
25
|
+
if (schema) {
|
|
26
|
+
const result = engine.validate(schema, content)
|
|
27
|
+
if (!result.ok) {
|
|
28
|
+
const first = result.errors[0]
|
|
29
|
+
throw Object.assign(new Error(first.message), { status: 400, type: first.code })
|
|
30
|
+
}
|
|
31
|
+
finalContent = result.data
|
|
32
|
+
}
|
|
19
33
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
...systemTemplates,
|
|
26
|
-
...(workspace.resourceTemplates || []).filter(t => !systemTemplates.find(s => s.id === t.id)),
|
|
27
|
-
]
|
|
28
|
-
const template = allTemplates.find(t => t.id === resource.type)
|
|
29
|
-
let finalContent = content
|
|
30
|
-
if (template) {
|
|
31
|
-
const normalized = normalizeAndValidateDocumentContent(content, template)
|
|
32
|
-
if (!normalized.ok) {
|
|
33
|
-
throw Object.assign(new Error(normalized.message), { status: 400, type: normalized.code })
|
|
34
|
-
}
|
|
35
|
-
finalContent = normalized.content
|
|
36
|
-
}
|
|
37
|
-
return Aggregate.Add(ResourcesEvents.ContentUpdated({ createdBy, content: finalContent }))(aggregate)
|
|
38
|
-
})
|
|
39
|
-
.then(Aggregate.View())
|
|
40
|
-
.then(resource => withResourceMedia(resource, mediaContextFromRun({ payload, req })))
|
|
34
|
+
const updated = await mutateResource(
|
|
35
|
+
resourceId,
|
|
36
|
+
ResourcesEvents.Updated({ createdBy, content: finalContent }),
|
|
37
|
+
)
|
|
38
|
+
return withResourceMedia(updated, mediaContextFromRun({ payload, req }))
|
|
41
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const metadata = { id: 'resources/update-location', access: 'workspace' }
|
|
1
|
+
export const metadata = { id: '@ossy/resources/actions/update-location', access: 'workspace' }
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { Aggregate } from '@ossy/event-store'
|
|
2
|
-
import { Resource } from './resource.aggregate.js'
|
|
3
1
|
import { ResourcesEvents } from './resources.events.js'
|
|
2
|
+
import { mutateResource } from './resource-stream.helpers.js'
|
|
3
|
+
import { resolveResourceId } from './resource-read.helpers.js'
|
|
4
4
|
import { mediaContextFromRun, withResourceMedia } from './resources.action-media.js'
|
|
5
5
|
|
|
6
|
-
export const metadata = { id: 'resources/update-location' }
|
|
6
|
+
export const metadata = { id: '@ossy/resources/tasks/update-location' }
|
|
7
7
|
|
|
8
|
-
export async function run({ payload, req }) {
|
|
8
|
+
export async function run ({ payload, req }) {
|
|
9
9
|
const createdBy = payload?.userId ?? req?.userId
|
|
10
|
-
const resourceId = payload
|
|
10
|
+
const resourceId = resolveResourceId({ payload, req })
|
|
11
11
|
const location = payload?.target ?? payload?.location
|
|
12
12
|
|
|
13
13
|
if (!resourceId) throw Object.assign(new Error('resourceId is required'), { status: 400 })
|
|
14
14
|
if (!location) throw Object.assign(new Error('target location is required'), { status: 400 })
|
|
15
15
|
|
|
16
|
-
const resource = await
|
|
17
|
-
|
|
18
|
-
.
|
|
16
|
+
const resource = await mutateResource(
|
|
17
|
+
resourceId,
|
|
18
|
+
ResourcesEvents.Patched({ createdBy, location }),
|
|
19
|
+
)
|
|
19
20
|
return withResourceMedia(resource, mediaContextFromRun({ payload, req }))
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const metadata = { id: 'resources/update-name', access: 'workspace' }
|
|
1
|
+
export const metadata = { id: '@ossy/resources/actions/update-name', access: 'workspace' }
|
package/src/update-name.task.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { Aggregate } from '@ossy/event-store'
|
|
2
|
-
import { Resource } from './resource.aggregate.js'
|
|
3
1
|
import { ResourcesEvents } from './resources.events.js'
|
|
2
|
+
import { mutateResource } from './resource-stream.helpers.js'
|
|
3
|
+
import { resolveResourceId } from './resource-read.helpers.js'
|
|
4
4
|
import { mediaContextFromRun, withResourceMedia } from './resources.action-media.js'
|
|
5
5
|
|
|
6
|
-
export const metadata = { id: 'resources/update-name' }
|
|
6
|
+
export const metadata = { id: '@ossy/resources/tasks/update-name' }
|
|
7
7
|
|
|
8
|
-
export async function run({ payload, req }) {
|
|
8
|
+
export async function run ({ payload, req }) {
|
|
9
9
|
const createdBy = payload?.userId ?? req?.userId
|
|
10
|
-
const resourceId = payload
|
|
10
|
+
const resourceId = resolveResourceId({ payload, req })
|
|
11
11
|
const name = payload?.name
|
|
12
12
|
|
|
13
13
|
if (!resourceId) throw Object.assign(new Error('resourceId is required'), { status: 400 })
|
|
14
14
|
if (!name) throw Object.assign(new Error('name is required'), { status: 400 })
|
|
15
15
|
|
|
16
|
-
const resource = await
|
|
17
|
-
|
|
18
|
-
.
|
|
16
|
+
const resource = await mutateResource(
|
|
17
|
+
resourceId,
|
|
18
|
+
ResourcesEvents.Patched({ createdBy, name }),
|
|
19
|
+
)
|
|
19
20
|
return withResourceMedia(resource, mediaContextFromRun({ payload, req }))
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const metadata = { id: 'resources/upload-named-version', access: 'workspace' }
|
|
1
|
+
export const metadata = { id: '@ossy/resources/actions/upload-named-version', access: 'workspace' }
|