@ossy/resources 3.9.0 → 3.11.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.
Files changed (89) hide show
  1. package/package.json +4 -4
  2. package/src/CreateDirectory.jsx +47 -53
  3. package/src/CreateDocument.jsx +1 -0
  4. package/src/GenericResourceForm.jsx +49 -31
  5. package/src/ResourceDialogMove.jsx +99 -50
  6. package/src/ResourceGrid.jsx +36 -84
  7. package/src/ResourceList.jsx +10 -1
  8. package/src/ResourcePanel.jsx +96 -17
  9. package/src/ResourceShareDialog.jsx +50 -12
  10. package/src/SchemaDetailView.jsx +15 -3
  11. package/src/Upload.jsx +25 -8
  12. package/src/batch-delete.flow.js +81 -0
  13. package/src/batch-download.flow.js +69 -0
  14. package/src/cancel-upload.action.js +4 -0
  15. package/src/cancel-upload.flow.js +40 -0
  16. package/src/close-share.action.js +4 -0
  17. package/src/confirm-upload.action.js +4 -0
  18. package/src/copy-share-link.action.js +4 -0
  19. package/src/create-directory.action.js +5 -0
  20. package/src/create-directory.flow.js +30 -0
  21. package/src/create-directory.form.js +5 -0
  22. package/src/create-directory.schema.js +9 -0
  23. package/src/create-document.flow.js +36 -0
  24. package/src/create-document.form.js +5 -0
  25. package/src/create-document.schema.js +11 -0
  26. package/src/create.action.js +5 -1
  27. package/src/delete-directory.flow.js +39 -0
  28. package/src/delete-file.flow.js +32 -0
  29. package/src/done-selecting.action.js +5 -0
  30. package/src/download-file.flow.js +31 -0
  31. package/src/download-resource.action.js +4 -0
  32. package/src/download-selected.action.js +4 -0
  33. package/src/en.translations.json +18 -0
  34. package/src/finish-upload.action.js +4 -0
  35. package/src/index.js +42 -0
  36. package/src/list.task.js +17 -6
  37. package/src/list.task.spec.js +81 -0
  38. package/src/make-private-resource.flow.js +72 -0
  39. package/src/make-private.action.js +4 -0
  40. package/src/make-public.action.js +4 -0
  41. package/src/move-file.flow.js +78 -0
  42. package/src/move.form.js +5 -0
  43. package/src/move.schema.js +9 -0
  44. package/src/open-delete-directory.action.js +7 -0
  45. package/src/open-move.action.js +4 -0
  46. package/src/open-remove-selected.action.js +5 -0
  47. package/src/open-rename.action.js +4 -0
  48. package/src/open-share.action.js +4 -0
  49. package/src/open-sort.action.js +5 -0
  50. package/src/open-view.action.js +5 -0
  51. package/src/rename-file.flow.js +43 -0
  52. package/src/rename.form.js +5 -0
  53. package/src/rename.schema.js +9 -0
  54. package/src/resource-list-query.js +182 -0
  55. package/src/resource-list-query.spec.js +75 -0
  56. package/src/resource-selection.js +25 -0
  57. package/src/resource-selection.spec.js +40 -0
  58. package/src/resource.helpers.js +8 -1
  59. package/src/resources-list-options.js +169 -0
  60. package/src/resources-list-options.spec.js +141 -0
  61. package/src/resources.action-media.js +6 -0
  62. package/src/resources.queries.js +91 -6
  63. package/src/schema-field-display.js +31 -0
  64. package/src/schema-field-display.spec.js +37 -0
  65. package/src/search-payload.js +10 -0
  66. package/src/search-payload.spec.js +20 -0
  67. package/src/search.task.js +2 -1
  68. package/src/share-resource.flow.js +59 -0
  69. package/src/sort-ascending.action.js +5 -0
  70. package/src/sort-by-created.action.js +5 -0
  71. package/src/sort-by-last-updated.action.js +5 -0
  72. package/src/sort-by-name.action.js +5 -0
  73. package/src/sort-by-size.action.js +5 -0
  74. package/src/sort-by-type.action.js +5 -0
  75. package/src/sort-descending.action.js +5 -0
  76. package/src/sort-storage-created.flow.js +87 -0
  77. package/src/sort-storage-last-updated.flow.js +119 -0
  78. package/src/sort-storage-name-asc.flow.js +34 -0
  79. package/src/sort-storage-size-desc.flow.js +34 -0
  80. package/src/sort-storage-size.flow.js +87 -0
  81. package/src/sort-storage-type.flow.js +83 -0
  82. package/src/sort-storage.flow.js +86 -0
  83. package/src/sv.translations.json +18 -0
  84. package/src/toggle-selection-mode.action.js +4 -0
  85. package/src/upload-file.flow.js +44 -0
  86. package/src/useResourceList.js +94 -0
  87. package/src/view-grid.action.js +5 -0
  88. package/src/view-list.action.js +5 -0
  89. package/src/view-storage.flow.js +49 -0
