some Item Popup Components ready to use

This commit is contained in:
Anton 2023-08-22 19:36:53 +02:00
parent 6bd062c1b3
commit a68d4951af
18 changed files with 143 additions and 73 deletions

View File

@ -26,6 +26,7 @@ const DialogModal = ({
onClose,
children,
}: Props) => {
const ref = useRef<HTMLDialogElement>(null);
useEffect(() => {

View File

@ -7,13 +7,14 @@ type InputTextProps = {
type?: string;
dataField?: string;
containerStyle?: string;
inputStyle?: string;
defaultValue?: string;
placeholder?: string;
updateFormValue?: (value: string ) => void;
}
export function TextInput({labelTitle, labelStyle, type, dataField, containerStyle, defaultValue, placeholder, updateFormValue} : InputTextProps){
export function TextInput({labelTitle, labelStyle, type, dataField, containerStyle, inputStyle, defaultValue, placeholder, updateFormValue} : InputTextProps){
return(
<div className={`tw-form-control tw-w-full ${containerStyle}`}>
@ -21,7 +22,7 @@ export function TextInput({labelTitle, labelStyle, type, dataField, containerSty
<span className={"tw-label-text tw-text-base-content " + labelStyle}>{labelTitle}</span>
</label>
: " "}
<input type={type || "text"} name={dataField} defaultValue={defaultValue} placeholder={placeholder || ""} onChange={(e) => updateFormValue&& updateFormValue(e.target.value)}className="tw-input tw-input-bordered tw-w-full " />
<input type={type || "text"} name={dataField} defaultValue={defaultValue} placeholder={placeholder || ""} onChange={(e) => updateFormValue&& updateFormValue(e.target.value)}className={`tw-input tw-input-bordered tw-w-full ${inputStyle ? inputStyle : ""}`} />
</div>
)
}

View File

@ -1,7 +1,14 @@
import * as React from 'react'
import { Item } from '../../types'
export const ItemForm = ({ children }:{children?: React.ReactNode}) => {
return (
<div>{children}</div>
)
export const ItemForm = ({ children, item }: { children?: React.ReactNode, item?: Item }) => {
return (
<div>{
children ?
React.Children.toArray(children).map((child) =>
React.isValidElement<{ item: Item, test: string }>(child) ?
React.cloneElement(child, { item: item, test: "test" }) : ""
) : ""
}</div>
)
}

View File

@ -1,7 +1,14 @@
import * as React from 'react'
import { Item } from '../../types'
export const ItemView = ({ children }:{children?: React.ReactNode}) => {
export const ItemView = ({ children, item }: { children?: React.ReactNode, item?: Item }) => {
return (
<div>{children}</div>
<div>
{children ?
React.Children.toArray(children).map((child) =>
React.isValidElement<{ item: Item, test: string }>(child) ?
React.cloneElement(child, { item: item, test: "test" }) : ""
) : ""}
</div>
)
}

View File

@ -88,12 +88,12 @@ export const Layer = (props: LayerProps) => {
<Marker icon={MarkerIconFactory(props.markerShape, color1, color2, props.markerIcon)} key={place.id} position={[place.position.coordinates[1], place.position.coordinates[0]]}>
{
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemForm") ?
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemView") ?
React.Children.toArray(props.children).map((child) =>
React.isValidElement(child) && typeof child.type !== "string" && child.type.name === "ItemView" ?
<ItemViewPopup key={place.id} item={place} setItemFormPopup={props.setItemFormPopup} >{child}</ItemViewPopup>
<ItemViewPopup key={place.id} item={place} setItemFormPopup={props.setItemFormPopup} >{child}</ItemViewPopup>
: ""
)
:
@ -106,7 +106,8 @@ export const Layer = (props: LayerProps) => {
);
})
}
{props.children}
{//{props.children}}
}
{props.itemFormPopup && props.itemFormPopup.layer!.name == props.name &&
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemForm") ?
React.Children.toArray(props.children).map((child) =>

View File

@ -85,9 +85,17 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
position={props.position}>
<form ref={formRef} onReset={resetPopup} onSubmit={e => handleSubmit(e)}>
<div className='tw-flex tw-justify-center'><b className="tw-text-xl tw-font-bold">New {props.layer.name}</b></div>
{props.children ? props.children :
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={props.item ? props.item.name : ""} inputStyle=''/>
{props.children ?
React.Children.toArray(props.children).map((child) =>
React.isValidElement<{ item: Item, test: string }>(child) ?
React.cloneElement(child, { item: props.item}) : ""
)
:
<>
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={props.item ? props.item.name : ""} />
<TextAreaInput placeholder="Text" dataField="text" defaultValue={props.item ? props.item.text : ""} inputStyle='tw-h-40 tw-mt-5' />
</>
}

View File

@ -1,9 +1,9 @@
import * as React from "react"
import { useRemoveItem } from "../hooks/useItems";
import { useRemoveItem } from "../../hooks/useItems";
import { useMap } from "react-leaflet";
import { ItemFormPopupProps } from "./ItemFormPopup";
import { ItemFormPopupProps } from "../ItemFormPopup";
import { LatLng } from "leaflet";
import { Item } from "../../../types";
import { Item } from "../../../../types";
@ -33,7 +33,7 @@ export function HeaderView({item, setItemFormPopup}: {
}
return (
<div className='tw-grid tw-grid-cols-6'>
<div className='tw-grid tw-grid-cols-6 tw-pb-2'>
<div className='tw-col-span-5'>
<b className="tw-text-xl tw-font-bold">{item.name}</b>
</div>

View File

@ -0,0 +1,12 @@
import * as React from 'react'
import { TextInput } from '../../../Input'
import { Item } from '../../../../types'
export const PopupStartEndInput = ({item}:{item?:Item}) => {
return (
<div className='tw-grid tw-grid-cols-2 tw-gap-2 tw-mb-5'>
<TextInput type='date' placeholder='start' dataField='start' inputStyle='tw-text-sm tw-px-2' labelTitle='start' defaultValue={item && item.start? item.start.substring(0, 10) : ""}></TextInput>
<TextInput type='date' placeholder='end' dataField='end' inputStyle='tw-text-sm tw-px-2' labelTitle='end' defaultValue={item && item.end ? item.end.substring(0, 10) : ""}></TextInput>
</div>
)
}

View File

@ -0,0 +1,16 @@
import * as React from 'react'
import { TextAreaInput } from '../../../Input'
import { Item } from '../../../../types'
export const PopupTextAreaInput = ({ dataField, placeholder, style, item }:
{
dataField: string,
placeholder: string,
style?: string,
item?: Item
}) => {
return (
<TextAreaInput defaultValue={item?.text ? item.text : ""} dataField={dataField} placeholder={placeholder} inputStyle={style}></TextAreaInput>
)
}

View File

@ -0,0 +1,7 @@
import * as React from 'react'
export const PopupTextInput = () => {
return (
<div>PopupTextInput</div>
)
}

View File

@ -0,0 +1,25 @@
import * as React from 'react'
import { Item } from '../../../../types'
export const StartEndView = ({item} : {item?:Item}) => {
return (
<div className="tw-flex tw-flex-row tw-mb-4 tw-mt-2">
<div className="tw-basis-2/5 tw-flex tw-flex-row">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-4 tw-w-4 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<time className='tw-align-middle' dateTime={item && item.start? item.start.substring(0, 10) : ""}>{item && item.start? new Date(item.start).toLocaleDateString(): ""}</time>
</div>
<div className="tw-basis-1/5 tw-place-content-center">
<span>-</span>
</div>
<div className="tw-basis-2/5 tw-flex tw-flex-row">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-4 tw-w-4 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<time className='tw-align-middle' dateTime={item && item.end? item.end.substring(0, 10) : ""}>{item && item.end ? new Date(item.end).toLocaleDateString() : ""}</time>
</div>
</div>
)
}

View File

@ -0,0 +1,14 @@
import * as React from 'react'
import { Item } from '../../../../types'
import { useTags } from '../../hooks/useTags';
import { replaceURLs } from '../../../../Utils/ReplaceURLs';
import { heighlightTags } from '../../../../Utils/HeighlightTags';
export const TextView = ({item} : {item?: Item}) => {
const all_tags = useTags();
return (
<p style={{ whiteSpace: "pre-wrap" }} className="!tw-m-0 !tw-mb-2" dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item && item.text ? item.text:"", all_tags)) }} />
)
}

View File

@ -2,9 +2,9 @@ import * as React from 'react'
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
import { Item } from '../../../types'
import { ItemFormPopupProps } from './ItemFormPopup'
import { HeaderView } from './HeaderView'
import StartEndView from './StartEndView'
import { TextView } from './TextView'
import { HeaderView } from './ItemPopupComponents/HeaderView'
import { StartEndView } from './ItemPopupComponents/StartEndView'
import { TextView } from './ItemPopupComponents/TextView'
export interface ItemViewPopupProps {
item: Item,
@ -21,13 +21,20 @@ export const ItemViewPopup = (props: ItemViewPopupProps) => {
<LeafletPopup maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 5]}>
<div>
<HeaderView item={props.item} setItemFormPopup={props.setItemFormPopup} />
{props.children ? props.children :
<div className='tw-overflow-y-auto tw-max-h-72'>
{item.start && item.end &&
<StartEndView item={props.item} />}
<div className='tw-overflow-y-auto tw-max-h-72'>
{props.children ?
React.Children.toArray(props.children).map((child) =>
React.isValidElement<{ item: Item, test: string }>(child) ?
React.cloneElement(child, { item: props.item }) : ""
)
:
<TextView item={props.item} />
</div>
}
}
</div>
</div>
</LeafletPopup>
)

View File

@ -1,26 +0,0 @@
import * as React from 'react'
import { Item } from '../../../types'
const StartEndView = ({item} : {item:Item}) => {
return (
<div className="tw-flex tw-flex-row">
<div className="tw-basis-2/5">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-6 tw-w-6 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span className='tw-align-middle'>{new Date(item.start!).toISOString().substring(0, 10) || ""}</span>
</div>
<div className="tw-basis-1/5 tw-place-content-center">
<span>-</span>
</div>
<div className="tw-basis-2/5">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-6 tw-w-6 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span className='tw-align-middle tw-leading-6'>{new Date(item.end!).toISOString().substring(0, 10) || ""}</span>
</div>
</div>
)
}
export default StartEndView

View File

@ -1,14 +0,0 @@
import * as React from 'react'
import { Item } from '../../../types'
import { useTags } from '../hooks/useTags';
import { replaceURLs } from '../../../Utils/ReplaceURLs';
import { heighlightTags } from '../../../Utils/HeighlightTags';
export const TextView = ({item} : {item: Item}) => {
const all_tags = useTags();
return (
<p style={{ whiteSpace: "pre-wrap" }} dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item.text, all_tags)) }} />
)
}

View File

@ -31,7 +31,7 @@ function MapEventListener(props: MapEventListenerProps) {
},
resize: () => {
console.log("resize");
}
})
return null
@ -57,14 +57,15 @@ function UtopiaMap({
<TagsProvider initialTags={[]}>
<ItemsProvider initialItems={[]}>
<div className={(selectMode != null ? "crosshair-cursor-enabled" : undefined)}>
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom}>
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://tile.osmand.net/hd/{z}/{x}/{y}.png" />
<MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50}>
{
React.Children.toArray(children).map((child) =>
React.isValidElement<{ setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps>>, itemFormPopup: ItemFormPopupProps | null }>(child) ? React.cloneElement(child, { setItemFormPopup: setItemFormPopup, itemFormPopup: itemFormPopup }) : child
React.isValidElement<{ setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps>>, itemFormPopup: ItemFormPopupProps | null }>(child) && typeof child.type !== "string" && child.type.name === "Layer" ?
React.cloneElement(child, { setItemFormPopup: setItemFormPopup, itemFormPopup: itemFormPopup }) : child
)
}
</MarkerClusterGroup>

View File

@ -1,6 +1,9 @@
export { UtopiaMap } from './UtopiaMap';
export { Layer } from './Layer';
export { Tags } from "./Tags";
export {ItemViewPopup} from './Subcomponents/ItemViewPopup';
export {ItemForm} from './ItemForm';
export {ItemView} from './ItemView';
export {ItemView} from './ItemView';
export {PopupTextAreaInput} from './Subcomponents/ItemPopupComponents/PopupTextAreaInput';
export {PopupStartEndInput} from './Subcomponents/ItemPopupComponents/PopupStartEndInput';
export {TextView} from './Subcomponents/ItemPopupComponents/TextView';
export {StartEndView} from './Subcomponents/ItemPopupComponents/StartEndView'

View File

@ -1,4 +1,4 @@
export { UtopiaMap, Layer, Tags, ItemViewPopup, ItemForm, ItemView } from './Components/Map/index';
export { UtopiaMap, Layer, Tags, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, TextView, StartEndView } from './Components/Map/index';
export {AppShell, Content, SideBar} from "./Components/AppShell"
export {AuthProvider, useAuth, LoginPage, SignupPage} from "./Components/Auth"
export {Settings} from './Components/Profile'