@lowdefy/plugin-aws 4.0.0-alpha.9 → 4.0.0-rc.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/README.md ADDED
@@ -0,0 +1,332 @@
1
+ # Lowdefy S3 Upload Blocks
2
+
3
+ To securely upload files to S3, the `S3UploadButton` or `S3UploadPhoto` blocks can be used. S3 file downloads can be done by getting a presigned URL using a `AwsS3PresignedGetObject` request and opening the URL in a new tab which will result in the browser starting the file download.
4
+
5
+ To access the [Amazon S3 API](https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html), a `AwsS3Bucket` connection is defined, and a `AwsS3PresignedPostPolicy` or `AwsS3PresignedGetObject` requests can be used to either upload or download files to S3.
6
+
7
+ ### AwsS3Bucket Connection
8
+ The `AwsS3Bucket` connenction provides functionality of the [Amazon S3 API](https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html).
9
+
10
+ ##### Properties
11
+ - `accessKeyId: string`: AWS IAM access key id with s3 access.
12
+ - `secretAccessKey: string` : AWS IAM secret access key with s3 access.
13
+ - `region: string`: AWS region the bucket is located in
14
+ - `bucket: string`: S3 bucket name.
15
+ - `read: boolean` : Allow reads from the bucket.
16
+ - `write: boolean`: Allow writes to the bucket.
17
+
18
+ ### AwsS3PresignedPostPolicy File Upload Request
19
+ To upload files, a request of type `AwsS3PresignedPostPolicy` is used.
20
+
21
+ ##### Properties
22
+ - `acl: string`: Access control lists used to grant read and write access.
23
+ - `conditions: array`: Conditions to be enforced on the request.
24
+ - `expires: number`: Number of seconds for which the policy should be valid.
25
+ - `key: string`: Key under which object will be stored.
26
+
27
+ ### AwsS3PresignedGetObject File Download Request
28
+ To download files, a request of type `AwsS3PresignedGetObject` is used.
29
+
30
+ ##### Properties
31
+ - `expires: number`: Number of seconds for which the policy should be valid.
32
+ - `key: string`: Key under which object is stored .
33
+ - `responseContentDisposition: string`: Sets the Content-Disposition header of the response.
34
+ - `responseContentType: string`: Sets the Content-Type header of the response.
35
+ - `versionId: string`: VersionId used to reference a specific version of the object.
36
+
37
+ ### S3UploadButton and S3UploadPhoto Blocks
38
+
39
+ ##### Properties
40
+ - `accept: string`: File types accepted by the input. See html file type input accept property at [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept).
41
+ - `button: object`: Button block properties.
42
+ - `disabled: boolean`: Disable the file input.
43
+ - `s3PostPolicyRequestId: string`: Id of a request of type AwsS3PresignedPostPolicy that defines to which S3 bucket and how the file should be uploaded.
44
+ - `showUploadList: boolean`: Whether to show default upload list.
45
+ - `singleFile: boolean`: Only allow a single file to be uploaded. Only one file can be selected in the prompt and the upload button is disabled after a file is uploaded.
46
+
47
+ ##### Events
48
+ - `onChange`: Triggered when the upload state is changing.
49
+ - `onClick`: Triggered when the upload button is clicked.
50
+ - `onSuccess`: Triggered when the upload is successful, returns `_event` object:
51
+ - `meta`:
52
+ - `bucket`: Name of bucket that the file was stored in.
53
+ - `filename`: Uploaded filename.
54
+ - `key`: Key under which the file is stored.
55
+ - `size`: Size of uploaded file.
56
+ - `type`: Type of uploaded file.
57
+ - `uid`: UID of uploaded file.
58
+ - `onDone`: Triggered when the upload is completed, returns `_event` object:
59
+ - `meta`:
60
+ - `bucket`: Name of bucket that the file was stored in.
61
+ - `filename`: Uploaded filename.
62
+ - `key`: Key under which the file is stored.
63
+ - `size`: Size of uploaded file.
64
+ - `type`: Type of uploaded file.
65
+ - `uid`: UID of uploaded file.
66
+ - `onError`: Triggered when an error occurs, returns `_event` object:
67
+ - `meta`:
68
+ - `bucket`: Name of bucket that the file was stored in.
69
+ - `filename`: Uploaded filename.
70
+ - `key`: Key under which the file is stored.
71
+ - `size`: Size of uploaded file.
72
+ - `type`: Type of uploaded file.
73
+ - `uid`: UID of uploaded file.
74
+
75
+ ### Examples
76
+
77
+ 1. File Upload and Download:
78
+
79
+ ```yaml
80
+ # .env secrets needed
81
+ LOWDEFY_SECRET_UPLOADS_S3_ACCESS_KEY_ID
82
+ LOWDEFY_SECRET_UPLOADS_S3_SECRET_ACCESS_KEY
83
+ LOWDEFY_SECRET_UPLOADS_S3_BUCKET
84
+ ```
85
+
86
+ ```yaml
87
+ # lowdefy.yaml
88
+ ...
89
+
90
+ connections:
91
+ - id: uploads_bucket
92
+ type: AwsS3Bucket
93
+ properties:
94
+ accessKeyId:
95
+ _secret: UPLOADS_S3_ACCESS_KEY_ID
96
+ secretAccessKey:
97
+ _secret: UPLOADS_S3_SECRET_ACCESS_KEY
98
+ region: af-south-1
99
+ bucket:
100
+ _secret: UPLOADS_S3_BUCKET
101
+ write: true
102
+
103
+ pages:
104
+ - id: s3_example_file_upload
105
+ type: PageHeaderMenu
106
+ properties:
107
+ title: S3 Example File Upload
108
+ layout:
109
+ contentGutter: 16
110
+
111
+ events:
112
+ onMount:
113
+ - id: set_state
114
+ type: SetState
115
+ params:
116
+ files: []
117
+
118
+ requests:
119
+ - id: upload_file
120
+ type: AwsS3PresignedPostPolicy
121
+ connectionId: uploads_bucket
122
+ payload:
123
+ key:
124
+ _state: file_uploader.file.name
125
+ properties:
126
+ key:
127
+ _payload: key
128
+ - id: download_file
129
+ type: AwsS3PresignedGetObject
130
+ connectionId: uploads_bucket
131
+ payload:
132
+ key:
133
+ _state: selected.key
134
+ responseContentType:
135
+ _state: selected.type
136
+ properties:
137
+ key:
138
+ _payload: key
139
+ responseContentType:
140
+ _payload: responseContentType
141
+
142
+ blocks:
143
+ - id: file_uploader_card
144
+ type: Card
145
+ properties:
146
+ title: Upload Files
147
+ blocks:
148
+ - id: file_uploader
149
+ type: S3UploadButton
150
+ properties:
151
+ s3PostPolicyRequestId: upload_file
152
+ button:
153
+ title: Upload
154
+ events:
155
+ onSuccess:
156
+ - id: set_state
157
+ type: SetState
158
+ params:
159
+ files:
160
+ _array.concat:
161
+ - _state: files
162
+ - - _event: meta
163
+
164
+ - id: file_card
165
+ type: Card
166
+ properties:
167
+ title: Files
168
+ blocks:
169
+ - id: files_table
170
+ type: AgGridAlpine
171
+ properties:
172
+ enableCellTextSelection: true
173
+ rowData:
174
+ _state: files
175
+ defaultColDef:
176
+ sortable: true
177
+ resizable: true
178
+ filter: true
179
+ columnDefs:
180
+ - headerName: filename
181
+ field: filename
182
+ - headerName: size
183
+ field: size
184
+ - headerName: type
185
+ field: type
186
+ events:
187
+ onRowClick:
188
+ - id: set_selected_id
189
+ type: SetState
190
+ params:
191
+ selected:
192
+ _event: row
193
+ - id: download_file
194
+ type: Request
195
+ params: download_file
196
+ - id: get_download_link
197
+ type: Link
198
+ messages:
199
+ error: Failed to open file. Check if popups are blocked in your browser.
200
+ params:
201
+ url:
202
+ _request: download_file
203
+ newTab: true
204
+ ```
205
+
206
+ 2. Photo Upload and Download:
207
+
208
+ ```yaml
209
+ # .env secrets needed
210
+ LOWDEFY_SECRET_UPLOADS_S3_ACCESS_KEY_ID
211
+ LOWDEFY_SECRET_UPLOADS_S3_SECRET_ACCESS_KEY
212
+ LOWDEFY_SECRET_UPLOADS_S3_BUCKET
213
+ ```
214
+
215
+ ```yaml
216
+ # lowdefy.yaml
217
+ ...
218
+ connections:
219
+ - id: uploads_bucket
220
+ type: AwsS3Bucket
221
+ properties:
222
+ accessKeyId:
223
+ _secret: UPLOADS_S3_ACCESS_KEY_ID
224
+ secretAccessKey:
225
+ _secret: UPLOADS_S3_SECRET_ACCESS_KEY
226
+ region: af-south-1
227
+ bucket:
228
+ _secret: UPLOADS_S3_BUCKET
229
+ write: true
230
+
231
+ pages:
232
+ - id: s3_example_photo_upload
233
+ type: PageHeaderMenu
234
+ properties:
235
+ title: S3 Example Photo Upload
236
+ layout:
237
+ contentGutter: 16
238
+
239
+ events:
240
+ onMount:
241
+ - id: set_state
242
+ type: SetState
243
+ params:
244
+ files: []
245
+
246
+ requests:
247
+ - id: upload_file
248
+ type: AwsS3PresignedPostPolicy
249
+ connectionId: uploads_bucket
250
+ payload:
251
+ key:
252
+ _state: file_uploader.file.name
253
+ properties:
254
+ key:
255
+ _payload: key
256
+ - id: download_file
257
+ type: AwsS3PresignedGetObject
258
+ connectionId: uploads_bucket
259
+ payload:
260
+ key:
261
+ _state: selected.key
262
+ responseContentType:
263
+ _state: selected.type
264
+ properties:
265
+ key:
266
+ _payload: key
267
+ responseContentType:
268
+ _payload: responseContentType
269
+
270
+ blocks:
271
+ - id: file_uploader_card
272
+ type: Card
273
+ properties:
274
+ title: Upload Files
275
+ blocks:
276
+ - id: file_uploader
277
+ type: S3UploadPhoto
278
+ properties:
279
+ s3PostPolicyRequestId: upload_file
280
+ button:
281
+ title: Upload
282
+ events:
283
+ onSuccess:
284
+ - id: set_state
285
+ type: SetState
286
+ params:
287
+ files:
288
+ _array.concat:
289
+ - _state: files
290
+ - - _event: meta
291
+
292
+ - id: file_card
293
+ type: Card
294
+ properties:
295
+ title: Files
296
+ blocks:
297
+ - id: files_table
298
+ type: AgGridAlpine
299
+ properties:
300
+ enableCellTextSelection: true
301
+ rowData:
302
+ _state: files
303
+ defaultColDef:
304
+ sortable: true
305
+ resizable: true
306
+ filter: true
307
+ columnDefs:
308
+ - headerName: filename
309
+ field: filename
310
+ - headerName: size
311
+ field: size
312
+ - headerName: type
313
+ field: type
314
+ events:
315
+ onRowClick:
316
+ - id: set_selected_id
317
+ type: SetState
318
+ params:
319
+ selected:
320
+ _event: row
321
+ - id: download_file
322
+ type: Request
323
+ params: download_file
324
+ - id: get_download_link
325
+ type: Link
326
+ messages:
327
+ error: Failed to open file. Check if popups are blocked in your browser.
328
+ params:
329
+ url:
330
+ _request: download_file
331
+ newTab: true
332
+ ```
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2020-2022 Lowdefy, Inc
2
+ Copyright 2020-2023 Lowdefy, Inc
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
@@ -38,8 +38,7 @@ const makeOnChangeValue = (s3Parameters, changeEvent)=>{
38
38
  const { file , fileList } = changeEvent;
39
39
  return {
40
40
  file: makeFileValue(file, s3Parameters),
41
- fileList: fileList.map((fl)=>makeFileValue(fl, s3Parameters)
42
- )
41
+ fileList: fileList.map((fl)=>makeFileValue(fl, s3Parameters))
43
42
  };
44
43
  };