@@ -0,0 +1,30 @@
1
+ import signUpFlow from '@ossy/authentication/sign-up.flow.js'
2
+ import { metadata as CreateDirectoryAction } from './create-directory.action.js'
3
+ import { metadata as CreateDirectoryForm } from './create-directory.form.js'
4
+
5
+ export const metadata = {
6
+ id: '@ossy/resources/flows/create-directory',
7
+ feature: 'resources',
8
+ requires: ['server', 'database'],
9
+ timeout: 120_000,
10
+ }
11
+
12
+ /**
13
+ * New user signs up, opens create-directory, names a folder, and sees it on
14
+ * storage home.
15
+ */
16
+ export default {
17
+ title: 'Create directory in storage',
18
+ description:
19
+ 'Signed-in user opens create-directory, submits a folder name, and lands on storage home with the folder listed',
20
+ steps: [
21
+ ...signUpFlow.steps,
22
+ { page: '@create-directory', search: { location: '/' } },
23
+ { result: { selector: '[data-flow-stage="create-directory"]', timeout: 15000 } },
24
+ { result: { action: CreateDirectoryAction, timeout: 10000 } },
25
+ { form: CreateDirectoryForm, fields: { name: 'e2e-folder' } },
26
+ { action: CreateDirectoryAction },
27
+ { result: { page: '@storage/home', timeout: 20000 } },
28
+ { result: { selector: '[data-resource-name="e2e-folder"]', timeout: 20000 } },
29
+ ],
30
+ }
@@ -0,0 +1,5 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/form/create-directory',
3
+ schemaId: '@ossy/resources/schema/create-directory',
4
+ label: '@ossy/resources/form/create-directory.label',
5
+ }
@@ -0,0 +1,9 @@
1
+ /** Create directory form — UI fields and flow faker schema. */
2
+ export default {
3
+ id: '@ossy/resources/schema/create-directory',
4
+ name: 'Create directory',
5
+ icon: 'folder-add',
6
+ fields: [
7
+ { name: 'name', type: 'text', required: true },
8
+ ],
9
+ }
@@ -0,0 +1,36 @@
1
+ import signUpFlow from '@ossy/authentication/sign-up.flow.js'
2
+ import { metadata as CreateResource } from './create.action.js'
3
+ import { metadata as CreateDocumentForm } from './create-document.form.js'
4
+
5
+ export const metadata = {
6
+ id: '@ossy/resources/flows/create-document',
7
+ feature: 'resources',
8
+ requires: ['server', 'database'],
9
+ timeout: 120_000,
10
+ }
11
+
12
+ /**
13
+ * New user signs up, opens create-document for Markdown, names the doc, and
14
+ * sees it on storage home.
15
+ */
16
+ export default {
17
+ title: 'Create markdown document in storage',
18
+ description:
19
+ 'Signed-in user opens create-document with the Markdown schema, submits a name, and lands on storage home with the document listed',
20
+ steps: [
21
+ ...signUpFlow.steps,
22
+ {
23
+ page: '@create-document',
24
+ search: {
25
+ location: '/',
26
+ schemaId: '@ossy/resources/schema/markdown',
27
+ },
28
+ },
29
+ { result: { selector: '[data-flow-stage="create-document"]', timeout: 15000 } },
30
+ { result: { action: CreateResource, timeout: 10000 } },
31
+ { form: CreateDocumentForm, fields: { name: 'e2e-note' } },
32
+ { action: CreateResource },
33
+ { result: { page: '@storage/home', timeout: 20000 } },
34
+ { result: { selector: '[data-resource-name="e2e-note"]', timeout: 20000 } },
35
+ ],
36
+ }
@@ -0,0 +1,5 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/form/create-document',
3
+ schemaId: '@ossy/resources/schema/create-document',
4
+ label: '@ossy/resources/form/create-document.label',
5
+ }
@@ -0,0 +1,11 @@
1
+ /** Create document form — UI name field and flow faker schema. */
2
+ export default {
3
+ id: '@ossy/resources/schema/create-document',
4
+ name: 'Create document',
5
+ icon: 'file-document',
6
+ // Platform category keeps this form schema out of the generic create picker.
7
+ categoryName: 'Platform',
8
+ fields: [
9
+ { name: 'name', type: 'text', required: true },
10
+ ],
11
+ }
@@ -1 +1,5 @@
1
- export const metadata = { id: '@ossy/resources/actions/create', access: 'workspace' }
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/create',
3
+ access: 'workspace',
4
+ label: '@ossy/resources/actions/create.label',
5
+ }
@@ -0,0 +1,39 @@
1
+ import createDirectoryFlow from './create-directory.flow.js'
2
+ import { metadata as OpenDeleteDirectory } from './open-delete-directory.action.js'
3
+ import { metadata as DeleteResource } from './delete.action.js'
4
+
5
+ export const metadata = {
6
+ id: '@ossy/resources/flows/delete-directory',
7
+ feature: 'resources',
8
+ requires: ['server', 'database'],
9
+ timeout: 150_000,
10
+ }
11
+
12
+ /**
13
+ * After creating a directory, open row actions, confirm delete via Guide, and
14
+ * assert the folder leaves storage home.
15
+ */
16
+ export default {
17
+ title: 'Delete directory in storage',
18
+ description:
19
+ 'Signed-in user creates a folder, opens its row actions, confirms delete, and sees it leave storage',
20
+ steps: [
21
+ ...createDirectoryFlow.steps,
22
+ {
23
+ click: {
24
+ selector: '[data-resource-name="e2e-folder"] [data-resource-actions]',
25
+ },
26
+ },
27
+ { result: { action: OpenDeleteDirectory, timeout: 10000 } },
28
+ { action: OpenDeleteDirectory },
29
+ { result: { action: DeleteResource, timeout: 10000 } },
30
+ { action: DeleteResource },
31
+ {
32
+ result: {
33
+ selector: '[data-resource-name="e2e-folder"]',
34
+ hidden: true,
35
+ timeout: 20000,
36
+ },
37
+ },
38
+ ],
39
+ }
@@ -0,0 +1,32 @@
1
+ import uploadFileFlow from './upload-file.flow.js'
2
+ import { metadata as DeleteResource } from './delete.action.js'
3
+
4
+ export const metadata = {
5
+ id: '@ossy/resources/flows/delete-file',
6
+ feature: 'resources',
7
+ requires: ['server', 'database'],
8
+ timeout: 150_000,
9
+ }
10
+
11
+ /**
12
+ * After uploading a file, open it in the resource panel and delete it.
13
+ * The file should disappear from the storage list.
14
+ */
15
+ export default {
16
+ title: 'Delete uploaded file',
17
+ description:
18
+ 'Signed-in user uploads a file, opens the resource panel, deletes it, and sees it leave storage',
19
+ steps: [
20
+ ...uploadFileFlow.steps,
21
+ { click: { selector: '[data-resource-name="e2e-upload.txt"]' } },
22
+ { result: { action: DeleteResource, timeout: 15000 } },
23
+ { action: DeleteResource },
24
+ {
25
+ result: {
26
+ selector: '[data-resource-name="e2e-upload.txt"]',
27
+ hidden: true,
28
+ timeout: 20000,
29
+ },
30
+ },
31
+ ],
32
+ }
@@ -0,0 +1,5 @@
1
+ /** Client-only — exit storage multi-select mode. */
2
+ export const metadata = {
3
+ id: '@ossy/resources/actions/done-selecting',
4
+ access: 'workspace',
5
+ }
@@ -0,0 +1,31 @@
1
+ import uploadFileFlow from './upload-file.flow.js'
2
+ import { metadata as DownloadResource } from './download-resource.action.js'
3
+
4
+ export const metadata = {
5
+ id: '@ossy/resources/flows/download-file',
6
+ feature: 'resources',
7
+ requires: ['server', 'database'],
8
+ timeout: 150_000,
9
+ }
10
+
11
+ /**
12
+ * After uploading a file, open it in the resource panel and download via the
13
+ * panel download action (browser download event).
14
+ */
15
+ export default {
16
+ title: 'Download uploaded file',
17
+ description:
18
+ 'Signed-in user uploads a file, opens the resource panel, and downloads it',
19
+ steps: [
20
+ ...uploadFileFlow.steps,
21
+ { click: { selector: '[data-resource-name="e2e-upload.txt"]' } },
22
+ { result: { action: DownloadResource, timeout: 15000 } },
23
+ {
24
+ download: {
25
+ action: DownloadResource,
26
+ filename: 'e2e-upload.txt',
27
+ timeout: 30000,
28
+ },
29
+ },
30
+ ],
31
+ }
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/download-resource',
3
+ access: 'workspace',
4
+ }
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/download-selected',
3
+ access: 'workspace',
4
+ }
@@ -49,11 +49,29 @@
49
49
  "resources.createDirectory.submit": "Create directory",
