mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
Merge pull request #45 from utopia-os/profile-fix
fix(other): fix some profile issues
This commit is contained in:
commit
5354daa402
4
package-lock.json
generated
4
package-lock.json
generated
@ -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",
|
||||||
|
|||||||
@ -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/",
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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) => ({
|
||||||
|
|||||||
@ -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) => ({
|
||||||
|
|||||||
@ -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,
|
||||||
}))
|
}))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user