-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(services): add document service for upload and replace
This moves the file upload logic to a service but leaves the handling in the components for more control.
- Loading branch information
1 parent
dd8bc22
commit a1d0a2f
Showing
7 changed files
with
151 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import Service, { inject as service } from "@ember/service"; | ||
import fetch from "fetch"; | ||
|
||
export default class DocumentService extends Service { | ||
@service store; | ||
@service config; | ||
|
||
/** | ||
* Uploads one or multipl files and creates the necessary document and | ||
* files entries on the API. | ||
* | ||
* @param {Object|String|Number} category Either an ID or category instance. | ||
* @param {Array<File>} files The file(s) from input[type=file]. | ||
*/ | ||
async upload(category, files) { | ||
if (!category.id) { | ||
category = | ||
(await this.store.peekRecord("category", category)) || | ||
this.store.findRecord("category", category); | ||
} | ||
|
||
await Promise.all( | ||
Array.from(files).map(async (file) => { | ||
const documentModel = this.store.createRecord("document", { | ||
category, | ||
meta: this.config.defaultModelMeta.document, | ||
}); | ||
documentModel.title = file.name; | ||
await documentModel.save(); | ||
|
||
const fileModel = this.store.createRecord("file", { | ||
name: file.name, | ||
type: "original", | ||
document: documentModel, | ||
}); | ||
await fileModel.save(); | ||
|
||
const response = await fetch(fileModel.uploadUrl, { | ||
method: "PUT", | ||
body: file, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(response.statusText, response.status); | ||
} | ||
}) | ||
); | ||
} | ||
|
||
/** | ||
* Uploads a new version of a file and creates the necessary API entry. | ||
* | ||
* @param {Object} document A document instance. | ||
* @param {File} file The file from input[type=file]. | ||
*/ | ||
async replace(document, file) { | ||
const fileModel = this.store.createRecord("file", { | ||
name: file.name, | ||
type: "original", | ||
document, | ||
}); | ||
|
||
await fileModel.save(); | ||
|
||
const response = await fetch(fileModel.uploadUrl, { | ||
method: "PUT", | ||
body: file, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(response.statusText, response.status); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "ember-alexandria/services/document"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { setupMirage } from "ember-cli-mirage/test-support"; | ||
import { setupTest } from "ember-qunit"; | ||
import { module, test } from "qunit"; | ||
|
||
module("Unit | Service | document", function (hooks) { | ||
setupTest(hooks); | ||
setupMirage(hooks); | ||
|
||
test("it exists", function (assert) { | ||
const service = this.owner.lookup("service:document"); | ||
assert.ok(service); | ||
}); | ||
|
||
test("it uploads documents", async function (assert) { | ||
const requests = this.server.pretender.handledRequests; | ||
|
||
const service = this.owner.lookup("service:document"); | ||
|
||
const category = this.server.create("category"); | ||
const files = [ | ||
new File(["1"], "test1.docx"), | ||
new File(["2"], "test2.docx"), | ||
new File(["3"], "test3.docx"), | ||
]; | ||
|
||
await service.upload(category, files); | ||
|
||
// Each file generates three requests. | ||
assert.equal(requests.length, files.length * 3); | ||
|
||
// Files will be uploaded in parallel. So, we cannot know the order. | ||
const documentRequests = requests.filter((request) => | ||
request.url.endsWith("documents") | ||
); | ||
const fileRequests = requests.filter((request) => | ||
request.url.endsWith("files") | ||
); | ||
const uploadRequests = requests.filter((request) => | ||
request.url.endsWith("file-upload") | ||
); | ||
|
||
assert.equal(documentRequests.length, files.length); | ||
assert.equal(fileRequests.length, files.length); | ||
assert.equal(uploadRequests.length, files.length); | ||
}); | ||
|
||
test("it replaces documents", async function (assert) { | ||
const requests = this.server.pretender.handledRequests; | ||
|
||
const service = this.owner.lookup("service:document"); | ||
|
||
const document = this.server.create("document"); | ||
const file = new File([""], "test.docx"); | ||
|
||
await service.replace(document, file); | ||
|
||
assert.equal(requests.length, 2); | ||
assert.ok(requests[0].url.endsWith("files")); | ||
assert.ok(requests[1].url.endsWith("file-upload")); | ||
}); | ||
}); |