Skip to content
This repository has been archived by the owner on Sep 9, 2024. It is now read-only.

fix: media not displaying with local backend #324

Merged
merged 1 commit into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions packages/core/dev-test/backends/proxy/config.yml
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -94,8 +95,6 @@ collections:
- name: settings
label: Settings
delete: false
editor:
preview: false
files:
- name: general
label: Site Settings
Expand Down
22 changes: 2 additions & 20 deletions packages/core/dev-test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/actions/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/backends/proxy/implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
24 changes: 7 additions & 17 deletions packages/core/src/components/Collection/Entries/EntryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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>
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 12 additions & 5 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
12 changes: 12 additions & 0 deletions packages/core/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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'];
Expand All @@ -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;
}
Expand Down Expand Up @@ -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>;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/lib/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 11 additions & 7 deletions packages/core/src/lib/hooks/useMediaAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 ?? '';
}
8 changes: 4 additions & 4 deletions packages/core/src/lib/util/media.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]!;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -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,
) {
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -19,5 +20,9 @@ declare global {
useMemo: useMemo;
useEffect: useEffect;
useCallback: useCallback;
useIsMediaAsset: useIsMediaAsset;
useMediaAsset: useMediaAsset;
useMediaInsert: useMediaInsert;
useUUID: useUUID;
}
}