50
50
  "resources.createDirectory.errorEmpty": "Directory name cannot be empty",
51
51
  "resources.createDirectory.errorOssyPrefix": "Directory name cannot start with @ossy",
52
+ "@ossy/resources/actions/create-directory.label": "Create directory",
53
+ "@ossy/resources/form/create-directory.label": "Create directory",
54
+ "@ossy/resources/schema/create-directory.name.label": "Directory name",
55
+ "@ossy/resources/form/create-document.label": "Create document",
56
+ "@ossy/resources/schema/create-document.name.label": "Document name",
52
57
  "resources.panel.download": "Download",
58
+ "resources.panel.delete": "Delete",
59
+ "resources.panel.rename": "Rename",
60
+ "resources.panel.move": "Move",
61
+ "resources.move.title": "Move resource",
62
+ "resources.move.errorEmpty": "Target location cannot be empty",
63
+ "resources.move.errorFailed": "Could not move the resource",
64
+ "@ossy/resources/form/rename.label": "Rename resource",
65
+ "@ossy/resources/schema/rename.name.label": "Name",
66
+ "@ossy/resources/form/move.label": "Move resource",
67
+ "@ossy/resources/schema/move.target.label": "New location",
68
+ "@ossy/resources/actions/open-move.label": "Move resource",
69
+ "@ossy/resources/actions/open-move.description": "Open the dialog to move a resource to a new location",
53
70
  "resources.share.title": "Share link",
