Skip to content

Commit

Permalink
TASK: rebase to latest release, refactor and fix code to work with la…
Browse files Browse the repository at this point in the history
…test changes
  • Loading branch information
andrehoffmann30 committed Nov 10, 2023
1 parent fa60fd6 commit 94ddbc0
Show file tree
Hide file tree
Showing 41 changed files with 578 additions and 348 deletions.
6 changes: 1 addition & 5 deletions Configuration/Settings.Features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ Neos:
Ui:
frontendConfiguration:
Flowpack.Media.Ui:
useNewMediaSelection: true
# Use the new upload dialog where the user can add additional information like caption or copy right notice when uploading the asset
useNewAssetUpload: true
queryAssetUsage: false
pollForChanges: true
showSimilarAssets: false
showVariantsEditor: false
# Allow the user to let the system create redirects when assets are replaced or renamed
createAssetRedirectsOption: true
# Only allow a single asset collection selection per asset to treat collection like folders
Expand Down
12 changes: 12 additions & 0 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,15 @@ Flowpack:
Media:
Ui:
maximumFileUploadLimit: 10
# Configure which properties in the new upload dialog are show and which are required
upload:
properties:
copyrightNotice:
show: true
required: false
title:
show: true
required: false
caption:
show: true
required: false
20 changes: 9 additions & 11 deletions Resources/Private/JavaScript/asset-upload-screen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,18 @@
},
"dependencies": {
"@apollo/client": "^3.3.13",
"@media-ui/core": "*",
"@media-ui/feature-asset-upload": "*",
"@media-ui/media-module": "*",
"@media-ui/core": "workspace:*",
"@media-ui/feature-asset-upload": "workspace:*",
"@media-ui/media-module": "workspace:*",
"apollo-upload-client": "^14.1.3",
"plow-js": "^2.2.0",
"react": "^17.0.2",
"react-redux": "^5.1.2",
"react": "^17.0.1",
"recoil": "^0.2.0"
},
"devDependencies": {
"webpack": "^4.44.2",
"webpack-graphql-loader": "^1.0.2"
"recoil": "^0.7.7"
},
"browserslist": [
"defaults and > 1% and not ie <= 11"
"> 0.5%",
"last 2 versions",
"not dead",
"supports async-functions"
]
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,28 @@
import * as React from 'react';
import React, { createRef } from 'react';
import { connect } from 'react-redux';
import { RecoilRoot } from 'recoil';
import { ApolloClient, ApolloLink, ApolloProvider } from '@apollo/client';
import { ApolloClient, ApolloLink } from '@apollo/client';
import { createUploadLink } from 'apollo-upload-client';
import { $get, $transform } from 'plow-js';

// Neos dependencies are provided by the UI
// @ts-ignore
import { neos } from '@neos-project/neos-ui-decorators';
// @ts-ignore
import { actions } from '@neos-project/neos-ui-redux-store';

import {
I18nRegistry,
IntlProvider,
MediaUiProvider,
MediaUiThemeProvider,
Notify,
NotifyProvider,
} from '@media-ui/core/src';
import { FeatureFlags, SelectionConstraints } from '@media-ui/core/src/interfaces';
import { AssetMediaType } from '@media-ui/core/src/state/selectedMediaTypeState';
import { ApolloErrorHandler, CacheFactory, PersistentStateManager } from '@media-ui/media-module/src/core';

import TYPE_DEFS_CORE from '@media-ui/core/schema.graphql';
import TYPE_DEFS_CLIPBOARD from '@media-ui/feature-clipboard/schema.graphql';
import TYPE_DEFS_ASSET_USAGE from '@media-ui/feature-asset-usage/schema.graphql';

// GraphQL local resolvers
import buildClipboardResolver from '@media-ui/feature-clipboard/src/resolvers/mutation';
import buildModuleResolver from '@media-ui/media-module/src/resolvers/mutation';
import { createRef } from 'react';
import NewAssetUpload from './NewAssetUpload';

