Merge branch 'main' into more-examples

This commit is contained in:
Ulf Gebhardt 2025-02-19 15:34:10 +01:00 committed by GitHub
commit c11de815e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 145 additions and 82 deletions

View File

@ -13,6 +13,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@types/geojson": "^7946.0.16",
"@types/react": "^18.3.18", "@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
@ -1270,6 +1271,13 @@
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"dev": true "dev": true
}, },
"node_modules/@types/geojson": {
"version": "7946.0.16",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/json-schema": { "node_modules/@types/json-schema": {
"version": "7.0.15", "version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",

View File

@ -16,6 +16,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@types/geojson": "^7946.0.16",
"@types/react": "^18.3.18", "@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",

View File

@ -1,6 +1,40 @@
import { UtopiaMap, Layer } from "utopia-ui" import { UtopiaMap, Layer } from "utopia-ui"
import { events, places } from "./sample-data" import { events, places } from "./sample-data"
const itemTypeEvent = {
name: "event",
show_name_input: false,
show_profile_button: false,
show_start_end: false,
show_start_end_input: false,
show_text: false,
show_text_input: false,
custom_text: "",
profileTemplate: [],
offers_and_needs: false,
icon_as_labels: null,
relations: false,
template: "TODO",
questlog: false,
}
const itemTypePlace = {
name: "event",
show_name_input: false,
show_profile_button: false,
show_start_end: false,
show_start_end_input: false,
show_text: false,
show_text_input: false,
custom_text: "",
profileTemplate: [],
offers_and_needs: false,
icon_as_labels: null,
relations: false,
template: "TODO",
questlog: false,
}
function App() { function App() {
return ( return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw"> <UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
@ -9,13 +43,23 @@ function App() {
markerIcon='calendar' markerIcon='calendar'
markerShape='square' markerShape='square'
markerDefaultColor='#700' markerDefaultColor='#700'
data={events} /> data={events}
menuIcon="calendar"
menuColor="#700"
menuText="events"
itemType={itemTypeEvent}
/>
<Layer <Layer
name='places' name='places'
markerIcon='point' markerIcon='point'
markerShape='circle' markerShape='circle'
markerDefaultColor='#007' markerDefaultColor='#007'
data={places} /> data={places}
menuIcon="point"
menuColor="#007"
menuText="places"
itemType={itemTypePlace}
/>
</UtopiaMap> </UtopiaMap>
) )
} }

View File

@ -1,22 +1,24 @@
import { Point } from "geojson";
export const places = [{ export const places = [{
"id": 51, "id": "51",
"name": "Stadtgemüse", "name": "Stadtgemüse",
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de", "text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] }, "position": { "type": "Point", "coordinates": [9.632435, 50.560342] } as Point,
}, },
{ {
"id": 166, "id": "166",
"name": "Weidendom", "name": "Weidendom",
"text": "free camping", "text": "free camping",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] }, "position": { "type": "Point", "coordinates": [9.438793, 50.560112] } as Point,
}]; }];
export const events = [ export const events = [
{ {
"id": 423, "id": "423",
"name": "Hackathon", "name": "Hackathon",
"text": "still in progress", "text": "still in progress",
"position": { "type": "Point", "coordinates": [10.5, 51.62] }, "position": { "type": "Point", "coordinates": [10.5, 51.62] } as Point,
"start": "2022-03-25T12:00:00", "start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00", "end": "2022-05-12T12:00:00",
} }

View File

@ -113,8 +113,8 @@
"imports": { "imports": {
"#components/*": "./src/Components/*", "#components/*": "./src/Components/*",
"#utils/*": "./src/Utils/*", "#utils/*": "./src/Utils/*",
"#types/*": "./src/types/*",
"#src/*": "./src/*", "#src/*": "./src/*",
"#types/*": "./types/*",
"#root/*": "./*" "#root/*": "./*"
} }
} }

View File

@ -76,17 +76,16 @@ export default [
], ],
}, },
{ {
input: 'src/index.tsx', input: 'dist/types/src/index.d.ts',
output: [{ file: 'dist/index.d.ts', format: 'es' }], output: [{ file: 'dist/index.d.ts', format: 'es' }],
plugins: [ plugins: [
aliasConfig, aliasConfig,
dts({ dts({
respectExternal: true,
compilerOptions: { compilerOptions: {
skipLibCheck: true, skipLibCheck: true,
}, },
}), }),
], ],
external: [/\.css$/, /\.d\.ts$/], // ✅ `.d.ts` als extern behandeln external: [/\.css$/], //, /\.d\.ts$/
}, },
] ]

