mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
Modularization of Item Popups
This commit is contained in:
parent
77f7e36a5d
commit
4fe4aa6b74
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 68 KiB |
@ -31,16 +31,18 @@ const DialogModal = ({
|
||||
useEffect(() => {
|
||||
if (isOpened) {
|
||||
ref.current?.showModal();
|
||||
ref.current?.classList.remove("tw-hidden");
|
||||
document.body.classList.add("modal-open"); // prevent bg scroll
|
||||
} else {
|
||||
ref.current?.close();
|
||||
ref.current?.classList.add("tw-hidden");
|
||||
document.body.classList.remove("modal-open");
|
||||
}
|
||||
}, [isOpened]);
|
||||
|
||||
|
||||
return (
|
||||
<dialog id="signup_modal" className='tw-card tw-shadow-xl tw-absolute tw-right-0 tw-top-0 tw-bottom-0 tw-left-0 tw-m-auto tw-transition-opacity tw-duration-300'
|
||||
<dialog className='tw-card tw-shadow-xl tw-absolute tw-right-0 tw-top-0 tw-bottom-0 tw-left-0 tw-m-auto tw-transition-opacity tw-duration-300'
|
||||
|
||||
ref={ref}
|
||||
onCancel={onClose}
|
||||
|
||||
@ -3,9 +3,10 @@ import * as React from "react"
|
||||
|
||||
|
||||
type TextAreaProps = {
|
||||
labelTitle: string;
|
||||
labelTitle?: string;
|
||||
labelStyle?: string;
|
||||
containerStyle?: string;
|
||||
inputStyle?: string;
|
||||
defaultValue: string;
|
||||
placeholder?: string;
|
||||
updateFormValue: (value: string ) => void;
|
||||
@ -13,7 +14,7 @@ type TextAreaProps = {
|
||||
|
||||
|
||||
|
||||
function TextAreaInput({labelTitle, labelStyle, containerStyle, defaultValue, placeholder, updateFormValue} : TextAreaProps){
|
||||
function TextAreaInput({labelTitle, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, updateFormValue} : TextAreaProps){
|
||||
|
||||
const [value, setValue] = useState<string>(defaultValue)
|
||||
|
||||
@ -28,11 +29,11 @@ function TextAreaInput({labelTitle, labelStyle, containerStyle, defaultValue, pl
|
||||
}
|
||||
|
||||
return(
|
||||
<div className={`tw-form-control tw-w-full ${containerStyle}`}>
|
||||
<label className="tw-label">
|
||||
<div className={`tw-form-control tw-w-full ${containerStyle? containerStyle : ""}`}>
|
||||
{labelTitle ? <label className="tw-label">
|
||||
<span className={"tw-label-text tw-text-base-content " + labelStyle}>{labelTitle}</span>
|
||||
</label>
|
||||
<textarea value={value} className="tw-textarea tw-textarea-bordered tw-w-full tw-min-h-64" placeholder={placeholder || ""} onChange={(e) => updateInputValue(e.target.value)}></textarea>
|
||||
</label> : ""}
|
||||
<textarea value={value} className={`tw-textarea tw-textarea-bordered tw-w-full tw-leading-5 ${inputStyle? inputStyle : ""}`} placeholder={placeholder || ""} onChange={(e) => updateInputValue(e.target.value)}></textarea>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ export const Layer = (props: LayerProps) => {
|
||||
}
|
||||
return (
|
||||
<Marker icon={MarkerIconFactory(props.markerShape, color1, color2, props.markerIcon)} key={place.id} position={[place.position.coordinates[1], place.position.coordinates[0]]}>
|
||||
<ItemViewPopup item={place} tags={tags} setItemFormPopup={props.setItemFormPopup} />
|
||||
<ItemViewPopup item={place} setItemFormPopup={props.setItemFormPopup} />
|
||||
</Marker>
|
||||
);
|
||||
})
|
||||
|
||||
@ -4,6 +4,8 @@ import { Popup as LeafletPopup, useMap } from 'react-leaflet'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useAddItem, useUpdateItem } from '../hooks/useItems'
|
||||
import { Geometry, LayerProps, Item, ItemsApi} from '../../../types'
|
||||
import TextAreaInput from '../../Input/TextAreaInput'
|
||||
import InputText from '../../Input/InputText'
|
||||
|
||||
export interface ItemFormPopupProps {
|
||||
position: LatLng,
|
||||
@ -68,8 +70,8 @@ export default function ItemFormPopup(props: ItemFormPopupProps) {
|
||||
position={props.position}>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className='tw-flex tw-justify-center'><b className="tw-text-xl tw-font-bold">New {props.layer.name}</b></div>
|
||||
<input type="text" placeholder="Name" className="tw-input tw-input-bordered tw-w-full tw-max-w-xs tw-mt-5" value={name} onChange={e => setName(e.target.value)} />
|
||||
<textarea className="tw-textarea tw-textarea-bordered tw-w-full tw-mt-5 tw-leading-5 tw-h-40" placeholder="Text" value={text} onChange={e => setText(e.target.value)}></textarea>
|
||||
<InputText type="text" placeholder="Name" defaultValue={name} updateFormValue={e => setName(e)} />
|
||||
<TextAreaInput placeholder="Text" defaultValue={text} updateFormValue={e => setText(e)} inputStyle='tw-h-40 tw-mt-5'/>
|
||||
<div className='tw-flex tw-justify-center'><button className={spinner ? 'tw-btn tw-loading tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'}>Save</button></div>
|
||||
</form>
|
||||
</LeafletPopup>
|
||||
|
||||
@ -1,118 +1,33 @@
|
||||
import { LatLng } from 'leaflet'
|
||||
import * as React from 'react'
|
||||
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
|
||||
import { Item, Tag } from '../../../types'
|
||||
import { replaceURLs } from '../../../Utils/ReplaceURLs'
|
||||
import { useRemoveItem } from '../hooks/useItems'
|
||||
import { Item} from '../../../types'
|
||||
import { ItemFormPopupProps } from './ItemFormPopup'
|
||||
import { heighlightTags } from '../../../Utils/HeighlightTags'
|
||||
import { useTags } from '../hooks/useTags'
|
||||
import {HeaderView} from './HeaderView'
|
||||
import StartEndView from './StartEndView'
|
||||
import { TextView } from './TextView'
|
||||
|
||||
export interface ItemViewPopupProps {
|
||||
item: Item,
|
||||
tags: Tag[],
|
||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ItemViewPopup = (props: ItemViewPopupProps) => {
|
||||
export const ItemViewPopup = (props: ItemViewPopupProps) => {
|
||||
const item: Item = props.item;
|
||||
const tags: Tag[] = props.tags;
|
||||
const removeItem = useRemoveItem();
|
||||
|
||||
const map = useMap();
|
||||
|
||||
const all_tags = useTags();
|
||||
|
||||
|
||||
const removeItemFromMap = (event: React.MouseEvent<HTMLElement>) => {
|
||||
props.item.api?.deleteItem!(props.item.id)
|
||||
.then( () => removeItem(item))
|
||||
.then(()=> map.closePopup())
|
||||
.catch(err => console.log(err));
|
||||
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
const openEditPopup = (event: React.MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation();
|
||||
map.closePopup();
|
||||
if (props.setItemFormPopup)
|
||||
props.setItemFormPopup({ position: new LatLng(item.position.coordinates[1], item.position.coordinates[0]), layer: item.layer, item: item, setItemFormPopup: props.setItemFormPopup })
|
||||
}
|
||||
|
||||
return (
|
||||
<LeafletPopup maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 5]}>
|
||||
<div>
|
||||
<div className='tw-grid tw-grid-cols-6'>
|
||||
<div className='tw-col-span-5'>
|
||||
<b className="tw-text-xl tw-font-bold">{item.name}</b>
|
||||
</div>
|
||||
<div className='tw-col-span-1'>
|
||||
{item.api &&
|
||||
<div className="tw-dropdown tw-dropdown-right">
|
||||
<label tabIndex={0} className="tw-btn tw-m-1 tw-bg-white hover:tw-bg-white tw-text-gray-500 hover:tw-text-gray-700 tw-leading-3 tw-border-none tw-min-h-0 tw-h-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
|
||||
</svg>
|
||||
</label>
|
||||
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box">
|
||||
{item.api.updateItem && <li>
|
||||
<a className='tw-bg-white hover:tw-bg-gray-300 !tw-text-blue-800 hover:tw-text-gray-700' onClick={openEditPopup}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>}
|
||||
|
||||
{item.api.deleteItem && <li>
|
||||
<a className='tw-bg-white hover:tw-bg-gray-300 !tw-text-red-800 hover:tw-text-red-950' onClick={removeItemFromMap}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>}
|
||||
</ul>
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
<HeaderView item={props.item} setItemFormPopup={props.setItemFormPopup}/>
|
||||
<div className='tw-overflow-y-auto tw-max-h-72'>
|
||||
{item.start && item.end &&
|
||||
<div className="tw-flex tw-flex-row">
|
||||
<div className="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>
|
||||
<StartEndView item={props.item} />
|
||||
}
|
||||
|
||||
<p style={{ whiteSpace: "pre-wrap" }} dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item.text, all_tags)) }} />
|
||||
<p>
|
||||
|
||||
{item.tags &&
|
||||
tags.map((tag: Tag) => (
|
||||
<span className="" style={{ fontWeight: "bold", display: "inline-block", color: "#fff", padding: ".3rem", borderRadius: ".5rem", backgroundColor: tag.color, margin: '.2rem', fontSize: "100%" }} key={tag.id}>#{tag.id}</span>
|
||||
))
|
||||
}
|
||||
</p>
|
||||
<TextView item={props.item}/>
|
||||
</div>
|
||||
</div>
|
||||
</LeafletPopup>
|
||||
)
|
||||
}
|
||||
|
||||
export { ItemViewPopup };
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { TileLayer, MapContainer, useMapEvents } from "react-leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import * as React from "react";
|
||||
import { Item, Tag, ItemsApi, LayerProps, UtopiaMapProps } from "../../types"
|
||||
import { Tag, ItemsApi, LayerProps, UtopiaMapProps } from "../../types"
|
||||
import "./UtopiaMap.css"
|
||||
import { LatLng } from "leaflet";
|
||||
import MarkerClusterGroup from 'react-leaflet-cluster'
|
||||
@ -87,4 +87,4 @@ function UtopiaMap({
|
||||
);
|
||||
}
|
||||
|
||||
export { UtopiaMap, Item, Tag, ItemsApi };
|
||||
export { UtopiaMap };
|
||||
@ -1,3 +1,3 @@
|
||||
export { UtopiaMap, Item, Tag, ItemsApi } from './UtopiaMap'
|
||||
export { UtopiaMap } from './UtopiaMap'
|
||||
export { Layer } from './Layer';
|
||||
export { Tags } from "./Tags";
|
||||
@ -55,10 +55,6 @@ export function Settings({useAuth}) {
|
||||
}
|
||||
|
||||
|
||||
const updateFormValue = (val: string) => {
|
||||
console.log(val)
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="tw-flex-1 tw-overflow-y-auto tw-overflow-x-hidden tw-pt-8 tw-px-6 tw-bg-base-200 tw-min-w-80 tw-flex tw-justify-center" >
|
||||
<div className='tw-w-full xl:tw-max-w-6xl'>
|
||||
@ -66,17 +62,17 @@ export function Settings({useAuth}) {
|
||||
|
||||
|
||||
<div className="tw-grid tw-grid-cols-1 tw-md:grid-cols-2 tw-gap-6">
|
||||
<InputText labelTitle="Name" defaultValue={user?.first_name ? user.first_name : ""} updateFormValue={(v) => setName(v)} />
|
||||
<InputText placeholder="Name" defaultValue={user?.first_name ? user.first_name : ""} updateFormValue={(v) => setName(v)} />
|
||||
</div>
|
||||
<div className="tw-grid tw-grid-cols-1 tw-md:grid-cols-1 tw-gap-6 tw-pt-6 tw-pb-6">
|
||||
<TextAreaInput labelTitle="About" defaultValue={user?.description ? user.description : ""} updateFormValue={(v) => setText(v)} />
|
||||
<TextAreaInput placeholder="About me, Contact, #Tags, ..." defaultValue={user?.description ? user.description : ""} updateFormValue={(v) => setText(v)} inputStyle='tw-h-64'/>
|
||||
</div>
|
||||
<div className="tw-divider" ></div>
|
||||
|
||||
|
||||
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6">
|
||||
<InputText type='email' labelTitle="E-Mail" defaultValue={user?.email ? user.email : ""} updateFormValue={(v) => setEmail(v)} />
|
||||
<InputText type='password' labelTitle="Password" defaultValue={user?.password ? user.password : ""} updateFormValue={(v) => {
|
||||
<InputText type='email' placeholder="E-Mail" defaultValue={user?.email ? user.email : ""} updateFormValue={(v) => setEmail(v)} />
|
||||
<InputText type='password' placeholder="new Password" defaultValue={user?.password ? user.password : ""} updateFormValue={(v) => {
|
||||
setPassword(v);
|
||||
setPasswordChanged(true);
|
||||
}} />
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export { UtopiaMap, Layer, Tags, Item, Tag } from './Components/Map/index';
|
||||
export { UtopiaMap, Layer, Tags } from './Components/Map/index';
|
||||
export {AppShell, Content, SideBar} from "./Components/AppShell"
|
||||
export {AuthProvider, useAuth, LoginPage, SignupPage} from "./Components/Auth"
|
||||
export {Settings} from './Components/Profile'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user