Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: upload dialog with configurable additional property fields #165

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f471fa3
FEATURE: add copyright notice to upload dialog
andrehoffmann30 Dec 15, 2022
1ca5ed9
FEATURE: make shown upload properties configurable
andrehoffmann30 Dec 16, 2022
e00fd51
TASK: assest replace dialog to handle additional upload properties
andrehoffmann30 Dec 19, 2022
f45045c
FEATURE: add media upload screen for content area
andrehoffmann30 Dec 20, 2022
e033705
TASK: adjust readme
andrehoffmann30 Dec 20, 2022
cee6c5a
TASK: rename media upload screen to asset upload screen
andrehoffmann30 Dec 21, 2022
519ea74
TASK: add pre build assets
andrehoffmann30 Dec 21, 2022
66cda1d
TASK: fixup after rebase
andrehoffmann30 Feb 10, 2023
b02c71e
TASK: refactor asset replace dialog and asset upload screen
andrehoffmann30 Feb 10, 2023
6966907
TASK: adjust handling of selected, uploaded and rejected files in upl…
andrehoffmann30 Jun 6, 2023
86a530b
TASK: rebase to latest release, refactor and fix code to work with la…
andrehoffmann30 Nov 10, 2023
2b1f31f
TASK: update build after rebase
andrehoffmann30 Nov 13, 2023
bca0fe5
TASK: fix linting errors
andrehoffmann30 Nov 13, 2023
a53e3ff
TASK: remove unneeded console.log
andrehoffmann30 Nov 14, 2023
652e833
TASK: adjust styling for preview section in upload dialog
andrehoffmann30 Nov 14, 2023
130634f
TASK: adjust line-hight for checkbox label in preview section
andrehoffmann30 Nov 14, 2023
3aad116
TASK: adjust and refactor changes according to review feedback
andrehoffmann30 Nov 20, 2023
66fb08d
TASK: add explanation in PropertyInstpector.tsx, adjust css imports f…
andrehoffmann30 Feb 19, 2024
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
47 changes: 46 additions & 1 deletion Classes/GraphQL/Resolver/Type/MutationResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,13 @@ public function uploadFile($_, array $variables): array
$file = $variables['file'];
$tagId = $variables['tagId'] ?? null;
$assetCollectionId = $variables['assetCollectionId'] ?? null;
$copyrightNotice = $variables['uploadProperties']['copyrightNotice'] ?? '';
$title = $variables['uploadProperties']['title'] ?? '';
$caption = $variables['uploadProperties']['caption'] ?? '';

$success = false;
$result = 'ERROR';
$assetUuid = '';

$filename = $file->getClientFilename();
try {
Expand All @@ -387,6 +391,16 @@ public function uploadFile($_, array $variables): array
$asset = new $className($resource);

if ($this->persistenceManager->isNewObject($asset)) {
if ($copyrightNotice !== '') {
$asset->setCopyrightNotice($copyrightNotice);
}
if ($title !== '') {
$asset->setTitle($title);
}
if ($caption !== '') {
$asset->setCaption($caption);
}

if ($tagId) {
/** @var Tag $tag */
$tag = $this->tagRepository->findByIdentifier($tagId);
Expand All @@ -408,6 +422,7 @@ public function uploadFile($_, array $variables): array
} else {
$result = 'EXISTS';
}
$assetUuid = $asset->getIdentifier();
} catch (IllegalObjectTypeException $e) {
$this->systemLogger->error('Type of uploaded file cannot be stored');
}
Expand All @@ -419,6 +434,7 @@ public function uploadFile($_, array $variables): array
'filename' => $filename,
'success' => $success,
'result' => $result,
'assetId' => $assetUuid,
];
}

