From 72d9732958702ab26a18a80400994b7f0c9d23d5 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Mon, 25 Feb 2019 23:01:49 +0700 Subject: [PATCH] Updated gh-uploader to work with new /images/upload/ endpoint --- ghost/admin/app/components/gh-uploader.js | 42 +++++++++++++++---- .../admin/app/templates/settings/general.hbs | 3 +- ghost/admin/mirage/config.js | 2 +- ghost/admin/mirage/config/uploads.js | 17 +++++--- .../tests/acceptance/settings/general-test.js | 2 +- .../components/gh-uploader-test.js | 14 +++---- 6 files changed, 57 insertions(+), 23 deletions(-) diff --git a/ghost/admin/app/components/gh-uploader.js b/ghost/admin/app/components/gh-uploader.js index 465887e8ba..0a54c4717c 100644 --- a/ghost/admin/app/components/gh-uploader.js +++ b/ghost/admin/app/components/gh-uploader.js @@ -3,7 +3,7 @@ import EmberObject from '@ember/object'; import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {all, task} from 'ember-concurrency'; import {get} from '@ember/object'; -import {isArray as isEmberArray} from '@ember/array'; +import {isArray} from '@ember/array'; import {isEmpty} from '@ember/utils'; import {run} from '@ember/runloop'; import {inject as service} from '@ember/service'; @@ -51,7 +51,9 @@ export default Component.extend({ accept: '', extensions: '', files: null, - paramName: 'uploadimage', // TODO: is this the best default? + paramName: 'file', + paramsHash: null, + resourceName: 'images', uploadUrl: null, // Interal attributes @@ -62,7 +64,7 @@ export default Component.extend({ uploadUrls: null, // [{filename: 'x', url: 'y'}], // Private - _defaultUploadUrl: '/images/', + _defaultUploadUrl: '/images/upload/', _files: null, _uploadTrackers: null, @@ -83,6 +85,10 @@ export default Component.extend({ this.set('errors', []); this.set('uploadUrls', []); this._uploadTrackers = []; + + if (!this.paramsHash) { + this.set('paramsHash', {purpose: 'image'}); + } }, didReceiveAttrs() { @@ -169,7 +175,7 @@ export default Component.extend({ return true; } - if (!isEmberArray(extensions)) { + if (!isArray(extensions)) { extensions = extensions.split(','); } @@ -240,10 +246,27 @@ export default Component.extend({ tracker.update({loaded: file.size, total: file.size}); this._updateProgress(); - let uploadResponse = JSON.parse(response); + let uploadResponse; + let responseUrl; + + try { + uploadResponse = JSON.parse(response); + } catch (e) { + if (!(e instanceof SyntaxError)) { + throw e; + } + } + + if (uploadResponse) { + let resource = get(uploadResponse, this.resourceName); + if (resource && isArray(resource) && resource[0]) { + responseUrl = get(resource[0], 'url'); + } + } + let result = { - fileName: file.name, - url: get(uploadResponse, 'url') + url: responseUrl, + fileName: file.name }; this.get('uploadUrls')[index] = result; @@ -274,6 +297,11 @@ export default Component.extend({ _getFormData(file) { let formData = new FormData(); formData.append(this.get('paramName'), file, file.name); + + Object.keys(this.paramsHash || {}).forEach((key) => { + formData.append(key, this.paramsHash[key]); + }); + return formData; }, diff --git a/ghost/admin/app/templates/settings/general.hbs b/ghost/admin/app/templates/settings/general.hbs index 68767657ce..487330d27b 100644 --- a/ghost/admin/app/templates/settings/general.hbs +++ b/ghost/admin/app/templates/settings/general.hbs @@ -95,7 +95,8 @@
{{#gh-uploader extensions=iconExtensions - uploadUrl="/images/icon/" + uploadUrl="/images/upload/" + paramsHash=(hash purpose="icon") onComplete=(action "imageUploaded" "icon") as |uploader| }} diff --git a/ghost/admin/mirage/config.js b/ghost/admin/mirage/config.js index 823725ef3e..792116b9aa 100644 --- a/ghost/admin/mirage/config.js +++ b/ghost/admin/mirage/config.js @@ -51,7 +51,7 @@ export function testConfig() { // this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server this.namespace = '/ghost/api/v2/admin'; // make this `api`, for example, if your API is namespaced // this.timing = 400; // delay for each request, automatically set to 0 during testing - this.logging = false; + this.logging = true; mockApiKeys(this); mockAuthentication(this); diff --git a/ghost/admin/mirage/config/uploads.js b/ghost/admin/mirage/config/uploads.js index c05ae164f4..de909e294c 100644 --- a/ghost/admin/mirage/config/uploads.js +++ b/ghost/admin/mirage/config/uploads.js @@ -1,5 +1,7 @@ const fileUploadResponse = function (db, {requestBody}) { - let [file] = requestBody.getAll('uploadimage'); + // let [ref] = requestBody.getAll('ref'); + let [purpose] = requestBody.getAll('purpose'); + let [file] = requestBody.getAll('file'); let now = new Date(); let year = now.getFullYear(); let month = `${now.getMonth()}`; @@ -8,12 +10,15 @@ const fileUploadResponse = function (db, {requestBody}) { month = `0${month}`; } - return { - url: `/content/images/${year}/${month}/${file.name}` - }; + if (['image', 'profile_image', 'icon'].includes(purpose)) { + return { + images: [{ + url: `/content/images/${year}/${month}/${file.name}` + }] + }; + } }; export default function mockUploads(server) { - server.post('/images/', fileUploadResponse, 200, {timing: 100}); - server.post('/images/icon/', fileUploadResponse, 200, {timing: 100}); + server.post('/images/upload/', fileUploadResponse, 200, {timing: 100}); } diff --git a/ghost/admin/tests/acceptance/settings/general-test.js b/ghost/admin/tests/acceptance/settings/general-test.js index 07140247aa..a640927e66 100644 --- a/ghost/admin/tests/acceptance/settings/general-test.js +++ b/ghost/admin/tests/acceptance/settings/general-test.js @@ -130,7 +130,7 @@ describe('Acceptance: Settings - General', function () { ).to.not.exist; // failed upload shows error - this.server.post('/images/icon/', function () { + this.server.post('/images/upload/', function () { return { errors: [{ errorType: 'ValidationError', diff --git a/ghost/admin/tests/integration/components/gh-uploader-test.js b/ghost/admin/tests/integration/components/gh-uploader-test.js index e74d0b20a3..623262635f 100644 --- a/ghost/admin/tests/integration/components/gh-uploader-test.js +++ b/ghost/admin/tests/integration/components/gh-uploader-test.js @@ -9,13 +9,13 @@ import {run} from '@ember/runloop'; import {setupRenderingTest} from 'ember-mocha'; const stubSuccessfulUpload = function (server, delay = 0) { - server.post('/ghost/api/v2/admin/images/', function () { - return [200, {'Content-Type': 'application/json'}, '{"url": "/content/images/test.png"}']; + server.post('/ghost/api/v2/admin/images/upload/', function () { + return [200, {'Content-Type': 'application/json'}, '{"images": [{"url": "/content/images/test.png"}]}']; }, delay); }; const stubFailedUpload = function (server, code, error, delay = 0) { - server.post('/ghost/api/v2/admin/images/', function () { + server.post('/ghost/api/v2/admin/images/upload/', function () { return [code, {'Content-Type': 'application/json'}, JSON.stringify({ errors: [{ errorType: error, @@ -51,11 +51,11 @@ describe('Integration: Component: gh-uploader', function () { let [lastRequest] = server.handledRequests; expect(server.handledRequests.length).to.equal(1); - expect(lastRequest.url).to.equal('/ghost/api/v2/admin/images/'); + expect(lastRequest.url).to.equal('/ghost/api/v2/admin/images/upload/'); // requestBody is a FormData object // this will fail in anything other than Chrome and Firefox // https://developer.mozilla.org/en-US/docs/Web/API/FormData#Browser_compatibility - expect(lastRequest.requestBody.has('uploadimage')).to.be.true; + expect(lastRequest.requestBody.has('file')).to.be.true; }); it('triggers multiple uploads', async function () { @@ -136,7 +136,7 @@ describe('Integration: Component: gh-uploader', function () { it('onComplete returns results in same order as selected', async function () { // first request has a delay to simulate larger file - server.post('/ghost/api/v2/admin/images/', function () { + server.post('/ghost/api/v2/admin/images/upload/', function () { // second request has no delay to simulate small file stubSuccessfulUpload(server, 0); @@ -266,7 +266,7 @@ describe('Integration: Component: gh-uploader', function () { it('uploads to supplied `uploadUrl`', async function () { server.post('/ghost/api/v2/admin/images/', function () { - return [200, {'Content-Type': 'application/json'}, '"/content/images/test.png"']; + return [200, {'Content-Type': 'application/json'}, '{"images": [{"url": "/content/images/test.png"}]']; }); await render(hbs`{{#gh-uploader files=files uploadUrl="/images/"}}{{/gh-uploader}}`);