refactor(source): get rid of item type (#142)

* started

* removed replaced itemType on all the places where it was used to identyfi the user profile layer

* removed unused property from NavBar

* removed unused property from AppShell

* removed userType from app state

* 3.0.60

* set version to 3.0.64 to publish package to include it in utopia-map

---------

Co-authored-by: Ulf Gebhardt <ulf.gebhardt@webcraft-media.de>
This commit is contained in:
Anton Tranelis 2025-02-20 11:04:05 +00:00 committed by GitHub
parent 27e4282624
commit 656fbb3ffc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 39 additions and 66 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "utopia-ui", "name": "utopia-ui",
"version": "3.0.59", "version": "3.0.60",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "utopia-ui", "name": "utopia-ui",
"version": "3.0.59", "version": "3.0.60",
"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.59", "version": "3.0.64",
"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,7 +13,6 @@ export function AppShell({
appName, appName,
children, children,
assetsApi, assetsApi,
userType,
}: { }: {
appName: string appName: string
children: React.ReactNode children: React.ReactNode
@ -23,8 +22,8 @@ export function AppShell({
return ( return (
<ContextWrapper> <ContextWrapper>
<div className='tw-flex tw-flex-col tw-h-full'> <div className='tw-flex tw-flex-col tw-h-full'>
<SetAppState assetsApi={assetsApi} userType={userType} /> <SetAppState assetsApi={assetsApi} />
<NavBar userType={userType} appName={appName}></NavBar> <NavBar appName={appName}></NavBar>
<div id='app-content' className='tw-flex-grow'> <div id='app-content' className='tw-flex-grow'>
{children} {children}
</div> </div>

View File

@ -8,7 +8,7 @@ import { useItems } from '#components/Map/hooks/useItems'
import type { Item } from '#types/Item' import type { Item } from '#types/Item'
export default function NavBar({ appName, userType }: { appName: string; userType: string }) { export default function NavBar({ appName }: { appName: string }) {
const { isAuthenticated, user, logout } = useAuth() const { isAuthenticated, user, logout } = useAuth()
const [userProfile, setUserProfile] = useState<Item>({} as Item) const [userProfile, setUserProfile] = useState<Item>({} as Item)
@ -16,12 +16,10 @@ export default function NavBar({ appName, userType }: { appName: string; userTyp
useEffect(() => { useEffect(() => {
const profile = const profile =
user && user && items.find((i) => i.user_created?.id === user.id && i.layer?.userProfileLayer)
items.find((i) => i.user_created?.id === user.id && i.layer?.itemType.name === userType)
profile profile
? setUserProfile(profile) ? setUserProfile(profile)
: setUserProfile({ id: crypto.randomUUID(), name: user?.first_name ?? '', text: '' }) : setUserProfile({ id: crypto.randomUUID(), name: user?.first_name ?? '', text: '' })
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user, items]) }, [user, items])
// useEffect(() => {}, [userProfile]) // useEffect(() => {}, [userProfile])

View File

@ -4,13 +4,7 @@ import { useSetAppState } from './hooks/useAppState'
import type { AssetsApi } from '#types/AssetsApi' import type { AssetsApi } from '#types/AssetsApi'
export const SetAppState = ({ export const SetAppState = ({ assetsApi }: { assetsApi: AssetsApi }) => {
assetsApi,
userType,
}: {
assetsApi: AssetsApi
userType: string
}) => {
const setAppState = useSetAppState() const setAppState = useSetAppState()
useEffect(() => { useEffect(() => {
@ -18,9 +12,5 @@ export const SetAppState = ({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [assetsApi]) }, [assetsApi])
useEffect(() => {
setAppState({ userType })
}, [setAppState, userType])
return <></> return <></>
} }

View File

@ -29,7 +29,7 @@ export function Quests() {
items.find( items.find(
(i) => (i) =>
i.user_created?.id === user?.id && i.user_created?.id === user?.id &&
i.layer?.itemType.name === 'user' && i.layer?.userProfileLayer &&
i.user_created?.id != null, i.user_created?.id != null,
), ),
) )

View File

@ -49,7 +49,7 @@ export const Layer = ({
markerDefaultColor2 = 'RGBA(35, 31, 32, 0.2)', markerDefaultColor2 = 'RGBA(35, 31, 32, 0.2)',
api, api,
itemType, itemType,
onlyOnePerOwner = false, userProfileLayer = false,
customEditLink, customEditLink,
customEditParameter, customEditParameter,
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
@ -101,7 +101,7 @@ export const Layer = ({
markerDefaultColor2, markerDefaultColor2,
api, api,
itemType, itemType,
onlyOnePerOwner, userProfileLayer,
// Can we just use editCallback for all cases? // Can we just use editCallback for all cases?
customEditLink, customEditLink,
customEditParameter, customEditParameter,
@ -127,7 +127,7 @@ export const Layer = ({
markerDefaultColor2, markerDefaultColor2,
api, api,
itemType, itemType,
onlyOnePerOwner, userProfileLayer,
customEditLink, customEditLink,
customEditParameter, customEditParameter,
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase

View File

@ -86,17 +86,16 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
map.closePopup() map.closePopup()
} else { } else {
const item = items.find( const item = items.find(
(i) => (i) => i.user_created?.id === user?.id && i.layer?.id === props.layer.id,
i.user_created?.id === user?.id && i.layer?.itemType.name === props.layer.itemType.name,
) )
const uuid = crypto.randomUUID() const uuid = crypto.randomUUID()
let success = false let success = false
try { try {
props.layer.onlyOnePerOwner && props.layer.userProfileLayer &&
item && item &&
(await props.layer.api?.updateItem!({ ...formItem, id: item.id })) (await props.layer.api?.updateItem!({ ...formItem, id: item.id }))
;(!props.layer.onlyOnePerOwner || !item) && ;(!props.layer.userProfileLayer || !item) &&
(await props.layer.api?.createItem!({ (await props.layer.api?.createItem!({
...formItem, ...formItem,
id: uuid, id: uuid,
@ -108,13 +107,12 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
toast.error(error.toString()) toast.error(error.toString())
} }
if (success) { if (success) {
if (props.layer.onlyOnePerOwner && item) updateItem({ ...item, ...formItem }) if (props.layer.userProfileLayer && item) updateItem({ ...item, ...formItem })
if (!props.layer.onlyOnePerOwner || !item) { if (!props.layer.userProfileLayer || !item) {
addItem({ addItem({
...formItem, ...formItem,
name: (formItem.name ? formItem.name : user?.first_name) ?? '', name: (formItem.name ? formItem.name : user?.first_name) ?? '',
user_created: user ?? undefined, user_created: user ?? undefined,
type: props.layer.itemType,
id: uuid, id: uuid,
layer: props.layer, layer: props.layer,
public_edit: !user, public_edit: !user,

View File

@ -60,9 +60,9 @@ export const ItemViewPopup = forwardRef((props: ItemViewPopupProps, ref: any) =>
setLoading(true) setLoading(true)
let success = false let success = false
try { try {
!props.item.layer?.onlyOnePerOwner && !props.item.layer?.userProfileLayer &&
(await props.item.layer?.api?.deleteItem!(props.item.id)) (await props.item.layer?.api?.deleteItem!(props.item.id))
props.item.layer?.onlyOnePerOwner && props.item.layer?.userProfileLayer &&
(await props.item.layer.api?.updateItem!({ id: props.item.id, position: null })) (await props.item.layer.api?.updateItem!({ id: props.item.id, position: null }))
success = true success = true
// eslint-disable-next-line no-catch-all/no-catch-all // eslint-disable-next-line no-catch-all/no-catch-all
@ -71,8 +71,8 @@ export const ItemViewPopup = forwardRef((props: ItemViewPopupProps, ref: any) =>
toast.error(error.toString()) toast.error(error.toString())
} }
if (success) { if (success) {
!props.item.layer?.onlyOnePerOwner && removeItem(props.item) !props.item.layer?.userProfileLayer && removeItem(props.item)
props.item.layer?.onlyOnePerOwner && updadateItem({ ...props.item, position: undefined }) props.item.layer?.userProfileLayer && updadateItem({ ...props.item, position: undefined })
toast.success('Item deleted') toast.success('Item deleted')
} }
setLoading(false) setLoading(false)

View File

@ -3,6 +3,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-argument */
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom' import { useLocation, useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { useAppState } from '#components/AppShell/hooks/useAppState' import { useAppState } from '#components/AppShell/hooks/useAppState'
import { useAuth } from '#components/Auth/useAuth' import { useAuth } from '#components/Auth/useAuth'
@ -76,14 +77,19 @@ export function ProfileForm() {
item && setItem(item) item && setItem(item)
if (!item) { if (!item) {
const layer = layers.find((l) => l.itemType.name === appState.userType) if (items.some((i) => i.user_created?.id === user?.id && i.layer?.userProfileLayer)) {
setItem({ navigate('/')
id: crypto.randomUUID(), toast.error('Item does not exist')
name: user?.first_name ?? '', } else {
text: '', const layer = layers.find((l) => l.userProfileLayer)
layer, setItem({
new: true, id: crypto.randomUUID(),
}) name: user?.first_name ?? '',
text: '',
layer,
new: true,
})
}
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps

View File

@ -16,24 +16,9 @@ export const ContactInfoView = ({ item, heading }: { item: Item; heading: string
const items = useItems() const items = useItems()
useEffect(() => { useEffect(() => {
// eslint-disable-next-line no-console
console.log(
'user:',
items.find(
(i) =>
i.user_created?.id === item.user_created?.id &&
i.layer?.itemType.name === appState.userType,
),
)
setProfileOwner( setProfileOwner(
items.find( items.find((i) => i.user_created?.id === item.user_created?.id && i.layer?.userProfileLayer),
(i) =>
i.user_created?.id === item.user_created?.id &&
i.layer?.itemType.name === appState.userType,
),
) )
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [item, items]) }, [item, items])
return ( return (

View File

@ -273,7 +273,6 @@ export const onUpdateItem = async (
...changedItem, ...changedItem,
layer: item.layer, layer: item.layer,
user_created: user, user_created: user,
type: item.layer?.itemType,
}), }),
) )
.then(() => { .then(() => {

View File

@ -76,7 +76,7 @@ export const AttestationForm = ({ api }: { api?: ItemsApi<unknown> }) => {
(i) => (i) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
i.user_created?.id === to[0].directus_users_id && i.user_created?.id === to[0].directus_users_id &&
i.layer?.itemType.name === 'player', i.layer?.userProfileLayer === true,
)?.id + )?.id +
'?tab=2', '?tab=2',
), ),

View File

@ -13,7 +13,7 @@ import { MapOverlayPage } from './MapOverlayPage'
export const SelectUser = () => { export const SelectUser = () => {
const appState = useAppState() const appState = useAppState()
const items = useItems() const items = useItems()
const users = items.filter((i) => i.layer?.itemType.name === appState.userType) const users = items.filter((i) => i.layer?.userProfileLayer)
const [selectedUsers, setSelectedUsers] = useState<string[]>([]) const [selectedUsers, setSelectedUsers] = useState<string[]>([])

2
src/types/Item.d.ts vendored
View File

@ -1,5 +1,4 @@
import type { ItemsApi } from './ItemsApi' import type { ItemsApi } from './ItemsApi'
import type { ItemType } from './ItemType'
import type { LayerProps } from './LayerProps' import type { LayerProps } from './LayerProps'
import type { Relation } from './Relation' import type { Relation } from './Relation'
import type { UserItem } from './UserItem' import type { UserItem } from './UserItem'
@ -50,7 +49,6 @@ export interface Item {
contact?: string contact?: string
telephone?: string telephone?: string
next_appointment?: string next_appointment?: string
type?: ItemType
gallery?: GalleryItem[] gallery?: GalleryItem[]
// { // {

View File

@ -21,7 +21,7 @@ export interface LayerProps {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
api?: ItemsApi<any> api?: ItemsApi<any>
itemType: ItemType itemType: ItemType
onlyOnePerOwner?: boolean userProfileLayer?: boolean
customEditLink?: string customEditLink?: string
customEditParameter?: string customEditParameter?: string
public_edit_items?: boolean public_edit_items?: boolean