Skip to content

Commit

Permalink
[FEATURE] Adds validation for create tag dialog
Browse files Browse the repository at this point in the history
To prevent exceptions and make it more user friedly this change validated the tag creation form, so that you can not create an empty tag or a tag that already exists.
  • Loading branch information
markusguenther committed Oct 29, 2024
1 parent 9e91555 commit 4477493
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 3,363 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ const AddTagButton: React.FC = () => {
const selectedTagId = useRecoilValue(selectedTagIdState);

const onClickCreate = useCallback(() => {
setCreateTagDialogState({ label: '', visible: true });
setCreateTagDialogState({
visible: true,
label: '',
tags: [],
validation: {
valid: false,
errors: [],
},
});
}, [setCreateTagDialogState]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import * as React from 'react';
import { useCallback } from 'react';
import { useRecoilState } from 'recoil';

import { Button, Label, TextInput } from '@neos-project/react-ui-components';
import { Button, Label, TextInput, Tooltip } from '@neos-project/react-ui-components';

import TAGS from '../queries/tags';
import { useQuery } from '@apollo/client';
import { useIntl, useNotify } from '@media-ui/core';
import { useSelectedAssetCollection } from '@media-ui/feature-asset-collections';
import { useCreateTag } from '@media-ui/feature-asset-tags';
import { useCreateTag, useTagsQuery } from '@media-ui/feature-asset-tags';
import { Dialog } from '@media-ui/core/src/components';

import createTagDialogState from '../state/createTagDialogState';
Expand All @@ -18,10 +20,22 @@ const CreateTagDialog: React.FC = () => {
const Notify = useNotify();
const selectedAssetCollection = useSelectedAssetCollection();
const [dialogState, setDialogState] = useRecoilState(createTagDialogState);
const createPossible = !!(dialogState.label && dialogState.label.trim());
const { createTag } = useCreateTag();
const { tags } = useTagsQuery();

const handleRequestClose = useCallback(() => setDialogState({ visible: false, label: '' }), [setDialogState]);
const handleRequestClose = useCallback(
() =>
setDialogState({
visible: false,
label: '',
tags: [],
validation: {
valid: false,
errors: [],
},
}),
[setDialogState]
);
const handleCreate = useCallback(() => {
setDialogState((state) => ({ ...state, visible: false }));
createTag(dialogState.label, selectedAssetCollection?.id)
Expand All @@ -32,7 +46,32 @@ const CreateTagDialog: React.FC = () => {
Notify.error(translate('tagActions.create.error', 'Failed to create tag'), error.message);
});
}, [Notify, setDialogState, createTag, dialogState, translate, selectedAssetCollection]);
const setLabel = useCallback((label) => setDialogState((state) => ({ ...state, label })), [setDialogState]);
const validate = (label) => {
const validationErrors = [];
const trimmedLabel = label.trim();
const tagWithLabelExist = tags?.some((tag) => tag.label === trimmedLabel);

if (trimmedLabel.length === 0) {
validationErrors.push(translate('tagActions.validation.emtpyTagLabl', 'Please provide a tag label'));
}

if (tagWithLabelExist) {
validationErrors.push(translate('tagActions.validation.tagExists', 'A tag with this label already exists'));
}

const validation = {
errors: validationErrors,
valid: validationErrors.length === 0,
};
setDialogState((state) => ({ ...state, validation }));
};
const setLabel = useCallback(
(label) => {
validate(label);
setDialogState((state) => ({ ...state, label }));
},
[setDialogState]
);

return (
<Dialog
Expand All @@ -47,7 +86,7 @@ const CreateTagDialog: React.FC = () => {
key="upload"
style="success"
hoverStyle="success"
disabled={!createPossible}
disabled={!dialogState.validation?.valid}
onClick={handleCreate}
>
{translate('general.create', 'Create')}
Expand All @@ -58,11 +97,22 @@ const CreateTagDialog: React.FC = () => {
<Label>{translate('general.label', 'Label')}</Label>
<TextInput
setFocus
validationerrors={dialogState.validation?.valid ? null : ['This input is invalid']}
required={true}
type="text"
value={dialogState.label}
onChange={setLabel}
onEnterKey={createPossible ? handleCreate : null}
onEnterKey={dialogState.validation?.valid ? handleCreate : null}
/>
{dialogState.validation?.errors?.length > 0 && (
<Tooltip renderInline asError>
<ul>
{dialogState.validation.errors.map((error, index) => (
<li key={index}>{error}</li>
))}
</ul>
</Tooltip>
)}
</div>
</Dialog>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ const createTagDialogState = atom({
default: {
visible: false,
label: '',
tags: [],
validation: {
valid: false,
errors: [],
},
},
});

Expand Down
8 changes: 8 additions & 0 deletions Resources/Private/Translations/de/Main.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,14 @@
<source>Create tag</source>
<target>Tag erstellen</target>
</trans-unit>
<trans-unit id="tagActions.validation.emtpyTagLabl" xml:space="preserve" approved="yes">
<source>Please provide a tag label</source>
<target>Bitte geben Sie ein Tag-Title an</target>
</trans-unit>
<trans-unit id="tagActions.validation.tagExists" xml:space="preserve" approved="yes">
<source>This tag is already exists. Please choose a different one.</source>
<target>Dieses Tag existiert bereits. Bitte wählen Sie eine andere aus.</target>
</trans-unit>
<trans-unit id="tagActions.create.success" xml:space="preserve" approved="yes">
<source>Tag was created</source>
<target>Tag wurde erstellt</target>
Expand Down
6 changes: 6 additions & 0 deletions Resources/Private/Translations/en/Main.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@
<trans-unit id="tagActions.create.success" xml:space="preserve" approved="yes">
<source>Tag was created</source>
</trans-unit>
<trans-unit id="tagActions.validation.emtpyTagLabl" xml:space="preserve" approved="yes">
<source>Please provide a tag label</source>
</trans-unit>
<trans-unit id="tagActions.validation.tagExists" xml:space="preserve" approved="yes">
<source>This tag is already exists. Please choose a different one.</source>
</trans-unit>
<trans-unit id="tagActions.create.error" xml:space="preserve" approved="yes">
<source>Failed to create tag</source>
</trans-unit>
Expand Down
46 changes: 23 additions & 23 deletions Resources/Public/AssetEditor/Plugin.js

Large diffs are not rendered by default.

Loading

0 comments on commit 4477493

Please sign in to comment.