Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Custom upload #7

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 103 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ var editor = EditorJS({
personality: {
class: Personality,
config: {
endpoint: 'http://localhost:8008/uploadFile' // Your backend file uploader endpoint
endpoints: {
byFile: 'http://localhost:8008/uploadFile', // Your backend image file uploader endpoint
byUrl: 'http://localhost:8008/fetchUrl', // Your endpoint that provides uploading image by Url
}
}
}
}
Expand All @@ -71,12 +74,17 @@ Personality Tool supports these configuration parameters:

| Field | Type | Description |
| ----- | -------- | ------------------ |
| endpoint | `string` | **Required** Endpoint for photo uploading. |
| endpoints | `{byFile: string, byUrl: string}` | Endpoints for photo uploading. <br> Contains 2 fields: <br> __byFile__ - for file uploading <br> __byUrl__ - for uploading by URL |
| field | `string` | (default: `image`) Name of uploaded image field in POST request |
| types | `string` | (default: `image/*`) Mime-types of files that can be [accepted with file selection](https://github.com/codex-team/ajax#accept-string).|
| additionalRequestData | `object` | Object with any data you want to send with uploading requests |
| additionalRequestHeaders | `object` | Object with any custom headers which will be added to request. [See example](https://github.com/codex-team/ajax/blob/e5bc2a2391a18574c88b7ecd6508c29974c3e27f/README.md#headers-object) |
| namePlaceholder | `string` | (default: `Name`) Placeholder for name field |
| descriptionPlaceholder | `string` | (default: `Description`) Placeholder for description field |
| linkPlaceholder | `string` | (default: `Link`) Link field placeholder |
| uploader | `{{uploadByFile: function, uploadByUrl: function}}` | Optional custom uploading methods. See details below. |

Note that if you don't implement your custom uploader methods, the `endpoints` param is required.

## Output data

Expand All @@ -101,11 +109,7 @@ This Tool returns `data` with following format
}
```

## Backend response format <a name="server-format"></a>

This Tool works with uploading files from the device

**Scenario:**
Scenario:

1. User select file from the device
2. Tool sends it to **your** backend (on `config.endpoint.byFile` route)
Expand All @@ -121,11 +125,102 @@ Response of your uploader **should** cover following format:
{
"success" : 1,
"file": {
"url" : "https://capella.pics/3c0e1b97-bc56-4961-b54e-2a6c2c3260f2.jpg"
"url" : "https://capella.pics/3c0e1b97-bc56-4961-b54e-2a6c2c3260f2.jpg",
}
}
```

**success** - uploading status. 1 for successful, 0 for failed

**file** - uploaded file data. **Must** contain an `url` field with full public path to the uploaded image.

### Uploading by pasted URL

Scenario:

1. User pastes an URL of the image file to the Editor
2. Editor pass pasted string to the Image Tool
3. Tool sends it to **your** backend (on `config.endpoints.byUrl` route) via 'url' POST-parameter
3. Your backend should accept URL, **download and save the original file by passed URL** and return file data with JSON at specified format.
4. Personality tool shows saved image and stores server answer

Response of your uploader should be at the same format as described at «[Uploading files from device](#from-device)» section


### Uploading by drag-n-drop or from Clipboard

Your backend will accept file as FormData object in field name, specified by `config.field` (by default, «`image`»).
You should save it and return the same response format as described above.

## Providing custom uploading methods

As mentioned at the Config Params section, you have an ability to provide own custom uploading methods.
It is a quite simple: implement `uploadByFile` and `uploadByUrl` methods and pass them via `uploader` config param.
Both methods must return a Promise that resolves with response in format that described at the [backend response format](#server-format) section.


| Method | Arguments | Return value | Description |
| -------------- | --------- | -------------| ------------|
| uploadByFile | `File` | `{Promise.<{success, file: {url}}>}` | Upload file to the server and return an uploaded image data |
| uploadByUrl | `string` | `{Promise.<{success, file: {url}}>}` | Send URL-string to the server, that should load image by this URL and return an uploaded image data |

Example:

```js
import Personality from '@editorjs/personality';

var editor = EditorJS({
...

tools: {
...
personality: {
class: Personality,
config: {
/**
* Custom uploader
*/
uploader: {
/**
* Upload file to the server and return an uploaded image data
* @param {File} file - file selected from the device or pasted by drag-n-drop
* @return {Promise.<{success, file: {url}}>}
*/
uploadByFile(file){
// your own uploading logic here
return MyAjax.upload(file).then(() => {
return {
success: 1,
file: {
url: 'https://codex.so/upload/redactor_images/o_80beea670e49f04931ce9e3b2122ac70.jpg',
// any other image data you want to store, such as width, height, color, extension, etc
}
};
});
},

/**
* Send URL-string to the server. Backend should load image by this URL and return an uploaded image data
* @param {string} url - pasted image URL
* @return {Promise.<{success, file: {url}}>}
*/
uploadByUrl(url){
// your ajax request for uploading
return MyAjax.upload(file).then(() => {
return {
success: 1,
file: {
url: 'https://codex.so/upload/redactor_images/o_e48549d1855c7fc1807308dd14990126.jpg',,
// any other image data you want to store, such as width, height, color, extension, etc
}
}
})
}
}
}
}
}

...
});
```
2 changes: 1 addition & 1 deletion dist/bundle.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@
},
"homepage": "https://github.com/editor-js/personality#readme",
"devDependencies": {
"@babel/core": "^7.6.3",
"@babel/preset-env": "^7.6.3",
"@codexteam/ajax": "^4.0.1",
"babel-loader": "^8.0.6",
"css-loader": "^3.1.0",
"eslint": "^6.1.0",
"eslint-config-codex": "github:codex-team/eslint-config",
"eslint-loader": "^2.2.1",
"file-loader": "^4.1.0",
"formidable": "^1.2.1",
"postcss-loader": "^3.0.0",
"postcss-nested": "^4.1.2",
"request": "^2.88.0",
"style-loader": "^0.23.1",
Expand Down
25 changes: 17 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@ const LOADER_DELAY = 500;
/**
* @typedef {object} PersonalityConfig
* @description Config supported by Tool
* @property {string} endpoint - image file upload url
* @property {object} endpoints - upload endpoints
* @property {string} endpoints.byFile - upload by file
* @property {string} endpoints.byUrl - upload by URL
* @property {string} field - field name for uploaded image
* @property {string} types - available mime-types
* @property {string} namePlaceholder - placeholder for name field
* @property {string} descriptionPlaceholder - description placeholder
* @property {string} linkPlaceholder - link placeholder
* @property {object} additionalRequestData - any data to send with requests
* @property {object} additionalRequestHeaders - allows to pass custom headers with Request
* @property {object} [uploader] - optional custom uploader
* @property {function(File): Promise.<UploadResponseFormat>} [uploader.uploadByFile] - method that upload image by File
* @property {function(string): Promise.<UploadResponseFormat>} [uploader.uploadByUrl] - method that upload image by URL
*/

/**
Expand Down Expand Up @@ -58,12 +65,15 @@ export default class Personality {
};

this.config = {
endpoint: config.endpoint || '',
endpoints: config.endpoints || '',
additionalRequestData: config.additionalRequestData || {},
additionalRequestHeaders: config.additionalRequestHeaders || {},
field: config.field || 'image',
types: config.types || 'image/*',
namePlaceholder: config.namePlaceholder || 'Name',
descriptionPlaceholder: config.descriptionPlaceholder || 'Description',
linkPlaceholder: config.linkPlaceholder || 'Link'
linkPlaceholder: config.linkPlaceholder || 'Link',
uploader: config.uploader || undefined
};

/**
Expand Down Expand Up @@ -99,12 +109,11 @@ export default class Personality {
* @param {UploadResponseFormat} response
*/
onUpload(response) {
const { body: { success, file } } = response;

if (success && file && file.url) {
Object.assign(this.data, { photo: file.url });

if (response.success && response.file) {
Object.assign(this.data, { photo: response.file.url });
this.showFullImage();
} else {
this.uploadingFailed('Incorrect response: ' + JSON.stringify(response));
}
}

Expand Down
Loading