0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Updated gh-uploader to work with new /images/upload/ endpoint

This commit is contained in:
Kevin Ansfield 2019-02-25 23:01:49 +07:00
parent a0a0c50ff5
commit 72d9732958
6 changed files with 57 additions and 23 deletions

View file

@ -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;
},

View file

@ -95,7 +95,8 @@
<div class="gh-setting" data-test-setting="icon">
{{#gh-uploader
extensions=iconExtensions
uploadUrl="/images/icon/"
uploadUrl="/images/upload/"
paramsHash=(hash purpose="icon")
onComplete=(action "imageUploaded" "icon")
as |uploader|
}}

View file

@ -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);

View file

@ -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});
}

View file

@ -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',

View file

@ -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}}`);