fix: media not displaying with local backend (#324)

This commit is contained in:
Daniel Lautzenheiser 2023-01-10 12:49:12 -05:00 committed by GitHub
parent a9e0770fd0
commit 9dba066ca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 69 additions and 69 deletions

View File

@ -1,17 +1,18 @@
backend:
name: github
branch: main
repo: owner/repo
media_folder: static/media
public_folder: /media
repo: staticjscms/static-cms-github
local_backend: true
media_folder: assets/upload
public_folder: /assets/upload
collections:
- name: posts
label: Posts
label_singular: Post
media_folder: /assets/posts
public_folder: /assets/posts
description: >
The description is a great place for tone setting, high level information,
and editing guidelines that are specific to a collection.
@ -94,8 +95,6 @@ collections:
- name: settings
label: Settings
delete: false
editor:
preview: false
files:
- name: general
label: Site Settings

View File

@ -11,29 +11,12 @@ const PostPreview = ({ entry, widgetFor, widgetsFor }) => {
);
};
const GeneralPreview = ({ widgetsFor, getAsset, entry }) => {
const GeneralPreview = ({ widgetsFor, entry, collection }) => {
const title = entry.data.site_title;
const posts = entry.data.posts;
const thumb = posts && posts.thumb;
const [thumbUrl, setThumbUrl] = useState('');
useEffect(() => {
let alive = true;
const loadThumb = async () => {
const thumbAsset = await getAsset(thumb);
if (alive) {
setThumbUrl(thumbAsset.toString());
}
};
loadThumb();
return () => {
alive = false;
};
}, [thumb]);
const thumbUrl = useMediaAsset(thumb, collection, undefined, entry);
return h(
'div',
@ -96,7 +79,6 @@ const CustomPage = () => {
return h('div', {}, 'I am a custom page!');
};
CMS.registerPreviewStyle('.toastui-editor-contents h1 { color: blue }', { raw: true });
CMS.registerPreviewTemplate('posts', PostPreview);
CMS.registerPreviewTemplate('general', GeneralPreview);
CMS.registerPreviewTemplate('authors', AuthorsPreview);

View File

@ -93,10 +93,6 @@ export function getAsset<F extends BaseField = UnknownField>(
dispatch: ThunkDispatch<RootState, {}, AnyAction>,
getState: () => RootState,
): Promise<AssetProxy> => {
if (!collection || !entry || !path) {
return Promise.resolve(emptyAsset);
}
const state = getState();
if (!state.config.config) {
return Promise.resolve(emptyAsset);

View File

@ -166,8 +166,12 @@ export default class ProxyBackend implements BackendClass {
return deserializeMediaFile(file);
}
getMediaDisplayURL(displayURL: DisplayURL) {
return Promise.resolve(typeof displayURL === 'string' ? displayURL : displayURL.id);
getMediaDisplayURL(displayURL: DisplayURL): Promise<string> {
if (typeof displayURL === 'string') {
return Promise.resolve(displayURL);
}
return Promise.resolve(displayURL.path);
}
async persistMedia(assetProxy: AssetProxy, options: PersistOptions) {

View File

@ -3,19 +3,20 @@ import CardActionArea from '@mui/material/CardActionArea';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import Typography from '@mui/material/Typography';
import React, { useEffect, useMemo, useState } from 'react';
import React, { useMemo } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { getAsset as getAssetAction } from '@staticcms/core/actions/media';
import { VIEW_STYLE_GRID, VIEW_STYLE_LIST } from '@staticcms/core/constants/collectionViews';
import useMediaAsset from '@staticcms/core/lib/hooks/useMediaAsset';
import { selectEntryCollectionTitle } from '@staticcms/core/lib/util/collection.util';
import { selectIsLoadingAsset } from '@staticcms/core/reducers/medias';
import type { ConnectedProps } from 'react-redux';
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
import type { Field, Collection, Entry } from '@staticcms/core/interface';
import type { Collection, Entry, Field } from '@staticcms/core/interface';
import type { RootState } from '@staticcms/core/store';
import type { ConnectedProps } from 'react-redux';
const EntryCard = ({
collection,
@ -25,22 +26,10 @@ const EntryCard = ({
imageField,
collectionLabel,
viewStyle = VIEW_STYLE_LIST,
getAsset,
}: NestedCollectionProps) => {
const summary = useMemo(() => selectEntryCollectionTitle(collection, entry), [collection, entry]);
const [imageUrl, setImageUrl] = useState<string>();
useEffect(() => {
if (!image) {
return;
}
const getImage = async () => {
setImageUrl((await getAsset(collection, entry, image, imageField)).toString());
};
getImage();
}, [collection, entry, getAsset, image, imageField]);
const imageUrl = useMediaAsset(image, collection, imageField, entry);
return (
<Card>
@ -84,8 +73,9 @@ function mapStateToProps(state: RootState, ownProps: EntryCardOwnProps) {
let image = inferedFields.imageField
? (entryData?.[inferedFields.imageField] as string | undefined)
: undefined;
if (image) {
image = encodeURI(image);
image = encodeURI(image.trim());
}
const isLoadingAsset = selectIsLoadingAsset(state.medias);

View File

@ -1,8 +1,9 @@
import { styled } from '@mui/material/styles';
import React, { useEffect, useMemo } from 'react';
import React, { useEffect } from 'react';
import { borders, colors, effects, lengths, shadows } from '@staticcms/core/components/UI/styles';
import { transientOptions } from '@staticcms/core/lib';
import useMediaAsset from '@staticcms/core/lib/hooks/useMediaAsset';
import transientOptions from '@staticcms/core/lib/util/transientOptions';
import type { MediaLibraryDisplayURL } from '@staticcms/core/reducers/mediaLibrary';
@ -104,7 +105,7 @@ const MediaLibraryCard = ({
isDraft,
loadDisplayURL,
}: MediaLibraryCardProps) => {
const url = useMemo(() => displayURL.url, [displayURL.url]);
const url = useMediaAsset(displayURL.url);
useEffect(() => {
if (!displayURL.url) {

View File

@ -2,15 +2,18 @@ import createReactClass from 'create-react-class';
import { createElement, useCallback, useEffect, useMemo, useState } from 'react';
import bootstrap from './bootstrap';
import useIsMediaAsset from './lib/hooks/useIsMediaAsset';
import useMediaAsset from './lib/hooks/useMediaAsset';
import useMediaInsert from './lib/hooks/useMediaInsert';
import useUUID from './lib/hooks/useUUID';
import Registry from './lib/registry';
export * from './backends';
export * from './widgets';
export * from './media-libraries';
export { default as locales } from './locales';
export * from './lib';
export * from './interface';
export * from './lib';
export { default as locales } from './locales';
export * from './media-libraries';
export * from './widgets';
const CMS = {
...Registry,
@ -25,6 +28,10 @@ if (typeof window !== 'undefined') {
window.useEffect = window.useEffect || useEffect;
window.useCallback = window.useCallback || useCallback;
window.h = window.h || createElement;
window.useIsMediaAsset = window.useIsMediaAsset || useIsMediaAsset;
window.useMediaAsset = window.useMediaAsset || useMediaAsset;
window.useMediaInsert = window.useMediaInsert || useMediaInsert;
window.useUUID = window.useUUID || useUUID;
}
export default CMS;

View File

@ -235,6 +235,9 @@ export interface DisplayURLState {
export type TranslatedProps<T> = T & ReactPolyglotTranslateProps;
/**
* @deprecated Should use `useMediaAsset` React hook instead
*/
export type GetAssetFunction<F extends BaseField = UnknownField> = (
path: string,
field?: F,
@ -248,6 +251,9 @@ export interface WidgetControlProps<T, F extends BaseField = UnknownField> {
fieldsErrors: FieldsErrors;
submitted: boolean;
forList: boolean;
/**
* @deprecated Should use `useMediaAsset` React hook instead
*/
getAsset: GetAssetFunction<F>;
isDisabled: boolean;
isFieldDuplicate: EditorControlProps['isFieldDuplicate'];
@ -273,6 +279,9 @@ export interface WidgetPreviewProps<T = unknown, F extends BaseField = UnknownFi
collection: Collection<F>;
entry: Entry;
field: RenderedField<F>;
/**
* @deprecated Should use `useMediaAsset` React hook instead
*/
getAsset: GetAssetFunction<F>;
value: T | undefined | null;
}
@ -300,6 +309,9 @@ export interface TemplatePreviewProps<T = EntryData, EF extends BaseField = Unkn
entry: Entry<T>;
document: Document | undefined | null;
window: Window | undefined | null;
/**
* @deprecated Should use `useMediaAsset` React hook instead
*/
getAsset: GetAssetFunction<Field<EF>>;
widgetFor: (name: T extends EntryData ? string : keyof T) => ReactNode;
widgetsFor: WidgetsFor<T>;

View File

@ -127,7 +127,7 @@ export function summaryFormatter(summaryTemplate: string, entry: Entry, collecti
export function folderFormatter(
folderTemplate: string,
entry: Entry | undefined,
entry: Entry | null | undefined,
collection: Collection,
defaultFolder: string,
folderKey: string,

View File

@ -4,18 +4,22 @@ import { getAsset } from '@staticcms/core/actions/media';
import { useAppDispatch } from '@staticcms/core/store/hooks';
import { isNotEmpty } from '../util/string.util';
import type { Collection, Entry, FileOrImageField, MarkdownField } from '@staticcms/core/interface';
import type { Field, Collection, Entry } from '@staticcms/core/interface';
export default function useMediaAsset<T extends FileOrImageField | MarkdownField>(
url: string,
collection: Collection<T>,
field: T,
entry: Entry,
export default function useMediaAsset<T extends Field>(
url: string | undefined,
collection?: Collection<T>,
field?: T,
entry?: Entry,
): string {
const dispatch = useAppDispatch();
const [assetSource, setAssetSource] = useState(url);
useEffect(() => {
if (!url) {
return;
}
const fetchMedia = async () => {
const asset = (await dispatch(getAsset<T>(collection, entry, url, field)))?.toString() ?? '';
setAssetSource(asset);
@ -24,5 +28,5 @@ export default function useMediaAsset<T extends FileOrImageField | MarkdownField
fetchMedia();
}, [collection, dispatch, entry, field, url]);
return isNotEmpty(assetSource) ? assetSource : url;
return isNotEmpty(assetSource) ? assetSource : url ?? '';
}

View File

@ -65,7 +65,7 @@ function evaluateFolder(
folderKey: 'media_folder' | 'public_folder',
config: Config,
c: Collection,
entryMap: Entry | undefined,
entryMap: Entry | null | undefined,
field: FileOrImageField | MarkdownField,
) {
let currentFolder = config[folderKey]!;
@ -158,7 +158,7 @@ function traverseFields(
folderKey: 'media_folder' | 'public_folder',
config: Config,
collection: Collection,
entryMap: Entry | undefined,
entryMap: Entry | null | undefined,
field: FileOrImageField | MarkdownField | ListField | ObjectField,
fields: Field[],
currentFolder: string,
@ -227,7 +227,7 @@ function traverseFields(
export function selectMediaFolder(
config: Config,
collection: Collection | undefined | null,
entryMap: Entry | undefined,
entryMap: Entry | null | undefined,
field: Field | undefined,
) {
const name = 'media_folder';
@ -279,7 +279,7 @@ export function selectMediaFilePublicPath(
export function selectMediaFilePath(
config: Config,
collection: Collection | null,
entryMap: Entry | undefined,
entryMap: Entry | null | undefined,
mediaPath: string,
field: Field | undefined,
) {

View File

@ -4,6 +4,7 @@ import type { Config } from '../interface';
import type CmsAPI from '../index';
import type createReactClass from 'create-react-class';
import type { createElement, useEffect, useState, useMemo, useCallback } from 'react';
import type { useIsMediaAsset, useMediaAsset, useMediaInsert, useUUID } from '../lib/hooks';
declare global {
interface Window {
@ -19,5 +20,9 @@ declare global {
useMemo: useMemo;
useEffect: useEffect;
useCallback: useCallback;
useIsMediaAsset: useIsMediaAsset;
useMediaAsset: useMediaAsset;
useMediaInsert: useMediaInsert;
useUUID: useUUID;
}
}