Expand All @@ -431,6 +447,15 @@ public function uploadFiles($_, array $variables): array
{
/** @var array<FlowUploadedFile> $files */
$files = $variables['files'];
$uploadProperties = $variables['uploadProperties'];
$sortedUploadProperties = [];
foreach ($uploadProperties as $property) {
$sortedUploadProperties[$property['filename']] = [
'copyrightNotice' => $property['copyrightNotice'] ?? '',
'title' => $property['title'] ?? '',
'caption' => $property['caption'] ?? '',
];
}
$tagId = $variables['tagId'] ?? null;
$assetCollectionId = $variables['assetCollectionId'] ?? null;

Expand All @@ -440,6 +465,7 @@ public function uploadFiles($_, array $variables): array
'file' => $file,
'tagId' => $tagId,
'assetCollectionId' => $assetCollectionId,
'uploadProperties' => $sortedUploadProperties[$file->getClientFilename()] ?? '',
]);
}
return $results;
Expand All @@ -461,7 +487,8 @@ public function replaceAsset($_, array $variables, AssetSourceContext $assetSour
'options' => [
'generateRedirects' => $generateRedirects,
'keepOriginalFilename' => $keepOriginalFilename
]
],
'uploadProperties' => $uploadProperties
] = $variables;

$assetProxy = $assetSourceContext->getAssetProxy($id, $assetSourceId);
Expand All @@ -480,6 +507,7 @@ public function replaceAsset($_, array $variables, AssetSourceContext $assetSour

$success = false;
$result = 'ERROR';
$assetUuid = $asset->getIdentifier();
$sourceMediaType = MediaTypes::parseMediaType($asset->getMediaType());
$replacementMediaType = MediaTypes::parseMediaType($file->getClientMediaType());
$filename = $file->getClientFilename();
Expand All @@ -491,6 +519,7 @@ public function replaceAsset($_, array $variables, AssetSourceContext $assetSour
'filename' => $filename,
'success' => false,
'result' => $result,
'assetId' => $assetUuid,
];
}

Expand All @@ -510,8 +539,23 @@ public function replaceAsset($_, array $variables, AssetSourceContext $assetSour
'generateRedirects' => $generateRedirects,
'keepOriginalFilename' => $keepOriginalFilename
]);
$copyrightNotice = $uploadProperties['copyrightNotice'] ?? '';
$title = $uploadProperties['title'] ?? '';
$caption = $uploadProperties['caption'] ?? '';

if ($copyrightNotice !== '') {
$asset->setCopyrightNotice($copyrightNotice);
}
if ($title !== '') {
$asset->setTitle($title);
}
if ($caption !== '') {
$asset->setCaption($caption);
}

$success = true;
$result = 'REPLACED';
$assetUuid = $asset->getIdentifier();
} catch (\Exception $exception) {
$this->systemLogger->error(sprintf('Asset %s could not be replaced', $asset->getIdentifier()), [$exception]);
}
Expand All @@ -521,6 +565,7 @@ public function replaceAsset($_, array $variables, AssetSourceContext $assetSour
'filename' => $filename,
'success' => $success,
'result' => $result,
'assetId' => $assetUuid,
];
}

Expand Down
19 changes: 19 additions & 0 deletions Classes/GraphQL/Resolver/Type/QueryResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ public function config($_): array
'uploadMaxFileSize' => $this->getMaximumFileUploadSize(),
'uploadMaxFileUploadLimit' => $this->getMaximumFileUploadLimit(),
'currentServerTime' => (new \DateTime())->format(DATE_W3C),
'uploadProperties' => $this->getUploadProperties(),
];
}

Expand All @@ -208,6 +209,24 @@ protected function getMaximumFileUploadLimit(): int
return (int)($this->settings['maximumFileUploadLimit'] ?? 10);
}

/**
* Returns the additionally required fields for the file upload like the copyright notice
*
* @return string[]
*/
protected function getUploadProperties(): array
{
$data = [];
foreach ($this->settings['upload']['properties'] as $fieldName => $config) {
$data[] = [
'name' => $fieldName,
'show' => $config['show'] ?? false,
'required' => $config['required'] ?? false,
];
}
return $data;
}

