feat: bundle assets with content (#2958)
* fix(media_folder_relative): use collection name in unpublished entry * refactor: pass arguments as object to AssetProxy ctor * feat: support media folders per collection * feat: resolve media files path based on entry path * fix: asset public path resolving * refactor: introduce typescript for AssetProxy * refactor: code cleanup * refactor(asset-proxy): add tests,switch to typescript,extract arguments * refactor: typescript for editorialWorkflow * refactor: add typescript for media library actions * refactor: fix type error on map set * refactor: move locale selector into reducer * refactor: add typescript for entries actions * refactor: remove duplication between asset store and media lib * feat: load assets from backend using API * refactor(github): add typescript, cache media files * fix: don't load media URL if already loaded * feat: add media folder config to collection * fix: load assets from API when not in UI state * feat: load entry media files when opening media library * fix: editorial workflow draft media files bug fixes * test(unit): fix unit tests * fix: editor control losing focus * style: add eslint object-shorthand rule * test(cypress): re-record mock data * fix: fix non github backends, large media * test: uncomment only in tests * fix(backend-test): add missing displayURL property * test(e2e): add media library tests * test(e2e): enable visual testing * test(e2e): add github backend media library tests * test(e2e): add git-gateway large media tests * chore: post rebase fixes * test: fix tests * test: fix tests * test(cypress): fix tests * docs: add media_folder docs * test(e2e): add media library delete test * test(e2e): try and fix image comparison on CI * ci: reduce test machines from 9 to 8 * test: add reducers and selectors unit tests * test(e2e): disable visual regression testing for now * test: add getAsset unit tests * refactor: use Asset class component instead of hooks * build: don't inline source maps * test: add more media path tests
This commit is contained in:
committed by
Shawn Erquhart
parent
7e4d4c1cc4
commit
2b41d8a838
@ -45,7 +45,7 @@ export default class API extends GithubAPI {
|
||||
return this.tokenPromise().then(jwtToken => {
|
||||
const baseHeader = {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
...headers,
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,10 @@ describe('github API', () => {
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
'https://site.netlify.com/.netlify/git/github/some-path?ts=1000',
|
||||
{
|
||||
headers: { Authorization: 'Bearer token', 'Content-Type': 'application/json' },
|
||||
headers: {
|
||||
Authorization: 'Bearer token',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ import GoTrue from 'gotrue-js';
|
||||
import jwtDecode from 'jwt-decode';
|
||||
import { fromPairs, get, pick, intersection, unzip } from 'lodash';
|
||||
import ini from 'ini';
|
||||
import { APIError, getBlobSHA, unsentRequest } from 'netlify-cms-lib-util';
|
||||
import { APIError, getBlobSHA, unsentRequest, basename } from 'netlify-cms-lib-util';
|
||||
import { GitHubBackend } from 'netlify-cms-backend-github';
|
||||
import { GitLabBackend } from 'netlify-cms-backend-gitlab';
|
||||
import { BitbucketBackend, API as BitBucketAPI } from 'netlify-cms-backend-bitbucket';
|
||||
@ -209,8 +209,37 @@ export default class GitGateway {
|
||||
return this.backend.getEntry(collection, slug, path);
|
||||
}
|
||||
|
||||
getMedia() {
|
||||
return Promise.all([this.backend.getMedia(), this.getLargeMediaClient()]).then(
|
||||
async loadEntryMediaFiles(files) {
|
||||
const client = await this.getLargeMediaClient();
|
||||
if (!client.enabled) {
|
||||
return this.backend.loadEntryMediaFiles(files);
|
||||
}
|
||||
|
||||
const mediaFiles = await Promise.all(
|
||||
files.map(async file => {
|
||||
if (client.matchPath(file.path)) {
|
||||
const { sha: id, path } = file;
|
||||
const largeMediaDisplayURLs = await this.getLargeMediaDisplayURLs([{ ...file, id }]);
|
||||
const url = await client.getDownloadURL(largeMediaDisplayURLs[id]);
|
||||
return {
|
||||
...file,
|
||||
id,
|
||||
name: basename(path),
|
||||
path,
|
||||
url,
|
||||
displayURL: url,
|
||||
};
|
||||
} else {
|
||||
return this.backend.loadMediaFile(file);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return mediaFiles;
|
||||
}
|
||||
|
||||
getMedia(mediaFolder = this.config.get('media_folder')) {
|
||||
return Promise.all([this.backend.getMedia(mediaFolder), this.getLargeMediaClient()]).then(
|
||||
async ([mediaFiles, largeMediaClient]) => {
|
||||
if (!largeMediaClient.enabled) {
|
||||
return mediaFiles.map(({ displayURL, ...rest }) => ({
|
||||
@ -218,6 +247,9 @@ export default class GitGateway {
|
||||
displayURL: { original: displayURL },
|
||||
}));
|
||||
}
|
||||
if (mediaFiles.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const largeMediaDisplayURLs = await this.getLargeMediaDisplayURLs(mediaFiles);
|
||||
return mediaFiles.map(({ id, displayURL, path, ...rest }) => {
|
||||
return {
|
||||
@ -339,6 +371,21 @@ export default class GitGateway {
|
||||
});
|
||||
}
|
||||
|
||||
async getMediaFile(path) {
|
||||
const client = await this.getLargeMediaClient();
|
||||
if (client.enabled && client.matchPath(path)) {
|
||||
const largeMediaDisplayURLs = await this.getLargeMediaDisplayURLs([{ path }]);
|
||||
const url = await client.getDownloadURL(Object.values(largeMediaDisplayURLs)[0]);
|
||||
return {
|
||||
name: basename(path),
|
||||
path,
|
||||
url,
|
||||
displayURL: url,
|
||||
};
|
||||
}
|
||||
return this.backend.getMediaFile(path);
|
||||
}
|
||||
|
||||
async getPointerFileForMediaFileObj(fileObj) {
|
||||
const client = await this.getLargeMediaClient();
|
||||
const { name, size } = fileObj;
|
||||
@ -419,10 +466,13 @@ export default class GitGateway {
|
||||
return this.backend.unpublishedEntries();
|
||||
}
|
||||
unpublishedEntry(collection, slug) {
|
||||
return (
|
||||
(this.backend.unpublishedEntry && this.backend.unpublishedEntry(collection, slug)) ||
|
||||
Promise.resolve(false)
|
||||
);
|
||||
if (!this.backend.unpublishedEntry) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return this.backend.unpublishedEntry(collection, slug, {
|
||||
loadEntryMediaFiles: files => this.loadEntryMediaFiles(files),
|
||||
});
|
||||
}
|
||||
updateUnpublishedEntryStatus(collection, slug, newStatus) {
|
||||
return this.backend.updateUnpublishedEntryStatus(collection, slug, newStatus);
|
||||
|
Reference in New Issue
Block a user