optimization for profile layers

This commit is contained in:
Anton Tranelis 2024-01-30 14:04:08 +01:00
parent 5b01dc983d
commit 07492564d7
5 changed files with 54 additions and 20 deletions

View File

@ -1,11 +1,17 @@
import * as React from 'react'
import { Item } from '../../types'
import * as PropTypes from 'prop-types'
import { useEffect } from 'react'
export const ItemForm = ({ children, item }: { children?: React.ReactNode, item?: Item }) => {
export const ItemForm = ({ children, item, title, setPopupTitle }: { children?: React.ReactNode, item?: Item, title?: string, setPopupTitle?: React.Dispatch<React.SetStateAction<string>> }) => {
useEffect(() => {
setPopupTitle&& title && setPopupTitle(title);
}, [title])
return (
<div>{
<div className='tw-flex tw-justify-center'>{
children ?
React.Children.toArray(children).map((child) =>
React.isValidElement<{ item: Item, test: string }>(child) ?

View File

@ -33,6 +33,7 @@ export const Layer = ({
itemOwnerField,
itemLatitudeField = 'position.coordinates.1',
itemLongitudeField = 'position.coordinates.0',
onlyOnePerOwner = false,
setItemFormPopup,
itemFormPopup,
clusterRef
@ -63,8 +64,8 @@ export const Layer = ({
useEffect(() => {
data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, setItemFormPopup, itemFormPopup, clusterRef });
api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, setItemFormPopup, itemFormPopup, clusterRef });
data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, onlyOnePerOwner, setItemFormPopup, itemFormPopup, clusterRef });
api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, onlyOnePerOwner, setItemFormPopup, itemFormPopup, clusterRef });
}, [data, api])
useMapEvents({
@ -138,8 +139,9 @@ export const Layer = ({
filter(item => item.layer && isLayerVisible(item.layer)).
map((item: Item) => {
if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) {
item[itemTextField] = getValue(item, itemTextField);
if (item?.tags) {
item[itemTextField] = getValue(item, itemTextField) + '\n\n';
item[itemTextField] = item[itemTextField] + '\n\n';
item.tags.map(tag => {
if(!item[itemTextField].includes(`#${tag}`))
return (item[itemTextField] = item[itemTextField] + `#${tag} `)

View File

@ -2,7 +2,7 @@ import * as React from 'react'
import { LatLng } from 'leaflet'
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
import { useEffect, useRef, useState } from 'react'
import { useAddItem, useUpdateItem } from '../hooks/useItems'
import { useAddItem, useItems, useRemoveItem, useUpdateItem } from '../hooks/useItems'
import { Geometry, LayerProps, Item, ItemsApi } from '../../../types'
import { TextAreaInput } from '../../Input/TextAreaInput'
import { TextInput } from '../../Input/TextInput'
@ -25,12 +25,17 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
const [spinner, setSpinner] = useState(false);
const [popupTitle, setPopupTitle] = useState<string>("");
const formRef = useRef<HTMLFormElement>(null);
const map = useMap();
const addItem = useAddItem();
const updateItem = useUpdateItem();
const items = useItems();
const removeItem = useRemoveItem();
const tags = useTags();
const addTag = useAddTag();
@ -51,7 +56,7 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
evt.preventDefault();
setSpinner(true);
formItem.text.toLocaleLowerCase().match(hashTagRegex)?.map(tag=> {
formItem.text && formItem.text.toLocaleLowerCase().match(hashTagRegex)?.map(tag=> {
if (!tags.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
addTag({id: tag.slice(1).toLocaleLowerCase(), color: randomColor()})
}
@ -85,6 +90,16 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
toast.error(error.toString());
}
if(success) {
console.log(props.layer);
if(props.layer.onlyOnePerOwner){
console.log(items);
const item = items.find(item => item.layer == props.layer && item.user_created?.id == user?.id);
console.log(item);
item && removeItem(item);
}
addItem({...formItem, id: uuid, layer: props.layer, user_created: user});
toast.success("New item created");
resetFilterTags();
@ -119,14 +134,14 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
<form ref={formRef} onReset={resetPopup} autoComplete='off' onSubmit={e => handleSubmit(e)}>
{props.item ? <div className='tw-h-3'></div>
:
<div className='tw-flex tw-justify-center'><b className="tw-text-xl tw-font-bold">New {props.layer.name}</b></div>
<div className='tw-flex tw-justify-center'><b className="tw-text-xl tw-font-bold">{ popupTitle? popupTitle : `New ${props.layer.name}`}</b></div>
}
{props.children ?
React.Children.toArray(props.children).map((child) =>
React.isValidElement<{ item: Item, test: string }>(child) ?
React.cloneElement(child, { item: props.item, key: props.position.toString() }) : ""
React.isValidElement<{ item: Item, test: string, setPopupTitle: React.Dispatch<React.SetStateAction<string>> }>(child) ?
React.cloneElement(child, { item: props.item, key: props.position.toString(), setPopupTitle: setPopupTitle }) : ""
)
:

View File

@ -8,17 +8,19 @@ import Markdown from 'react-markdown'
import rehypeVideo from 'rehype-video';
import { getValue } from '../../../../Utils/GetValue';
export const TextView = ({ item }: { item?: Item }) => {
export const TextView = ({ item, truncate = false}: { item?: Item, truncate?: boolean }) => {
const tags = useTags();
const addFilterTag = useAddFilterTag();
const text = item?.layer?.itemTextField && item ? getValue(item, item.layer?.itemTextField) : undefined;
let text = item?.layer?.itemTextField && item ? getValue(item, item.layer?.itemTextField) : "";
if(item && text && truncate) text = truncateString(text, 100, true);
let replacedText;
if (item && text) replacedText = fixUrls(text);
item && text ? replacedText = fixUrls(text) : "";
replacedText = replacedText.replace(/(?<!\]?\()https?:\/\/[^\s\)]+(?!\))/g, (url) => {
replacedText ? replacedText = replacedText.replace(/(?<!\]?\()https?:\/\/[^\s\)]+(?!\))/g, (url) => {
let shortUrl = url;
if (url.match('^https:\/\/')) {
shortUrl = url.split('https://')[1];
@ -27,15 +29,15 @@ export const TextView = ({ item }: { item?: Item }) => {
shortUrl = url.split('http://')[1];
}
return `[${shortUrl}](${url})`
})
}) : "" ;
replacedText = replacedText.replace(mailRegex, (url) => {
replacedText ? replacedText = replacedText.replace(mailRegex, (url) => {
return `[${url}](mailto:${url})`
})
}) : "";
replacedText = replacedText.replace(hashTagRegex, (match) => {
replacedText ? replacedText = replacedText.replace(hashTagRegex, (match) => {
return `[${match}](${match})`
})
}) : "";
@ -146,4 +148,12 @@ export const TextView = ({ item }: { item?: Item }) => {
}
}
function truncateString( str, n, useWordBoundary ){
if (str.length <= n) { return str; }
const subString = str.slice(0, n-1); // the original check
return (useWordBoundary
? subString.slice(0, subString.lastIndexOf(" "))
: subString) + "&hellip;";
};

View File

@ -29,6 +29,7 @@ export interface LayerProps {
itemTagField?: string,
itemLatitudeField?: any,
itemLongitudeField?: any,
onlyOnePerOwner?: boolean,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
itemFormPopup?: ItemFormPopupProps | null,
clusterRef?: React.MutableRefObject<any>