54
71
  "resources.share.confirmPublic": "Make this resource public so anyone with the link can open it. You can copy the link after confirming.",
55
72
  "resources.share.alreadyPublic": "This resource is public. Copy the link below to share it.",
56
73
  "resources.share.makePublic": "Make public & copy link",
74
+ "resources.share.makePrivate": "Make private",
57
75
  "resources.share.copyLink": "Copy link",
58
76
  "resources.share.linkCopied": "Link copied",
59
77
  "resources.share.copyFailed": "Could not copy the link",
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/finish-upload',
3
+ access: 'workspace',
4
+ }
package/src/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export { metadata as CreateResource } from './create.action.js'
2
+ export { metadata as CreateDocumentForm } from './create-document.form.js'
3
+ export { metadata as RenameForm } from './rename.form.js'
2
4
  export { metadata as GetResource } from './get.action.js'
3
5
  export { metadata as ListResources } from './list.action.js'
4
6
  export { metadata as SearchResources } from './search.action.js'
@@ -9,6 +11,34 @@ export { metadata as UpdateResourceLocation } from './update-location.action.js'
9
11
  export { metadata as UpdateResourceName } from './update-name.action.js'
10
12
  export { metadata as UpdateResourceAccess } from './update-access.action.js'
11
13
  export { metadata as UploadNamedVersion } from './upload-named-version.action.js'