import { MediaUiProvider, typeDefs as TYPE_DEFS_CORE } from '@media-ui/core';
import MediaApplicationWrapper from '@media-ui/core/src/components/MediaApplicationWrapper';
import { CacheFactory, createErrorHandler } from '@media-ui/media-module/src/core';
import { typeDefs as TYPE_DEFS_ASSET_USAGE } from '@media-ui/feature-asset-usage';

let apolloClient = null;

interface AssetUploadScreenProps {
i18nRegistry: I18nRegistry;
frontendConfiguration: {
queryAssetUsage: boolean;
};
frontendConfiguration: FeatureFlags;
neos: Record<string, unknown>;
type: AssetMediaType | 'images'; // The image editor sets the type to 'images'
type: AssetType | 'images'; // The image editor sets the type to 'images'
onComplete: (result: { object: { __identity: string } }) => void;
isLeftSideBarHidden: boolean;
isNodeCreationDialogOpen: boolean;
Expand All @@ -55,23 +36,22 @@ interface AssetUploadScreenState {
initialNodeCreationDialogOpenState: boolean;
}

@connect(
$transform({
isLeftSideBarHidden: $get('ui.leftSideBar.isHidden'),
isNodeCreationDialogOpen: $get('ui.nodeCreationDialog.isOpen'),
}),
{
addFlashMessage: actions.UI.FlashMessages.add,
toggleSidebar: actions.UI.LeftSideBar.toggle,
}
)
@neos((globalRegistry) => ({
i18nRegistry: globalRegistry.get('i18n'),
frontendConfiguration: globalRegistry.get('frontendConfiguration').get('Flowpack.Media.Ui'),
}))
export class AssetUploadScreen extends React.PureComponent<AssetUploadScreenProps, AssetUploadScreenState> {
notificationHandler: NeosNotification;

constructor(props) {
super(props);
this.state = {
initialLeftSideBarHiddenState: false,
initialNodeCreationDialogOpenState: false,
};
this.notificationHandler = {
info: (message) => props.addFlashMessage(message, message, 'info'),
ok: (message) => props.addFlashMessage(message, message, 'success'),
notice: (message) => props.addFlashMessage(message, message, 'info'),
warning: (title, message = '') => props.addFlashMessage(title, message, 'error'),
error: (title, message = '') => props.addFlashMessage(title, message, 'error'),
};
}

getConfig() {
Expand All @@ -90,22 +70,17 @@ export class AssetUploadScreen extends React.PureComponent<AssetUploadScreenProp
if (!apolloClient) {
const { endpoints } = this.getConfig();
const cache = CacheFactory.createCache(this.props.frontendConfiguration as FeatureFlags);
PersistentStateManager.restoreLocalState(cache, this.props.constraints);

apolloClient = new ApolloClient({
cache,
link: ApolloLink.from([
ApolloErrorHandler,
createErrorHandler(this.notificationHandler),
createUploadLink({
uri: endpoints.graphql,
credentials: 'same-origin',
}),
]),
typeDefs: [TYPE_DEFS_CORE, TYPE_DEFS_CLIPBOARD, TYPE_DEFS_ASSET_USAGE],
resolvers: [
buildModuleResolver(PersistentStateManager.updateLocalState),
buildClipboardResolver(PersistentStateManager.updateLocalState),
],
typeDefs: [TYPE_DEFS_CORE, TYPE_DEFS_ASSET_USAGE],
});
}
return apolloClient;
Expand All @@ -121,45 +96,58 @@ export class AssetUploadScreen extends React.PureComponent<AssetUploadScreenProp
return this.props.i18nRegistry.translate(id, fallback, params, packageKey, sourceName);
};

getInitialState = () => {
const { frontendConfiguration, constraints, type } = this.props;

return {
applicationContext: 'selection' as ApplicationContext,
featureFlags: frontendConfiguration,
constraints: {
...(constraints || {}),
assetType: type === 'images' ? 'image' : type,
},
};
};

render() {
const { addFlashMessage, onComplete, constraints, type } = this.props;
const client = this.getApolloClient();
const { onComplete } = this.props;
const { dummyImage } = this.getConfig();
const containerRef = createRef<HTMLDivElement>();

const featureFlags: FeatureFlags = this.props.frontendConfiguration as FeatureFlags;

// The Neos.UI Flashmessages only support the levels 'success', 'error' and 'info'
const Notification: Notify = {
info: (message) => addFlashMessage(message, message, 'info'),
ok: (message) => addFlashMessage(message, message, 'success'),
notice: (message) => addFlashMessage(message, message, 'info'),
warning: (title, message = '') => addFlashMessage(title, message, 'error'),
error: (title, message = '') => addFlashMessage(title, message, 'error'),
};
const isInNodeCreationDialog = this.state.initialNodeCreationDialogOpenState;

return (
<div style={{ width: '100%', height: '100%', padding: '2rem' }}>
<IntlProvider translate={this.translate}>
<NotifyProvider notificationApi={Notification}>
<ApolloProvider client={client}>
<RecoilRoot>
<MediaUiProvider
dummyImage={dummyImage}
containerRef={containerRef}
featureFlags={featureFlags}
constraints={constraints || {}}
assetType={type === 'images' ? 'image' : type}
>
<MediaUiThemeProvider>
<NewAssetUpload onComplete={onComplete} />
</MediaUiThemeProvider>
</MediaUiProvider>
</RecoilRoot>
</ApolloProvider>
</NotifyProvider>
</IntlProvider>
<MediaApplicationWrapper
client={this.getApolloClient()}
translate={this.translate}
notificationApi={this.notificationHandler}
initialState={this.getInitialState()}
>
<MediaUiProvider
dummyImage={dummyImage}
selectionMode
isInNodeCreationDialog={isInNodeCreationDialog}
containerRef={containerRef}
>
<NewAssetUpload onComplete={onComplete} />
</MediaUiProvider>
</MediaApplicationWrapper>
</div>
);
}
}

const mapStateToProps = (state: any) => ({
isLeftSideBarHidden: state.ui.leftSideBar.isHidden,
isNodeCreationDialogOpen: state.ui.nodeCreationDialog.isOpen,
});

const mapGlobalRegistryToProps = neos((globalRegistry: any) => ({
i18nRegistry: globalRegistry.get('i18n'),
frontendConfiguration: globalRegistry.get('frontendConfiguration').get('Flowpack.Media.Ui'),
}));

export default connect(() => ({}), {
addFlashMessage: actions.UI.FlashMessages.add,
toggleSidebar: actions.UI.LeftSideBar.toggle,
})(connect(mapStateToProps)(mapGlobalRegistryToProps(AssetUploadScreen)));
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.uploadArea {
padding: 1rem;
}

.controls {
margin-top: 2rem;
display: flex;
justify-content: flex-end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,18 @@ import * as React from 'react';

import { Button } from '@neos-project/react-ui-components';

import { createUseMediaUiStyles, MediaUiTheme, useIntl, useNotify } from '@media-ui/core/src';
import { useIntl, useNotify } from '@media-ui/core/src';
import { useUploadDialogState, useUploadFiles } from '@media-ui/feature-asset-upload/src/hooks';
import { useCallback } from 'react';
import { FilesUploadState, UploadedFile } from '@media-ui/feature-asset-upload/src/interfaces';
import { PreviewSection, UploadSection } from '@media-ui/feature-asset-upload/src/components';

const useStyles = createUseMediaUiStyles((theme: MediaUiTheme) => ({
uploadArea: {
padding: theme.spacing.full,
},
controls: {
marginTop: '2rem',
display: 'flex',
justifyContent: 'flex-end',
},
}));
import { FilesUploadState, UploadedFile } from '@media-ui/feature-asset-upload/typings';
import classes from './NewAssetUpload.module.css';

const NewAssetUpload = (props: { onComplete: (result: { object: { __identity: string } }) => void }) => {
const { translate } = useIntl();
const Notify = useNotify();
const { uploadFiles, uploadState, loading } = useUploadFiles();
const { state: dialogState, setFiles, setUploadPossible } = useUploadDialogState();
const classes = useStyles();
const onComplete = props.onComplete;

const handleUpload = useCallback(() => {
Expand Down Expand Up @@ -62,6 +51,7 @@ const NewAssetUpload = (props: { onComplete: (result: { object: { __identity: st
);
} else {
Notify.ok(translate('uploadDialog.uploadFinished', 'Upload finished'));
console.log(uploadFiles);
onComplete({ object: { __identity: uploadFiles[0].assetId } });
}
setUploadPossible(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { AssetUploadScreen } from './AssetUploadScreen';
export { default as AssetUploadScreen } from './AssetUploadScreen';
5 changes: 2 additions & 3 deletions Resources/Private/JavaScript/asset-upload/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"private": true,
"main": "src/index.ts",
"dependencies": {
"@media-ui/core": "workspace:*"
"@media-ui/core": "*",
"@media-ui/media-module": "*"
"@media-ui/core": "workspace:*",
"@media-ui/media-module": "workspace:*"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import { useUploadDialogState, useUploadFiles } from '../../hooks';
import { useAssetsQuery } from '@media-ui/core/src/hooks';

import classes from './NewAssetDialog.module.css';
import { FilesUploadState, UploadedFile } from '../../../typings';

const NewAssetDialog: React.FC = () => {
const { translate } = useIntl();
const Notify = useNotify();
const { uploadFiles, uploadState, loading } = useUploadFiles();
const { state: dialogState, closeDialog, setFiles, setUploadPossible } = useUploadDialogState();
const { state: dialogState, closeDialog, setFiles } = useUploadDialogState();
const { refetch } = useAssetsQuery();

const handleUpload = useCallback(() => {
Expand Down Expand Up @@ -68,7 +68,16 @@ const NewAssetDialog: React.FC = () => {
.catch((error) => {
Notify.error(translate('fileUpload.error', 'Upload failed'), error);
});
}, [uploadFiles, dialogState.files.selected, setFiles, Notify, translate, refetch]);
}, [
dialogState.files.selected,
dialogState.files.finished,
uploadFiles,
setFiles,
setUploadPossible,
Notify,
translate,
refetch,
]);

const handleSetFiles = useCallback(
(files: UploadedFile[]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import UploadSection from '../UploadSection';
import PreviewSection from '../PreviewSection';
import { useUploadDialogState } from '../../hooks';
import useReplaceAsset, { AssetReplacementOptions } from '../../hooks/useReplaceAsset';
import { UploadedFile } from '../../interfaces';
import { useSetRecoilState } from 'recoil';

import classes from './ReplaceAssetDialog.module.css';
import { UploadedFile } from '../../../typings';
import {
selectedAssetLabelState,
selectedAssetCaptionState,
selectedAssetCopyrightNoticeState,
} from '@media-ui/media-module/src/state';

import classes from './ReplaceAssetDialog.module.css';

const ReplaceAssetDialog: React.FC = () => {
const { translate } = useIntl();
const Notify = useNotify();
Expand All @@ -37,11 +37,9 @@ const ReplaceAssetDialog: React.FC = () => {
keepOriginalFilename: false,
generateRedirects: false,
});
const classes = useStyles();
const setLabel = useSetRecoilState(selectedAssetLabelState);
const setCaption = useSetRecoilState(selectedAssetCaptionState);
const setCopyrightNotice = useSetRecoilState(selectedAssetCopyrightNoticeState);
const uploadPossible = !loading && dialogState.files.selected.length > 0;
const acceptedFileTypes = useMemo(() => {
// TODO: Extract this into a helper function
const completeMediaType = selectedAsset?.file.mediaType;
Expand Down
Loading

0 comments on commit 94ddbc0

Please sign in to comment.