/**
* Provides a filterable list of asset proxies. These are the main entities for media management.
*/
Expand Down
2 changes: 2 additions & 0 deletions Configuration/Settings.Features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Neos:
Ui:
frontendConfiguration:
Flowpack.Media.Ui:
# Use the new upload dialog where the user can add additional information like caption or copy right notice when uploading the asset
useNewAssetUpload: true
# 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
23 changes: 23 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,29 @@ Neos:
Flowpack.Media.Ui:
createAssetRedirectsOption: false
```

### Add additional field to the upload dialog

You can add additional fields to the upload dialog to add property data while uploading a file. Add the moment the fields title, caption and copyright notice can be used.
This additional the fields can be configured to be required for the upload. See the following settings example:


```yaml
Flowpack:
Media:
Ui:
upload:
properties:
copyrightNotice:
show: true
required: true
title:
show: true
required: false
caption:
show: true
required: false
```

## Architecture

Expand Down
18 changes: 17 additions & 1 deletion Resources/Private/GraphQL/schema.root.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type Mutation {
assetSourceId: AssetSourceId!
file: Upload!
options: AssetReplacementOptionsInput!
uploadProperties: UploadProperties
): FileUploadResult!

editAsset(
Expand All @@ -142,7 +143,7 @@ type Mutation {

uploadFile(file: Upload!, tagId: TagId, assetCollectionId: AssetCollectionId): FileUploadResult!

uploadFiles(files: [Upload!]!, tagId: TagId, assetCollectionId: AssetCollectionId): [FileUploadResult!]!
uploadFiles(files: [Upload!]!, tagId: TagId, assetCollectionId: AssetCollectionId, uploadProperties: [UploadProperties]): [FileUploadResult!]!

importAsset(id: AssetId!, assetSourceId: AssetSourceId!): Asset!

Expand All @@ -164,6 +165,13 @@ type Config {
uploadMaxFileSize: FileSize!
uploadMaxFileUploadLimit: Int!
currentServerTime: DateTime!
uploadProperties: [UploadPropertiesConfig]
}

type UploadPropertiesConfig {
name: String!
show: Boolean!
required: Boolean!
}

"""
Expand Down Expand Up @@ -335,6 +343,7 @@ type FileUploadResult {
filename: Filename!
success: Boolean!
result: String!
assetId: AssetId!
}

"""
Expand Down Expand Up @@ -517,6 +526,13 @@ Variant Name
"""
scalar VariantName

input UploadProperties {
filename: String!
copyrightNotice: String
title: String
caption: String
}

schema {
query: Query
mutation: Mutation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
type AssetCollectionType = 'AssetCollection';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface AssetCollection extends GraphQlEntity {
__typename: AssetCollectionType;
readonly id: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface TreeNodeProps {
title?: string;
label?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ type AssetSourceType = 'AssetSource';

type AssetSourceId = string;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface AssetSource extends GraphQlEntity {
__typename: AssetSourceType;
readonly id: AssetSourceId;
Expand Down
1 change: 1 addition & 0 deletions Resources/Private/JavaScript/asset-tags/typings/Tag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
type TagType = 'Tag';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Tag extends GraphQlEntity {
__typename: TagType;
id: string;
Expand Down
1 change: 1 addition & 0 deletions Resources/Private/JavaScript/asset-upload-screen/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This subpackage provides the media upload screen / secondary inspector for the Neos content module.
1 change: 1 addition & 0 deletions Resources/Private/JavaScript/asset-upload-screen/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src';
25 changes: 25 additions & 0 deletions Resources/Private/JavaScript/asset-upload-screen/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@media-ui/asset-upload-screen",
"version": "1.0.0",
"license": "GNU GPLv3",
"private": true,
"engines": {
"node": ">=12"
},
"dependencies": {
"@apollo/client": "^3.3.13",
"@media-ui/core": "workspace:*",
"@media-ui/feature-asset-upload": "workspace:*",
"@media-ui/media-module": "workspace:*",
"apollo-upload-client": "^14.1.3",
"react": "^17.0.2",
"react-redux": "^5.1.2",
"recoil": "^0.7.7"
},
"browserslist": [
"> 0.5%",
"last 2 versions",
"not dead",
"supports async-functions"
]
}
Loading