14
+ export { metadata as ConfirmUpload } from './confirm-upload.action.js'
15
+ export { metadata as FinishUpload } from './finish-upload.action.js'
16
+ export { metadata as CancelUpload } from './cancel-upload.action.js'
17
+ export { metadata as CreateDirectoryAction } from './create-directory.action.js'
18
+ export { metadata as OpenShare } from './open-share.action.js'
19
+ export { metadata as OpenRename } from './open-rename.action.js'
20
+ export { metadata as OpenMove } from './open-move.action.js'
21
+ export { metadata as OpenDeleteDirectory } from './open-delete-directory.action.js'
22
+ export { metadata as OpenRemoveSelected } from './open-remove-selected.action.js'
23
+ export { metadata as MakePublic } from './make-public.action.js'
24
+ export { metadata as MakePrivate } from './make-private.action.js'
25
+ export { metadata as CopyShareLink } from './copy-share-link.action.js'
26
+ export { metadata as CloseShare } from './close-share.action.js'
27
+ export { metadata as DownloadResource } from './download-resource.action.js'
28
+ export { metadata as DownloadSelected } from './download-selected.action.js'
29
+ export { metadata as ToggleSelectionMode } from './toggle-selection-mode.action.js'
30
+ export { metadata as OpenSort } from './open-sort.action.js'
31
+ export { metadata as SortByName } from './sort-by-name.action.js'
32
+ export { metadata as SortByCreated } from './sort-by-created.action.js'
33
+ export { metadata as SortByLastUpdated } from './sort-by-last-updated.action.js'
34
+ export { metadata as SortBySize } from './sort-by-size.action.js'
35
+ export { metadata as SortByType } from './sort-by-type.action.js'
36
+ export { metadata as SortAscending } from './sort-ascending.action.js'
37
+ export { metadata as SortDescending } from './sort-descending.action.js'
38
+ export { metadata as OpenView } from './open-view.action.js'
39
+ export { metadata as ViewList } from './view-list.action.js'
40
+ export { metadata as ViewGrid } from './view-grid.action.js'
41
+ export { metadata as DoneSelecting } from './done-selecting.action.js'
12
42
  export { metadata as CreatePageView } from './create-page-view.action.js'
13
43
  export { metadata as GetPageViewStats } from './get-page-view-stats.action.js'
14
44
  export * from './AudioResource.jsx'
@@ -52,5 +82,17 @@ export * from './useSchemas.js'
52
82
  export * from './useSchemaEngine.js'
53
83
  export * from './useDocumentValidator.js'
54
84
  export * from './useForm.js'
85
+ export * from './useResourceList.js'
55
86
  export * from './resource.helpers.js'
56
87
  export * from './document-create.helpers.js'
88
+ export {
89
+ DEFAULT_RESOURCE_LIST_LIMIT,
90
+ MAX_RESOURCE_LIST_LIMIT,
91
+ RESOURCE_LIST_SORT_FIELDS,
92
+ extractResourceListOptions,
93
+ isDirectoryResourceType,
94
+ mergeResourceListParams,
95
+ paginateResources,
96
+ resourceSizeOf,
97
+ sortResources,
98
+ } from './resources-list-options.js'
package/src/list.task.js CHANGED
@@ -1,20 +1,31 @@
1
1
  import { ResourcesQueries } from './resources.queries.js'
2
2
  import { mediaContextFromRun, withResourceMedia } from './resources.action-media.js'
3
+ import { extractResourceListOptions, mergeResourceListParams } from './resources-list-options.js'
3
4
 
4
5
  export const metadata = { id: '@ossy/resources/tasks/list' }
5
6
 