View File

@ -4,6 +4,8 @@ import { SetAppState } from './SetAppState'
import type { AssetsApi } from '#types/AssetsApi' import type { AssetsApi } from '#types/AssetsApi'
export type { AssetsApi } from '#types/AssetsApi'
/** /**
* @category AppShell * @category AppShell
*/ */

View File

@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from 'react'
import { Link, useLocation } from 'react-router-dom' import { Link, useLocation } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth/useAuth'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import type { Item } from '#types/Item' import type { Item } from '#types/Item'

View File

@ -1,4 +1,4 @@
export { AppShell } from './AppShell' export * from './AppShell'
export { SideBar } from './SideBar' export { SideBar } from './SideBar'
export { Content } from './Content' export { Content } from './Content'
export { Sitemap } from './Sitemap' export { Sitemap } from './Sitemap'

View File

@ -1,4 +1,4 @@
export { AuthProvider, useAuth } from './useAuth' export { AuthProvider, UserApi, UserItem } from './useAuth'
export { LoginPage } from './LoginPage' export { LoginPage } from './LoginPage'
export { SignupPage } from './SignupPage' export { SignupPage } from './SignupPage'
export { RequestPasswordPage } from './RequestPasswordPage' export { RequestPasswordPage } from './RequestPasswordPage'

View File

