Merge pull request #45 from utopia-os/profile-fix

fix(other): fix some profile issues
This commit is contained in:
antontranelis 2024-11-22 13:33:07 +01:00 committed by GitHub
commit 5354daa402
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 108 additions and 84 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "utopia-ui", "name": "utopia-ui",
"version": "3.0.20", "version": "3.0.26",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "utopia-ui", "name": "utopia-ui",
"version": "3.0.20", "version": "3.0.26",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"dependencies": { "dependencies": {
"@heroicons/react": "^2.0.17", "@heroicons/react": "^2.0.17",

View File

@ -1,6 +1,6 @@
{ {
"name": "utopia-ui", "name": "utopia-ui",
"version": "3.0.20", "version": "3.0.26",
"description": "Reuseable React Components to build mapping apps for real life communities and networks", "description": "Reuseable React Components to build mapping apps for real life communities and networks",
"repository": "https://github.com/utopia-os/utopia-ui", "repository": "https://github.com/utopia-os/utopia-ui",
"homepage:": "https://utopia-os.org/", "homepage:": "https://utopia-os.org/",

View File

@ -13,6 +13,8 @@ type InputTextProps = {
defaultValue?: string defaultValue?: string
placeholder?: string placeholder?: string
autocomplete?: string autocomplete?: string
pattern?: string
required?: boolean
updateFormValue?: (value: string) => void updateFormValue?: (value: string) => void
} }
@ -26,6 +28,8 @@ export function TextInput({
defaultValue, defaultValue,
placeholder, placeholder,
autocomplete, autocomplete,
pattern,
required = true,
updateFormValue, updateFormValue,
}: InputTextProps) { }: InputTextProps) {
const [inputValue, setInputValue] = useState<string>(defaultValue || '') const [inputValue, setInputValue] = useState<string>(defaultValue || '')
@ -50,7 +54,8 @@ export function TextInput({
</label> </label>
) : null} ) : null}
<input <input
required required={required}
pattern={pattern}
type={type || 'text'} type={type || 'text'}
name={dataField} name={dataField}
value={inputValue} value={inputValue}

View File

@ -103,6 +103,7 @@ export function HeaderView({
<div className={`${avatar ? 'tw-ml-2' : ''} tw-overflow-hidden`}> <div className={`${avatar ? 'tw-ml-2' : ''} tw-overflow-hidden`}>
<div <div
className={`${big ? 'xl:tw-text-3xl tw-text-2xl' : 'tw-text-xl'} tw-font-semibold tw-truncate`} className={`${big ? 'xl:tw-text-3xl tw-text-2xl' : 'tw-text-xl'} tw-font-semibold tw-truncate`}
title={title}
> >
{title} {title}
</div> </div>

View File

@ -1,7 +1,5 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/restrict-plus-operands */ /* eslint-disable @typescript-eslint/restrict-plus-operands */
/* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-return */
@ -13,7 +11,7 @@ import remarkBreaks from 'remark-breaks'
import { useAddFilterTag } from '#components/Map/hooks/useFilter' import { useAddFilterTag } from '#components/Map/hooks/useFilter'
import { useTags } from '#components/Map/hooks/useTags' import { useTags } from '#components/Map/hooks/useTags'
import { Item } from '#src/types' import { Item, Tag } from '#src/types'
import { decodeTag } from '#utils/FormatTags' import { decodeTag } from '#utils/FormatTags'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
@ -76,47 +74,54 @@ export const TextView = ({
}) })
} }
// eslint-disable-next-line react/prop-types
const CustomH1 = ({ children }) => <h1 className='tw-text-xl tw-font-bold'>{children}</h1> const CustomH1 = ({ children }) => <h1 className='tw-text-xl tw-font-bold'>{children}</h1>
// eslint-disable-next-line react/prop-types
const CustomH2 = ({ children }) => <h2 className='tw-text-lg tw-font-bold'>{children}</h2> const CustomH2 = ({ children }) => <h2 className='tw-text-lg tw-font-bold'>{children}</h2>
// eslint-disable-next-line react/prop-types
const CustomH3 = ({ children }) => <h3 className='tw-text-base tw-font-bold'>{children}</h3> const CustomH3 = ({ children }) => <h3 className='tw-text-base tw-font-bold'>{children}</h3>
// eslint-disable-next-line react/prop-types
const CustomH4 = ({ children }) => <h4 className='tw-text-base tw-font-bold'>{children}</h4> const CustomH4 = ({ children }) => <h4 className='tw-text-base tw-font-bold'>{children}</h4>
// eslint-disable-next-line react/prop-types
const CustomH5 = ({ children }) => <h5 className='tw-text-sm tw-font-bold'>{children}</h5> const CustomH5 = ({ children }) => <h5 className='tw-text-sm tw-font-bold'>{children}</h5>
// eslint-disable-next-line react/prop-types
const CustomH6 = ({ children }) => <h6 className='tw-text-sm tw-font-bold'>{children}</h6> const CustomH6 = ({ children }) => <h6 className='tw-text-sm tw-font-bold'>{children}</h6>
// eslint-disable-next-line react/prop-types
const CustomParagraph = ({ children }) => <p className='!tw-my-2'>{children}</p> const CustomParagraph = ({ children }) => <p className='!tw-my-2'>{children}</p>
// eslint-disable-next-line react/prop-types
const CustomUnorderdList = ({ children }) => ( const CustomUnorderdList = ({ children }) => (
<ul className='tw-list-disc tw-list-inside'>{children}</ul> <ul className='tw-list-disc tw-list-inside'>{children}</ul>
) )
// eslint-disable-next-line react/prop-types
const CustomOrderdList = ({ children }) => ( const CustomOrderdList = ({ children }) => (
<ol className='tw-list-decimal tw-list-inside'>{children}</ol> <ol className='tw-list-decimal tw-list-inside'>{children}</ol>
) )
// eslint-disable-next-line react/prop-types
const CustomHorizontalRow = ({ children }) => <hr className='tw-border-current'>{children}</hr> const CustomHorizontalRow = ({ children }) => <hr className='tw-border-current'>{children}</hr>
// eslint-disable-next-line react/prop-types // eslint-disable-next-line react/prop-types
const CustomImage = ({ alt, src, title }) => ( const CustomImage = ({ alt, src, title }) => (
<img className='tw-max-w-full tw-rounded tw-shadow' src={src} alt={alt} title={title} /> <img className='tw-max-w-full tw-rounded tw-shadow' src={src} alt={alt} title={title} />
) )
// eslint-disable-next-line react/prop-types
const CustomExternalLink = ({ href, children }) => ( const CustomExternalLink = ({ href, children }) => (
<a className='tw-font-bold tw-underline' href={href} target='_blank' rel='noreferrer'> <a className='tw-font-bold tw-underline' href={href} target='_blank' rel='noreferrer'>
{' '} {' '}
{children} {children}
</a> </a>
) )
/* eslint-disable react/prop-types */
const CustomHashTagLink = ({ children, tag, item }) => { const CustomHashTagLink = ({
children,
tag,
item,
}: {
children: string
tag: Tag
item?: Item
}) => {
return ( return (
<a <a
style={{ color: tag ? tag.color : '#faa', fontWeight: 'bold', cursor: 'pointer' }} style={{ color: tag ? tag.color : '#faa', fontWeight: 'bold', cursor: 'pointer' }}
key={tag ? tag.name + item.id : item.id} key={tag ? tag.name + item?.id : item?.id}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
addFilterTag(tag) addFilterTag(tag)
@ -126,7 +131,6 @@ export const TextView = ({
</a> </a>
) )
} }
/* eslint-enable react/prop-types */
// eslint-disable-next-line react/display-name // eslint-disable-next-line react/display-name
const MemoizedVideoEmbed = memo(({ url }: { url: string }) => ( const MemoizedVideoEmbed = memo(({ url }: { url: string }) => (
@ -144,32 +148,34 @@ export const TextView = ({
remarkPlugins={[remarkBreaks]} remarkPlugins={[remarkBreaks]}
components={{ components={{
p: CustomParagraph, p: CustomParagraph,
a: ({ href, children }) => { a: ({ href, children }: { href: string; children: string }) => {
// eslint-disable-next-line react/prop-types
const isYouTubeVideo = href?.startsWith('https://www.youtube.com/watch?v=') const isYouTubeVideo = href?.startsWith('https://www.youtube.com/watch?v=')
// eslint-disable-next-line react/prop-types
const isRumbleVideo = href?.startsWith('https://rumble.com/embed/') const isRumbleVideo = href?.startsWith('https://rumble.com/embed/')
if (isYouTubeVideo) { if (isYouTubeVideo) {
// eslint-disable-next-line react/prop-types
const videoId = href?.split('v=')[1].split('&')[0] const videoId = href?.split('v=')[1].split('&')[0]
const youtubeEmbedUrl = `https://www.youtube-nocookie.com/embed/${videoId}` const youtubeEmbedUrl = `https://www.youtube-nocookie.com/embed/${videoId}`
return <MemoizedVideoEmbed url={youtubeEmbedUrl}></MemoizedVideoEmbed> return <MemoizedVideoEmbed url={youtubeEmbedUrl}></MemoizedVideoEmbed>
} }
if (isRumbleVideo) { if (isRumbleVideo) {
return <MemoizedVideoEmbed url={href!}></MemoizedVideoEmbed> return <MemoizedVideoEmbed url={href}></MemoizedVideoEmbed>
} }
// eslint-disable-next-line react/prop-types
if (href?.startsWith('#')) { if (href?.startsWith('#')) {
console.log(href.slice(1).toLowerCase())
console.log(tags)
const tag = tags.find( const tag = tags.find(
(t) => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase(), (t) => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase(),
) )
return ( if (tag)
<CustomHashTagLink tag={tag} item={item}> return (
{children} <CustomHashTagLink tag={tag} item={item}>
</CustomHashTagLink> {children}
) </CustomHashTagLink>
)
else return children
} else { } else {
return <CustomExternalLink href={href}>{children}</CustomExternalLink> return <CustomExternalLink href={href}>{children}</CustomExternalLink>
} }

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/restrict-template-expressions */
@ -148,58 +147,63 @@ export function ProfileForm() {
backdrop backdrop
className='tw-mx-4 tw-mt-4 tw-mb-4 tw-overflow-x-hidden tw-w-[calc(100%-32px)] md:tw-w-[calc(50%-32px)] tw-max-w-3xl !tw-left-auto tw-top-0 tw-bottom-0' className='tw-mx-4 tw-mt-4 tw-mb-4 tw-overflow-x-hidden tw-w-[calc(100%-32px)] md:tw-w-[calc(50%-32px)] tw-max-w-3xl !tw-left-auto tw-top-0 tw-bottom-0'
> >
<div className='tw-flex tw-flex-col tw-h-full'> <form
<FormHeader item={item} state={state} setState={setState} /> onSubmit={(e) => {
e.preventDefault()
void onUpdateItem(
state,
item,
tags,
addTag,
setLoading,
navigate,
updateItem,
addItem,
user,
urlParams,
)
}}
>
<div className='tw-flex tw-flex-col tw-h-full'>
<FormHeader item={item} state={state} setState={setState} />
{template === 'onepager' && ( {template === 'onepager' && (
<OnepagerForm item={item} state={state} setState={setState}></OnepagerForm> <OnepagerForm item={item} state={state} setState={setState}></OnepagerForm>
)} )}
{template === 'simple' && <SimpleForm state={state} setState={setState}></SimpleForm>} {template === 'simple' && <SimpleForm state={state} setState={setState}></SimpleForm>}
{template === 'flex' && ( {template === 'flex' && (
<FlexForm item={item} state={state} setState={setState}></FlexForm> <FlexForm item={item} state={state} setState={setState}></FlexForm>
)} )}
{template === 'tabs' && ( {template === 'tabs' && (
<TabsForm <TabsForm
loading={loading} loading={loading}
item={item} item={item}
state={state} state={state}
setState={setState} setState={setState}
updatePermission={updatePermission} updatePermission={updatePermission}
linkItem={(id) => linkItem(id, item, updateItem)} linkItem={(id) => linkItem(id, item, updateItem)}
unlinkItem={(id) => unlinkItem(id, item, updateItem)} unlinkItem={(id) => unlinkItem(id, item, updateItem)}
setUrlParams={setUrlParams} setUrlParams={setUrlParams}
></TabsForm> ></TabsForm>
)} )}
<div className='tw-mt-4'> <div className='tw-mt-4'>
<button <button
className={loading ? ' tw-loading tw-btn tw-float-right' : 'tw-btn tw-float-right'} className={loading ? ' tw-loading tw-btn tw-float-right' : 'tw-btn tw-float-right'}
onClick={() => type='submit'
onUpdateItem( style={{
state, backgroundColor: `${item.layer?.itemColorField && getValue(item, item.layer?.itemColorField) ? getValue(item, item.layer?.itemColorField) : getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : item?.layer?.markerDefaultColor}`,
item, color: '#fff',
tags, }}
addTag, >
setLoading, Update
navigate, </button>
updateItem, </div>
addItem,
user,
urlParams,
)
}
style={{
backgroundColor: `${item.layer?.itemColorField && getValue(item, item.layer?.itemColorField) ? getValue(item, item.layer?.itemColorField) : getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : item?.layer?.markerDefaultColor}`,
color: '#fff',
}}
>
Update
</button>
</div> </div>
</div> </form>
</MapOverlayPage> </MapOverlayPage>
</> </>
) )

View File

@ -22,6 +22,7 @@ export const ContactInfoForm = ({
<TextInput <TextInput
placeholder='Email' placeholder='Email'
type='email' type='email'
required={false}
defaultValue={state.contact} defaultValue={state.contact}
updateFormValue={(v) => updateFormValue={(v) =>
setState((prevState) => ({ setState((prevState) => ({
@ -41,6 +42,9 @@ export const ContactInfoForm = ({
</label> </label>
<TextInput <TextInput
placeholder='Telefonnummer' placeholder='Telefonnummer'
type='tel'
required={false}
pattern='^\+?[0-9\s\-]{7,15}$'
defaultValue={state.telephone} defaultValue={state.telephone}
updateFormValue={(v) => updateFormValue={(v) =>
setState((prevState) => ({ setState((prevState) => ({

View File

@ -44,6 +44,7 @@ export const FormHeader = ({ item, state, setState }) => {
/> />
<TextInput <TextInput
placeholder='Subtitle' placeholder='Subtitle'
required={false}
defaultValue={item?.subname ? item.subname : ''} defaultValue={item?.subname ? item.subname : ''}
updateFormValue={(v) => updateFormValue={(v) =>
setState((prevState) => ({ setState((prevState) => ({

View File

@ -30,13 +30,16 @@ export const GroupSubheaderForm = ({
useEffect(() => { useEffect(() => {
if (groupTypes && groupStates) { if (groupTypes && groupStates) {
const groupType = groupTypes.find((gt) => gt.groupTypes_id.name === state.group_type) const groupType = groupTypes.find((gt) => gt.groupTypes_id.name === state.group_type)
// eslint-disable-next-line no-console const customImage = !groupTypes.some(
console.log(state.group_type) (gt) => gt.groupTypes_id.image === state.image || !state.image,
)
setState((prevState) => ({ setState((prevState) => ({
...prevState, ...prevState,
color: groupType?.groupTypes_id.color || groupTypes[0].groupTypes_id.color, color: groupType?.groupTypes_id.color || groupTypes[0].groupTypes_id.color,
marker_icon: groupType?.groupTypes_id.markerIcon || groupTypes[0].groupTypes_id.markerIcon, marker_icon: groupType?.groupTypes_id.markerIcon || groupTypes[0].groupTypes_id.markerIcon,
image: groupType?.groupTypes_id.image || groupTypes[0].groupTypes_id.image, image: customImage
? state.image
: groupType?.groupTypes_id.image || groupTypes[0].groupTypes_id.image,
status: state.status || groupStates[0], status: state.status || groupStates[0],
group_type: state.group_type || groupTypes[0].groupTypes_id.name, group_type: state.group_type || groupTypes[0].groupTypes_id.name,
})) }))