6
7
  export async function run({ payload, req }) {
7
- const query = { ...(payload?.query ?? {}) }
8
+ const merged = mergeResourceListParams(payload ?? {}, req?.query ?? {})
8
9
  const workspaceId = payload?.workspaceId ?? req?.workspaceId
9
10
  const user = payload?.user ?? req?.user
10
- let location = payload?.location ?? query.location
11
+ let location = merged.location
11
12
 
12
13
  if (location && !location.endsWith('/')) location += '/'
13
14
  if (location && !location.startsWith('/')) location = '/' + location
14
- if (location) query.location = location
15
+ if (location) merged.location = location
15
16
 
16
- if (workspaceId) query.belongsTo = workspaceId
17
+ if (workspaceId) merged.belongsTo = workspaceId
17
18
 
18
- const resources = await ResourcesQueries.GetResources(query, user)
19
- return withResourceMedia(resources, mediaContextFromRun({ payload, req }))
19
+ const { paginated } = extractResourceListOptions(merged)
20
+ const resources = await ResourcesQueries.GetResources(merged, user)
21
+ const media = mediaContextFromRun({ payload, req })
22
+
23
+ if (paginated && resources && !Array.isArray(resources)) {
24
+ return {
25
+ ...resources,
26
+ items: await withResourceMedia(resources.items ?? [], media),
27
+ }
28
+ }
29
+
30
+ return withResourceMedia(resources, media)
20
31
  }