45
44
  const getDisabled = ({ properties , value })=>{
@@ -66,6 +65,14 @@ const getCustomRequest = ({ methods , setS3Parameters })=>async ({ file , onErr
66
65
  }
67
66
  const { url , fields } = s3PostPolicyResponse.responses.__getS3PostPolicy.response[0];
68
67
  const { bucket , key } = fields;
68
+ const meta1 = {
69
+ bucket,
70
+ key,
71
+ filename: name,
72
+ size,
73
+ type,
74
+ uid
75
+ };
69
76
  setS3Parameters((prevState)=>{
70
77
  const ret = {
71
78
  ...prevState
@@ -88,23 +95,56 @@ const getCustomRequest = ({ methods , setS3Parameters })=>async ({ file , onErr
88
95
  // file needs to be the last field in the form
89
96
  formData.append('file', file);
90
97
  const xhr = new XMLHttpRequest();
91
- xhr.upload.onprogress = (event)=>{
92
- if (event.lengthComputable) {
98
+ xhr.upload.onprogress = (event1)=>{
99
+ if (event1.lengthComputable) {
93
100
  onProgress({
94
- percent: event.loaded / event.total * 80 + 20
101
+ percent: event1.loaded / event1.total * 80 + 20
95
102
  });
96
103
  }
97
104
  };
98
- xhr.addEventListener('error', onError);
99
- xhr.addEventListener('load', onSuccess);
105
+ xhr.addEventListener('error', async (event1)=>{
106
+ await methods.triggerEvent({
107
+ name: 'onError',
108
+ event: {
109
+ meta: meta1,
110
+ event: event1
111
+ }
112
+ });
113
+ onError(event1);
114
+ });
115
+ xhr.addEventListener('load', async (event1)=>{
116
+ await methods.triggerEvent({
117
+ name: 'onSuccess',
118
+ event: {
119
+ meta: meta1,
120
+ event: event1
121
+ }
122
+ });
123
+ onSuccess(event1);
124
+ });
125
+ xhr.addEventListener('loadend', async (event1)=>{
126
+ await methods.triggerEvent({
127
+ name: 'onDone',
128
+ event: {
129
+ meta: meta1,
130
+ event: event1
131
+ }
132
+ });
133
+ });
100
134
  xhr.open('post', url);
101
135
  xhr.send(formData);
102
136
  } catch (error) {
103
137
  console.error(error);
138
+ await methods.triggerEvent({
139
+ name: 'onError',
140
+ event: {
141
+ meta,
142
+ event
143
+ }
144
+ });
104
145
  onError(error);
105
146
  }
106
- }
107
- ;
147
+ };
108
148
  const S3UploadButtonBlock = ({ blockId , components , events , methods , properties , value })=>{
109
149
  // Use state here because we need to set s3 bucket and key as block value
110
150
  // The customRequest function does not have access to the updated block value,
@@ -129,7 +169,7 @@ const S3UploadButtonBlock = ({ blockId , components , events , methods , propert
129
169
  params: [
130
170
  properties.s3PostPolicyRequestId
131
171
  ]
132
- },
172
+ }
133
173
  ]
134
174
  });
135
175
  }, []);
@@ -137,15 +177,15 @@ const S3UploadButtonBlock = ({ blockId , components , events , methods , propert
137
177
  properties,
138
178
  value
139
179
  });
140
- return(/*#__PURE__*/ React.createElement(Upload, {
180
+ return /*#__PURE__*/ React.createElement(Upload, {
141
181
  accept: properties.accept,
142
182
  customRequest: customRequest,
143
183
  disabled: disabled,
144
184
  id: blockId,
145
185
  multiple: !properties.singleFile,
146
186
  showUploadList: properties.showUploadList,
147
- onChange: (event)=>{
148
- methods.setValue(makeOnChangeValue(s3Parameters, event));
187
+ onChange: (event1)=>{
188
+ methods.setValue(makeOnChangeValue(s3Parameters, event1));
149
189
  methods.triggerEvent({
150
190
  name: 'onChange'
151
191
  });
@@ -162,7 +202,7 @@ const S3UploadButtonBlock = ({ blockId , components , events , methods , propert
162
202
  ...properties.button
163
203
  },
164
204
  methods: methods
165
- })));
205
+ }));
166
206
  };
167
207
  S3UploadButtonBlock.defaultProps = blockDefaultProps;
168
208
  S3UploadButtonBlock.meta = {