@ -8,6 +8,9 @@ import { createContext, useState, useContext, useEffect } from 'react'
import type { UserApi } from '#types/UserApi' import type { UserApi } from '#types/UserApi'
import type { UserItem } from '#types/UserItem' import type { UserItem } from '#types/UserItem'
export type { UserApi } from '#types/UserApi'
export type { UserItem } from '#types/UserItem'
interface AuthProviderProps { interface AuthProviderProps {
userApi: UserApi userApi: UserApi
children?: React.ReactNode children?: React.ReactNode

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth/useAuth'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import { useQuestsOpen, useSetQuestOpen } from './hooks/useQuests' import { useQuestsOpen, useSetQuestOpen } from './hooks/useQuests'

View File

@ -27,6 +27,11 @@ import type { Tag } from '#types/Tag'
import type { Popup } from 'leaflet' import type { Popup } from 'leaflet'
import type { ReactElement, ReactNode } from 'react' import type { ReactElement, ReactNode } from 'react'
export type { Item } from '#types/Item'
export type { LayerProps } from '#types/LayerProps'
export type { Tag } from '#types/Tag'
export type { Popup } from 'leaflet'
/** /**
* @category Map * @category Map
*/ */

View File

@ -1,6 +1,6 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth/useAuth'
import { useSetPermissionData, useSetPermissionApi, useSetAdminRole } from './hooks/usePermissions' import { useSetPermissionData, useSetPermissionApi, useSetAdminRole } from './hooks/usePermissions'
@ -8,17 +8,20 @@ import type { ItemsApi } from '#types/ItemsApi'
import type { Permission } from '#types/Permission' import type { Permission } from '#types/Permission'
/** /**
* @category Map * @category Types
*/ */
export function Permissions({ export interface PermissionsProps {
data,
api,
adminRole,
}: {
data?: Permission[] data?: Permission[]
api?: ItemsApi<Permission> api?: ItemsApi<Permission>
adminRole?: string adminRole?: string
}) { }
export type { Permission } from '#types/Permission'
export type { ItemsApi } from '#types/ItemsApi'
/**
* @category Map
*/
export function Permissions({ data, api, adminRole }: PermissionsProps) {
const setPermissionData = useSetPermissionData() const setPermissionData = useSetPermissionData()
const setPermissionApi = useSetPermissionApi() const setPermissionApi = useSetPermissionApi()
const setAdminRole = useSetAdminRole() const setAdminRole = useSetAdminRole()

View File

@ -1,6 +1,6 @@
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth/useAuth'
export const GratitudeControl = () => { export const GratitudeControl = () => {
const navigate = useNavigate() const navigate = useNavigate()

View File

@ -27,12 +27,14 @@ export const TextView = ({
text, text,
truncate = false, truncate = false,
rawText, rawText,
itemTextField,
}: { }: {
item?: Item item?: Item
itemId: string itemId?: string
text?: string text?: string
truncate?: boolean truncate?: boolean
rawText?: string rawText?: string
itemTextField?: string
}) => { }) => {
if (item) { if (item) {
text = item.text text = item.text
@ -40,6 +42,8 @@ export const TextView = ({
} }
const tags = useTags() const tags = useTags()
const addFilterTag = useAddFilterTag() const addFilterTag = useAddFilterTag()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const itemTextFieldDummy = itemTextField
let innerText = '' let innerText = ''
let replacedText = '' let replacedText = ''
@ -125,7 +129,7 @@ export const TextView = ({
}: { }: {
children: string children: string
tag: Tag tag: Tag
itemId: string itemId?: string
}) => { }) => {
return ( return (
<a <a

View File

@ -1,7 +1,7 @@
export { UtopiaMap } from './UtopiaMap' export { UtopiaMap } from './UtopiaMap'
export { Layer } from './Layer' export * from './Layer'
export { Tags } from './Tags' export { Tags } from './Tags'
export { Permissions } from './Permissions' export * from './Permissions'
export { ItemForm } from './ItemForm' export { ItemForm } from './ItemForm'
export { ItemView } from './ItemView' export { ItemView } from './ItemView'
export { PopupTextAreaInput } from './Subcomponents/ItemPopupComponents/PopupTextAreaInput' export { PopupTextAreaInput } from './Subcomponents/ItemPopupComponents/PopupTextAreaInput'

View File

@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom' import { useLocation, useNavigate } from 'react-router-dom'
import { useAppState } from '#components/AppShell/hooks/useAppState' import { useAppState } from '#components/AppShell/hooks/useAppState'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth/useAuth'
import { useItems, useUpdateItem, useAddItem } from '#components/Map/hooks/useItems' import { useItems, useUpdateItem, useAddItem } from '#components/Map/hooks/useItems'
import { useLayers } from '#components/Map/hooks/useLayers' import { useLayers } from '#components/Map/hooks/useLayers'
import { useHasUserPermission } from '#components/Map/hooks/usePermissions' import { useHasUserPermission } from '#components/Map/hooks/usePermissions'

View File

@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth/useAuth'
import { TextInput } from '#components/Input' import { TextInput } from '#components/Input'
import { MapOverlayPage } from '#components/Templates' import { MapOverlayPage } from '#components/Templates'

View File

@ -1,4 +1,4 @@
export { UserSettings } from './UserSettings' export { UserSettings } from './UserSettings'
export { PlusButton } from './Subcomponents/PlusButton' // export { PlusButton } from './Subcomponents/PlusButton'
export { ProfileView } from './ProfileView' export { ProfileView } from './ProfileView'
export { ProfileForm } from './ProfileForm' export { ProfileForm } from './ProfileForm'

View File

@ -33,14 +33,18 @@ import type { Item } from '#types/Item'
export const OverlayItemsIndexPage = ({ export const OverlayItemsIndexPage = ({
url, url,
layerName, layerName,
parameterField,
plusButton = true, plusButton = true,
}: { }: {
layerName: string layerName: string
url: string url: string
parameterField?: string
plusButton?: boolean plusButton?: boolean
}) => { }) => {
const [loading, setLoading] = useState<boolean>(false) const [loading, setLoading] = useState<boolean>(false)
const [addItemPopupType, setAddItemPopupType] = useState<string>('') const [addItemPopupType, setAddItemPopupType] = useState<string>('')
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const parameterFieldDummy = parameterField
const tabRef = useRef<HTMLFormElement>(null) const tabRef = useRef<HTMLFormElement>(null)

View File

@ -1,43 +1,12 @@
import './index.css' import './index.css'
export { export * from './Components/Map'
UtopiaMap, export * from './Components/AppShell'
Layer, export * from './Components/Auth'
Tags, export * from './Components/Profile'
Permissions, export * from './Components/Gaming'
ItemForm, export * from './Components/Templates'
ItemView, export * from './Components/Input'
PopupTextAreaInput,
PopupStartEndInput,
PopupTextInput,
PopupButton,
TextView,
StartEndView,
PopupCheckboxInput,
} from './Components/Map'
export { AppShell, Content, SideBar, Sitemap } from './Components/AppShell'
export {
AuthProvider,
LoginPage,
SignupPage,
RequestPasswordPage,
SetNewPasswordPage,
} from './Components/Auth'
export { UserSettings, ProfileView, ProfileForm } from './Components/Profile'
export { Quests, Modal } from './Components/Gaming'
export {
TitleCard,
CardPage,
MapOverlayPage,
OverlayItemsIndexPage,
MoonCalendar,
SelectUser,
AttestationForm,
MarketView,
} from './Components/Templates'
export { TextInput, TextAreaInput, SelectBox } from './Components/Input'
export * from './types'
declare global { declare global {
interface Window { interface Window {

View File

@ -1,3 +1,6 @@
/**
* @category Types
*/
export interface AssetsApi { export interface AssetsApi {
upload(file: Blob, title: string): Promise<{ id: string }> upload(file: Blob, title: string): Promise<{ id: string }>
url: string url: string

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

@ -15,6 +15,9 @@ interface GalleryItem {
} }
} }
/**
* @category Types
*/
export interface Item { export interface Item {
id: string id: string
name: string name: string

View File

@ -2,14 +2,18 @@ import type { Key } from 'react'
export interface ItemType { export interface ItemType {
name: string name: string
show_name_input: boolean
show_profile_button: boolean
show_start_end: boolean show_start_end: boolean
show_start_end_input: boolean
show_text: boolean show_text: boolean
show_text_input: boolean
custom_text: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
profileTemplate: { collection: string | number; id: Key | null | undefined; item: any }[] profileTemplate: { collection: string | number; id: Key | null | undefined; item: any }[]
offers_and_needs: boolean offers_and_needs: boolean
icon_as_labels: unknown icon_as_labels: unknown
relations: boolean relations: boolean
template: string template: string
show_start_end_input: boolean
questlog: boolean questlog: boolean
} }

View File

@ -1,3 +1,6 @@
/**
* @category Types
*/
export interface ItemsApi<T> { export interface ItemsApi<T> {
getItems(): Promise<T[]> getItems(): Promise<T[]>
getItem?(id: string): Promise<T> getItem?(id: string): Promise<T>

View File

@ -3,6 +3,9 @@ import type { ItemFormPopupProps } from './ItemFormPopupProps'
import type { ItemsApi } from './ItemsApi' import type { ItemsApi } from './ItemsApi'
import type { ItemType } from './ItemType' import type { ItemType } from './ItemType'
/**
* @category Types
*/
export interface LayerProps { export interface LayerProps {
id?: string id?: string
data?: Item[] data?: Item[]

View File

@ -1,6 +1,9 @@
import type { PermissionAction } from './PermissionAction' import type { PermissionAction } from './PermissionAction'
import type { PermissionCondition } from './PermissionCondition' import type { PermissionCondition } from './PermissionCondition'
/**
* @category Types
*/
export interface Permission { export interface Permission {
id?: string id?: string
policy?: { name: string } policy?: { name: string }

3
src/types/Tag.d.ts vendored
View File

@ -1,3 +1,6 @@
/**
* @category Types
*/
export interface Tag { export interface Tag {
color: string color: string
id: string id: string

View File

@ -1,5 +1,8 @@
import type { UserItem } from './UserItem' import type { UserItem } from './UserItem'
/**
* @category Types
*/
export interface UserApi { export interface UserApi {
register(email: string, password: string, userName: string): Promise<void> register(email: string, password: string, userName: string): Promise<void>
login(email: string, password: string): Promise<UserItem | undefined> login(email: string, password: string): Promise<UserItem | undefined>

View File

@ -1,5 +1,8 @@
import type { Profile } from './Profile' import type { Profile } from './Profile'
/**
* @category Types
*/
export interface UserItem { export interface UserItem {
id?: string id?: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@ -1,9 +0,0 @@
export type { ItemsApi } from './ItemsApi'
export type { Tag } from './Tag'
export type { Item } from './Item'
export type { Permission } from './Permission'
export type { LayerProps } from './LayerProps'
export type { UserApi } from './UserApi'
export type { UserItem } from './UserItem'
export type { UtopiaMapProps } from './UtopiaMapProps'
export type { AssetsApi } from './AssetsApi'

View File

@ -22,15 +22,15 @@
"paths": { "paths": {
"#components/*": ["./src/Components/*"], "#components/*": ["./src/Components/*"],
"#utils/*": ["./src/Utils/*"], "#utils/*": ["./src/Utils/*"],
"#src/*": ["./src/*"],
"#types/*": ["./src/types/*"], "#types/*": ["./src/types/*"],
"#src/*": ["./src/*"],
"#root/*": ["./*"] "#root/*": ["./*"]
} }
}, },
"include": ["src", "vite.config.ts", "setupTest.ts", "cypress.config.ts", "cypress/support/commands.ts", "cypress/support/component.ts"], "include": ["src", "vite.config.ts", "setupTest.ts", "cypress.config.ts", "cypress/support/commands.ts", "cypress/support/component.ts"],
"exclude": ["node_modules", "dist", "example", "rollup.config.mjss"], "exclude": ["node_modules", "dist", "example", "rollup.config.mjss"],
"typeRoots": [ "typeRoots": [
"./types", "./src/types",
"./node_modules/@types/" "./node_modules/@types/"
] ]
} }