@@ -0,0 +1,81 @@
1
+ import { describe, it, expect, jest, beforeEach } from '@jest/globals'
2
+
3
+ const getResources = jest.fn()
4
+ const withResourceMedia = jest.fn(async (value) => value)
5
+
6
+ jest.unstable_mockModule('./resources.queries.js', () => ({
7
+ ResourcesQueries: { GetResources: getResources },
8
+ }))
9
+
10
+ jest.unstable_mockModule('./resources.action-media.js', () => ({
11
+ mediaContextFromRun: () => ({}),
12
+ withResourceMedia,
13
+ }))
14
+
15
+ const { run } = await import('./list.task.js')
16
+
17
+ describe('resources/tasks/list', () => {
18
+ beforeEach(() => {
19
+ getResources.mockReset()
20
+ withResourceMedia.mockClear()
21
+ })
22
+
23
+ it('returns a media-wrapped array when unpaginated', async () => {
24
+ const resources = [{ id: 'a', name: 'A' }]
25
+ getResources.mockResolvedValue(resources)
26
+
27
+ const result = await run({
28
+ payload: { location: '/docs/', workspaceId: 'ws-1' },
29
+ req: { workspaceId: 'ws-1' },
30
+ })
31
+
32
+ expect(getResources).toHaveBeenCalledWith(
33
+ expect.objectContaining({ location: '/docs/', belongsTo: 'ws-1' }),
34
+ undefined,
35
+ )
36
+ expect(result).toEqual(resources)
37
+ })
38
+
39
+ it('preserves paginated { items, total } shape', async () => {
40
+ getResources.mockResolvedValue({
41
+ items: [{ id: 'a', name: 'A' }],
42
+ total: 120,
43
+ limit: 50,
44
+ offset: 50,
45
+ sortBy: 'name',
46
+ sortOrder: 'asc',
47
+ })
48
+
49
+ const result = await run({
50
+ payload: {
51
+ location: '/docs/',
52
+ workspaceId: 'ws-1',
53
+ limit: 50,
54
+ offset: 50,
55
+ sortBy: 'name',
56
+ sortOrder: 'asc',
57
+ },
58
+ req: { workspaceId: 'ws-1' },
59
+ })
60
+
61
+ expect(getResources).toHaveBeenCalledWith(
62
+ expect.objectContaining({
63
+ location: '/docs/',
64
+ belongsTo: 'ws-1',
65
+ limit: 50,
66
+ offset: 50,
67
+ sortBy: 'name',
68
+ sortOrder: 'asc',
69
+ }),
70
+ undefined,
71
+ )
72
+ expect(result).toEqual({
73
+ items: [{ id: 'a', name: 'A' }],
74
+ total: 120,
75
+ limit: 50,
76
+ offset: 50,
77
+ sortBy: 'name',
78
+ sortOrder: 'asc',
79
+ })
80
+ })
81
+ })
@@ -0,0 +1,72 @@
1
+ import uploadFileFlow from './upload-file.flow.js'
2
+ import { metadata as OpenShare } from './open-share.action.js'
3
+ import { metadata as MakePublic } from './make-public.action.js'
4
+ import { metadata as MakePrivate } from './make-private.action.js'
5
+ import { metadata as CloseShare } from './close-share.action.js'
6
+
7
+ export const metadata = {
8
+ id: '@ossy/resources/flows/make-private-resource',
9
+ feature: 'resources',
10
+ requires: ['server', 'database'],
11
+ timeout: 150_000,
12
+ }
13
+
14
+ /**
15
+ * After uploading a file and making it public, revoke public access from the
16
+ * share dialog and confirm the resource returns to a private share state.
17
+ */
18
+ export default {
19
+ title: 'Make uploaded resource private',
20
+ description:
21
+ 'Signed-in user uploads a file, makes it public from share, then makes it private again',
22
+ steps: [
23
+ ...uploadFileFlow.steps,
24
+ { click: { selector: '[data-resource-name="e2e-upload.txt"]' } },
25
+ { result: { action: OpenShare, timeout: 15000 } },
26
+ { action: OpenShare },
27
+ {
28
+ result: {
29
+ selector: '[data-region="resource-share"][data-share-status="private"]',
30
+ timeout: 15000,
31
+ },
32
+ },
33
+ { result: { action: MakePublic, timeout: 10000 } },
34
+ { action: MakePublic },
35
+ {
36
+ result: {
37
+ selector: '[data-region="resource-share"][data-share-status="public"]',
38
+ timeout: 20000,
39
+ },
40
+ },
41
+ {
42
+ result: {
43
+ selector: '[data-resource-name="e2e-upload.txt"][data-resource-access="public"]',
44
+ timeout: 20000,
45
+ },
46
+ },
47
+ { result: { action: MakePrivate, timeout: 10000 } },
48
+ { action: MakePrivate },
49
+ {
50
+ result: {
51
+ selector: '[data-region="resource-share"][data-share-status="private"]',
52
+ timeout: 20000,
53
+ },
54
+ },
55
+ {
56
+ result: {
57
+ selector: '[data-resource-name="e2e-upload.txt"][data-resource-access="restricted"]',
58
+ timeout: 20000,
59
+ },
60
+ },
61
+ { result: { action: MakePublic, timeout: 10000 } },
62
+ { result: { action: CloseShare, timeout: 10000 } },
63
+ { action: CloseShare },
64
+ {
65
+ result: {
66
+ selector: '[data-region="resource-share"]',
67
+ hidden: true,
68
+ timeout: 10000,
69
+ },
70
+ },
71
+ ],
72
+ }
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/make-private',
3
+ access: 'workspace',
4
+ }
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/make-public',
3
+ access: 'workspace',
4
+ }
@@ -0,0 +1,78 @@
1
+ import signUpFlow from '@ossy/authentication/sign-up.flow.js'
2
+ import { metadata as CreateDirectoryAction } from './create-directory.action.js'
3
+ import { metadata as CreateDirectoryForm } from './create-directory.form.js'
4
+ import { metadata as ConfirmUpload } from './confirm-upload.action.js'
5
+ import { metadata as FinishUpload } from './finish-upload.action.js'
6
+ import { metadata as OpenMove } from './open-move.action.js'
7
+ import { metadata as UpdateResourceLocation } from './update-location.action.js'
8
+ import { metadata as MoveForm } from './move.form.js'
9
+
10
+ export const metadata = {
11
+ id: '@ossy/resources/flows/move-file',
12
+ feature: 'resources',
13
+ requires: ['server', 'database'],
14
+ timeout: 180_000,
15
+ }
16
+
17
+ /**
18
+ * Create a folder, upload a file at storage root, move the file into the folder
19
+ * from the resource panel, and confirm it appears under the new location.
20
+ */
21
+ export default {
22
+ title: 'Move uploaded file',
23
+ description:
24
+ 'Signed-in user creates a folder, uploads a file, moves it into the folder, and sees it listed there',
25
+ steps: [
26
+ ...signUpFlow.steps,
27
+ { page: '@create-directory', search: { location: '/' } },
28
+ { result: { selector: '[data-flow-stage="create-directory"]', timeout: 15000 } },
29
+ { result: { action: CreateDirectoryAction, timeout: 10000 } },
30
+ { form: CreateDirectoryForm, fields: { name: 'e2e-folder' } },
31
+ { action: CreateDirectoryAction },
32
+ { result: { page: '@storage/home', timeout: 20000 } },
33
+ { result: { selector: '[data-resource-name="e2e-folder"]', timeout: 20000 } },
34
+ { page: '@upload-media', search: { location: '/' } },
35
+ { result: { selector: '#upload-resources', timeout: 15000 } },
36
+ { result: { selector: '[data-flow-stage="upload-idle"]', timeout: 15000 } },
37
+ {
38
+ files: {
39
+ selector: '#upload-resources',
40
+ items: [{
41
+ name: 'e2e-upload.txt',
42
+ mimeType: 'text/plain',
43
+ content: 'hello from ossy e2e move',
44
+ }],
45
+ },
46
+ },
47
+ { result: { selector: '[data-flow-stage="upload-preview"]', timeout: 15000 } },
48
+ { result: { action: ConfirmUpload, timeout: 10000 } },
49
+ { action: ConfirmUpload },
50
+ { result: { selector: '[data-flow-stage="upload-done"]', timeout: 30000 } },
51
+ { result: { action: FinishUpload, timeout: 10000 } },
52
+ { action: FinishUpload },
53
+ { result: { page: '@storage/home', timeout: 20000 } },
54
+ { result: { selector: '[data-resource-name="e2e-upload.txt"]', timeout: 20000 } },
55
+ { result: { selector: '[data-resource-name="e2e-folder"]', timeout: 20000 } },
56
+ { click: { selector: '[data-resource-name="e2e-upload.txt"]' } },
57
+ { result: { action: OpenMove, timeout: 15000 } },
58
+ { action: OpenMove },
59
+ { result: { selector: '[data-flow-stage="move-resource"]', timeout: 10000 } },
60
+ { result: { action: UpdateResourceLocation, timeout: 10000 } },
61
+ { form: MoveForm, fields: { target: '/e2e-folder/' } },
62
+ { action: UpdateResourceLocation },
63
+ {
64
+ result: {
65
+ selector: '[data-resource-name="e2e-upload.txt"]',
66
+ hidden: true,
67
+ timeout: 20000,
68
+ },
69
+ },
70
+ { page: '@storage/home', search: { location: '/e2e-folder/' } },
71
+ {
72
+ result: {
73
+ selector: '[data-resource-name="e2e-upload.txt"]',
74
+ timeout: 20000,
75
+ },
76
+ },
77
+ ],
78
+ }
@@ -0,0 +1,5 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/form/move',
3
+ schemaId: '@ossy/resources/schema/move',
4
+ label: '@ossy/resources/form/move.label',
5
+ }
@@ -0,0 +1,9 @@
1
+ /** Move resource form — UI fields and flow faker schema. */
2
+ export default {
3
+ id: '@ossy/resources/schema/move',
4
+ name: 'Move resource',
5
+ icon: 'details-more',
6
+ fields: [
7
+ { name: 'target', type: 'text', required: true },
8
+ ],
9
+ }
@@ -0,0 +1,7 @@
1
+ /** Client-only — opens the storage directory delete confirmation dialog. */
2
+ export const metadata = {
3
+ id: '@ossy/resources/actions/open-delete-directory',
4
+ access: 'workspace',
5
+ label: 'storage.resources.contextRemove',
6
+ icon: 'trash-empty',
7
+ }
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/open-move',
3
+ access: 'workspace',
4
+ }
@@ -0,0 +1,5 @@
1
+ /** Client-only — opens the storage batch-remove confirmation dialog. */
2
+ export const metadata = {
3
+ id: '@ossy/resources/actions/open-remove-selected',
4
+ access: 'workspace',
5
+ }
@@ -0,0 +1,4 @@
1
+ export const metadata = {
2
+ id: '@ossy/resources/actions/open-rename',
3
+ access: 'workspace',
4
+ }