diff --git a/public/locales/en/createCollection.json b/public/locales/en/createCollection.json index 2c701b242..8d14585af 100644 --- a/public/locales/en/createCollection.json +++ b/public/locales/en/createCollection.json @@ -7,9 +7,9 @@ "required": "Host Collection is required" }, "name": { - "label": "Dataverse Name", + "label": "Collection Name", "description": "The project, department, university, professor, or journal this collection will contain data for.", - "required": "Dataverse Name is required" + "required": "Collection Name is required" }, "affiliation": { "label": "Affiliation", @@ -22,7 +22,8 @@ "invalid": { "format": "Identifier is not a valid identifier. Valid characters are a-Z, 0-9, '_', and '-'.", "maxLength": "Identifier must be at most {{maxLength}} characters." - } + }, + "suggestion": "Psst... try this" }, "storage": { "label": "Storage", diff --git a/src/sections/create-collection/CreateCollection.tsx b/src/sections/create-collection/CreateCollection.tsx index 29561da9a..32eef981e 100644 --- a/src/sections/create-collection/CreateCollection.tsx +++ b/src/sections/create-collection/CreateCollection.tsx @@ -1,11 +1,12 @@ +import { useEffect } from 'react' +import { useTranslation } from 'react-i18next' import { useCollection } from '../collection/useCollection' import { CollectionRepository } from '../../collection/domain/repositories/CollectionRepository' -import { BreadcrumbsGenerator } from '../shared/hierarchy/BreadcrumbsGenerator' -import { useTranslation } from 'react-i18next' -import { RequiredFieldText } from '../shared/form/RequiredFieldText/RequiredFieldText' -import { CollectionForm, CollectionFormProps } from './collection-form' -import { useEffect } from 'react' import { useLoading } from '../loading/LoadingContext' +import { useSession } from '../session/SessionContext' +import { RequiredFieldText } from '../shared/form/RequiredFieldText/RequiredFieldText' +import { BreadcrumbsGenerator } from '../shared/hierarchy/BreadcrumbsGenerator' +import { CollectionForm, CollectionFormData } from './collection-form' interface CreateCollectionProps { ownerCollectionId: string @@ -18,14 +19,13 @@ export function CreateCollection({ }: CreateCollectionProps) { const { t } = useTranslation('createCollection') const { isLoading, setIsLoading } = useLoading() + const { user } = useSession() const { collection, isLoading: isLoadingCollection } = useCollection( collectionRepository, ownerCollectionId ) - console.log({ collection, isLoadingCollection }) - // TODO:ME If is not loading and collection is not found, show a message and navigate to the root collection // One good thing would be add toastify to show messages on top of the page for this kind of things @@ -44,15 +44,15 @@ export function CreateCollection({ return

Loading...

} // TODO:ME name = user name, affiliation = user affiliation, first email = user email - const formDefaultValues: CollectionFormProps['defaultValues'] = { - parentCollectionName: collection.name, - name: 'The Nameeeee', - alias: 'Some Alias', - type: 'Department', - contacts: [{ value: '' }], - affiliation: 'Some Affi', + const formDefaultValues: Partial = { + hostCollection: collection.name, + name: user?.displayName ? `${user?.displayName} Collection` : '', + alias: '', + type: undefined, + contacts: [{ value: user?.email ?? '' }], + affiliation: user?.affiliation ?? '', storage: 'Local (Default)', - description: 'Some Description' + description: '' } return ( diff --git a/src/sections/create-collection/collection-form/CollectionForm.module.scss b/src/sections/create-collection/collection-form/CollectionForm.module.scss index e67184332..a2fca1ed7 100644 --- a/src/sections/create-collection/collection-form/CollectionForm.module.scss +++ b/src/sections/create-collection/collection-form/CollectionForm.module.scss @@ -2,6 +2,35 @@ :global .input-group-text { font-size: 14px; } + + .suggestion-container { + display: flex; + gap: 0.5rem; + align-items: center; + width: 100%; + margin-top: -0.75rem; + margin-bottom: 1rem; + padding-top: 0.25rem; + + :global .form-text { + margin-top: 0; + } + + .apply-suggestion-btn { + display: grid; + place-items: center; + padding: 3px; + border-radius: 50%; + } + } +} + +.contact-row { + margin-bottom: 1rem; + + &:last-child { + margin-bottom: 0; + } } .dynamic-fields-button-container { diff --git a/src/sections/create-collection/collection-form/index.tsx b/src/sections/create-collection/collection-form/index.tsx index f91cb2703..613de998c 100644 --- a/src/sections/create-collection/collection-form/index.tsx +++ b/src/sections/create-collection/collection-form/index.tsx @@ -1,29 +1,31 @@ import { useRef } from 'react' import { FormProvider, useForm } from 'react-hook-form' -import { TopFieldsSection } from './top-fields-section' import { CollectionType, CollectionStorage } from '../../../collection/domain/useCases/DTOs/CollectionDTO' import { SeparationLine } from '../../shared/layout/SeparationLine/SeparationLine' +import { TopFieldsSection } from './top-fields-section' export interface CollectionFormProps { - defaultValues: { - parentCollectionName: string - name: string - affiliation?: string - alias: string - storage?: CollectionStorage - type: CollectionType - description?: string - contacts: { value: string }[] - } + defaultValues: Partial +} + +export type CollectionFormData = { + hostCollection: string + name: string + affiliation?: string + alias: string + storage?: CollectionStorage + type: CollectionType + description?: string + contacts: { value: string }[] } export const CollectionForm = ({ defaultValues }: CollectionFormProps) => { const formContainerRef = useRef(null) - const form = useForm({ + const form = useForm({ mode: 'onChange', defaultValues }) @@ -38,8 +40,8 @@ export const CollectionForm = ({ defaultValues }: CollectionFormProps) => { if (!isButton && !isButtonTypeSubmit) e.preventDefault() } - const submitForm = (formValues: any) => { - // console.log({ formValues }) + const submitForm = (formValues: CollectionFormData) => { + console.log({ formValues }) } function onSubmittedCollectionError() { diff --git a/src/sections/create-collection/collection-form/top-fields-section/ContactsField.tsx b/src/sections/create-collection/collection-form/top-fields-section/ContactsField.tsx index 1c32ac9dd..c53cdf5f2 100644 --- a/src/sections/create-collection/collection-form/top-fields-section/ContactsField.tsx +++ b/src/sections/create-collection/collection-form/top-fields-section/ContactsField.tsx @@ -56,7 +56,7 @@ export const ContactsField = ({ rules }: ContactsFieldProps) => { {(fieldsArray as { id: string; value: string }[]).map((field, index) => ( - + { + const { t } = useTranslation('createCollection') + const { control, setValue } = useFormContext() + const nameFieldValue = useWatch({ name: 'name' }) as string + + const collectionNameToAlias = (name: string) => { + if (!name) return '' + + return name + .toLowerCase() // Convert to lowercase + .trim() // Remove leading/trailing whitespace + .replace(/[^\w\s-]/g, '') // Remove non-alphanumeric characters except for spaces and hyphens + .replace(/[\s_-]+/g, '-') // Replace spaces and underscores with hyphens + .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens + } + + const aliasSuggestion = useMemo(() => collectionNameToAlias(nameFieldValue), [nameFieldValue]) + + const applyAliasSuggestion = () => + setValue('alias', aliasSuggestion, { shouldValidate: true, shouldDirty: true }) + + return ( + + + {t('fields.alias.label')} + + + ( + + + {window.location.origin}/spa/collections/ + + {error?.message} + + + {aliasSuggestion !== '' && value !== aliasSuggestion && !invalid && ( +
+ + {t('fields.alias.suggestion')} 👉 {aliasSuggestion} + + +
+ )} + + )} + /> +
+ ) +} diff --git a/src/sections/create-collection/collection-form/top-fields-section/index.tsx b/src/sections/create-collection/collection-form/top-fields-section/index.tsx index ff9dfffb0..7ae71f389 100644 --- a/src/sections/create-collection/collection-form/top-fields-section/index.tsx +++ b/src/sections/create-collection/collection-form/top-fields-section/index.tsx @@ -5,9 +5,9 @@ import { collectionTypeOptions, collectionStorageOptions } from '../../../../collection/domain/useCases/DTOs/CollectionDTO' -import { ContactsField } from './ContactsField' -import styles from '../CollectionForm.module.scss' import { Validator } from '../../../../shared/helpers/Validator' +import { ContactsField } from './ContactsField' +import { IdentifierField } from './IdentifierField' export const TopFieldsSection = () => { const { t } = useTranslation('createCollection') @@ -69,9 +69,6 @@ export const TopFieldsSection = () => { aria-required={true} ref={ref} disabled - // readOnly - // plaintext - // TODO:ME Check this, modify ds component? /> {error?.message} @@ -112,7 +109,6 @@ export const TopFieldsSection = () => { ( { {/* Identifier(alias) & Storage */} - - - {t('fields.alias.label')} - - ( - - - - {window.location.origin}/spa/collections/ - - - {error?.message} - - - )} - /> - + {t('fields.storage.label')} @@ -172,7 +135,6 @@ export const TopFieldsSection = () => { ( { {/* Category (type) & Description */} - + {t('fields.type.label')} { @@ -226,20 +189,18 @@ export const TopFieldsSection = () => { - + {t('fields.description.label')} ( {error?.message}