HeaderView and bugfixing

This commit is contained in:
Anton Tranelis 2024-03-22 11:58:27 +01:00
parent 0b717f35fe
commit 93cbcf7f15
5 changed files with 176 additions and 157 deletions

View File

@ -14,6 +14,7 @@ import { LocateControl } from './LocateControl';
import * as L from 'leaflet';
import MarkerIconFactory from '../../../../Utils/MarkerIconFactory';
import { decodeTag } from '../../../../Utils/FormatTags';
import { useNavigate } from 'react-router-dom';
@ -45,6 +46,8 @@ export const SearchControl = ({ clusterRef }) => {
}
})
const navigate = useNavigate();
useDebounce(() => {
const searchGeo = async () => {
try {
@ -111,18 +114,23 @@ export const SearchControl = ({ clusterRef }) => {
{itemsResults.slice(0, 5).map(item => (
<div key={item.id} className='tw-cursor-pointer hover:tw-font-bold' onClick={() => {
const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker;
if (filterTags.length > 0) {
marker !== null && window.history.pushState({}, "", `/${item.layer.name}/${item.id}`)
resetFilterTags();
hide();
if(marker){
if (filterTags.length > 0) {
marker !== null && window.history.pushState({}, "", `/${item.layer.name}/${item.id}`)
resetFilterTags();
hide();
}
else {
marker !== null && clusterRef?.current?.zoomToShowLayer(marker, () => {
marker?.openPopup();
hide();
});
}
}
else {
marker !== null && clusterRef?.current?.zoomToShowLayer(marker, () => {
marker?.openPopup();
hide();
});
navigate("item/"+item.id)
}
}
}><div className='tw-flex tw-flex-row'>
<item.layer.menuIcon className="tw-text-current tw-w-5 tw-mr-2 tw-mt-0" />

View File

@ -1,12 +1,8 @@
import * as React from "react"
import { useRemoveItem } from "../../hooks/useItems";
import { useMap } from "react-leaflet";
import { ItemFormPopupProps } from "../ItemFormPopup";
import { LatLng } from "leaflet";
import { Item } from "../../../../types";
import { Item, ItemsApi } from "../../../../types";
import { toast } from "react-toastify";
import { useHasUserPermission } from "../../hooks/usePermissions";
import { useAuth } from "../../../Auth";
import { getValue } from "../../../../Utils/GetValue";
import { useAssetApi } from '../../../AppShell/hooks/useAssets'
import DialogModal from "../../../Templates/DialogModal";
@ -15,129 +11,97 @@ import { useNavigate } from "react-router-dom";
export function HeaderView({ item, setItemFormPopup, hideMenu=false }: {
export function HeaderView({ item, api, editCallback, deleteCallback, itemNameField, itemAvatarField, loading, hideMenu = false }: {
item: Item,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
api?: ItemsApi<any>,
editCallback?: any,
deleteCallback?: any,
itemNameField?: string,
itemAvatarField?: string,
loading?: boolean,
hideMenu?: boolean
}) {
const [modalOpen, setModalOpen] = React.useState<boolean>(false);
const [loading, setLoading] = React.useState<boolean>(false);
const removeItem = useRemoveItem();
const map = useMap();
const hasUserPermission = useHasUserPermission();
const { user } = useAuth();
const assetsApi = useAssetApi();
const navigate = useNavigate();
const avatar = item.layer?.itemAvatarField && item && getValue(item, item.layer?.itemAvatarField)? assetsApi.url + getValue(item, item.layer?.itemAvatarField ) : undefined;
const title = item.layer?.itemNameField && item ? getValue(item, item.layer?.itemNameField) : undefined;
const owner = item.layer?.itemOwnerField && item ? getValue(item, item.layer?.itemOwnerField) : undefined;
const avatar = itemAvatarField && getValue(item, itemAvatarField) ? assetsApi.url + getValue(item, itemAvatarField) : item.layer?.itemAvatarField && item && getValue(item, item.layer?.itemAvatarField) && assetsApi.url + getValue(item, item.layer?.itemAvatarField);
const title = itemNameField ? getValue(item, itemNameField) : item.layer?.itemNameField && item && getValue(item, item.layer?.itemNameField);
const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
setLoading(true);
let success = false;
try {
await item.layer?.api?.deleteItem!(item.id)
success = true;
} catch (error) {
toast.error(error.toString());
}
if (success) {
removeItem(item);
toast.success("Item deleted");
}
setLoading(false);
map.closePopup();
let params = new URLSearchParams(window.location.search);
window.history.pushState({}, "", "/" + `${params? `?${params}` : ""}`);
setModalOpen(false);
navigate("/");
}
const openDeleteModal = async (event: React.MouseEvent<HTMLElement>) => {
setModalOpen(true);
event.stopPropagation();
}
const openEditPopup = (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
map.closePopup();
if (setItemFormPopup && item.position)
setItemFormPopup({ position: new LatLng(item.position.coordinates[1], item.position.coordinates[0]), layer: item.layer!, item: item, setItemFormPopup: setItemFormPopup })
}
return (
<>
<div className='tw-grid tw-grid-cols-6 tw-pb-2'>
<div className='tw-col-span-5'>
<div className="tw-flex tw-flex-row">{
avatar ?
<div className="tw-w-10 tw-min-w-[2.5em] tw-rounded-full">
<img className="tw-rounded-full" src={`${avatar}?width=80&height=80`} />
</div>
:
""
}
<div className='tw-grid tw-grid-cols-6 tw-pb-2'>
<div className='tw-col-span-5'>
<div className="tw-flex tw-flex-row">{
avatar ?
<div className="tw-w-10 tw-min-w-[2.5em] tw-rounded-full">
<img className="tw-rounded-full" src={`${avatar}?width=80&height=80`} />
</div>
:
""
}
<b className={`tw-text-xl tw-font-bold ${avatar ? "tw-ml-2 tw-mt-1" : ""}`}>{title ? title : item.name}</b>
</div>
</div>
<div className='tw-col-span-1' onClick={(e) => e.stopPropagation()}>
{(api?.deleteItem || item.layer?.api?.updateItem)
&& (hasUserPermission(api?.collectionName!, "delete", item) || hasUserPermission(api?.collectionName!, "update", item))
&& !hideMenu &&
<div className="tw-dropdown tw-dropdown-bottom">
<label tabIndex={0} className="tw-bg-base-100 tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6">
<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 tw-z-1000">
{((api?.updateItem && hasUserPermission(api.collectionName!, "update", item)) || item.layer?.customEditLink) && <li>
<a className="!tw-text-base-content tw-cursor-pointer" onClick={editCallback}>
<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>}
{api?.deleteItem && hasUserPermission(api.collectionName!, "delete", item) && <li>
<a className='tw-cursor-pointer !tw-text-error' onClick={openDeleteModal}>
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
:
<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>
<div className='tw-col-span-1' onClick={(e)=>e.stopPropagation()}>
{(item.layer?.api?.deleteItem || item.layer?.api?.updateItem)
&& (hasUserPermission(item.layer.api?.collectionName!, "delete", item) || hasUserPermission(item.layer.api?.collectionName!, "update", item))
&& !hideMenu &&
<div className="tw-dropdown tw-dropdown-bottom">
<label tabIndex={0} className="tw-bg-base-100 tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6">
<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 tw-z-1000">
{((item.layer.api.updateItem && hasUserPermission(item.layer.api?.collectionName!, "update", item)) || item.layer.customEditLink) && <li>
<a className="!tw-text-base-content tw-cursor-pointer" onClick={(e) => {
item.layer?.customEditLink && navigate(item.layer.customEditLink);
!item.layer?.customEditLink && openEditPopup(e);
}}>
<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.layer.api.deleteItem && hasUserPermission(item.layer.api?.collectionName!, "delete", item) && <li>
<a className='tw-cursor-pointer !tw-text-error' onClick={openDeleteModal}>
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
:
<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>
<DialogModal isOpened={modalOpen} title="Are you sure?" showCloseButton={false} onClose={ () => (setModalOpen(false)) }>
<span>Do you want to delete <b>{item.name}</b>?</span>
<div className="tw-grid">
<div className="tw-flex tw-justify-between">
<label className="tw-btn tw-mt-4 tw-btn-error" onClick={removeItemFromMap}>Yes</label>
<label className="tw-btn tw-mt-4" onClick={() => setModalOpen(false)}>No</label>
</div>
<DialogModal isOpened={modalOpen} title="Are you sure?" showCloseButton={false} onClose={() => (setModalOpen(false))} >
<div onClick={(e) => e.stopPropagation()} >
<span>Do you want to delete <b>{item.name}</b>?</span>
<div className="tw-grid">
<div className="tw-flex tw-justify-between" >
<label className="tw-btn tw-mt-4 tw-btn-error" onClick={(e) => { deleteCallback(e); setModalOpen(false); }}>Yes</label>
<label className="tw-btn tw-mt-4" onClick={() => setModalOpen(false)}>No</label>
</div>
</DialogModal>
</div>
</div>
</DialogModal>
</>
)
}

View File

@ -1,11 +1,15 @@
import * as React from 'react'
import { Popup as LeafletPopup } from 'react-leaflet'
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
import { Item } from '../../../types'
import { ItemFormPopupProps } from './ItemFormPopup'
import { HeaderView } from './ItemPopupComponents/HeaderView'
import { TextView } from './ItemPopupComponents/TextView'
import { timeAgo } from '../../../Utils/TimeAgo'
import { useState } from 'react'
import { LatLng } from 'leaflet'
import { useNavigate } from 'react-router-dom'
import { useRemoveItem } from '../hooks/useItems'
import { toast } from 'react-toastify'
export interface ItemViewPopupProps {
@ -17,12 +21,46 @@ export interface ItemViewPopupProps {
export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: any) => {
const map = useMap();
const [loading, setLoading] = React.useState<boolean>(false);
const removeItem = useRemoveItem();
const navigate = useNavigate();
const [infoExpanded, setInfoExpanded] = useState<Boolean>(false);
const handleEdit = (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
map.closePopup();
props.setItemFormPopup && props.setItemFormPopup({ position: new LatLng(props.item.position?.coordinates[1]!, props.item.position?.coordinates[0]!), layer: props.item.layer!, item: props.item, setItemFormPopup: props.setItemFormPopup })
}
const handleDelete = async (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
setLoading(true);
let success = false;
try {
await props.item.layer?.api?.deleteItem!(props.item.id)
success = true;
} catch (error) {
toast.error(error.toString());
}
if (success) {
removeItem(props.item);
toast.success("Item deleted");
}
setLoading(false);
map.closePopup();
let params = new URLSearchParams(window.location.search);
window.history.pushState({}, "", "/" + `${params ? `?${params}` : ""}`);
navigate("/");
}
return (
<LeafletPopup ref={ref} maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 80]}>
<div className='tw-bg-base-100 tw-text-base-content'>
<HeaderView item={props.item} setItemFormPopup={props.setItemFormPopup} />
<HeaderView api={props.item.api} item={props.item} editCallback={handleEdit} deleteCallback={handleDelete} />
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
{props.children ?
@ -48,8 +86,8 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
<p className="!tw-my-0 tw-min-h-[21px] tw-font-bold tw-cursor-pointer tw-text-gray-500" onClick={() => setInfoExpanded(true)}></p>
}
<div className='tw-grow'></div>
{ //** <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="tw-place-self-end tw-w-4 tw-h-4 tw-mb-1 tw-cursor-pointer"><path strokeLinecap="round" strokeLinejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" /></svg> */
}
{ //** <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="tw-place-self-end tw-w-4 tw-h-4 tw-mb-1 tw-cursor-pointer"><path strokeLinecap="round" strokeLinejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" /></svg> */
}
</div>
</div>
</LeafletPopup>

View File

@ -65,6 +65,11 @@ export function OverlayItemProfile() {
scroll();
}, [addItemPopupType])
useEffect(() => {
console.log(addItemPopupType);
}, [addItemPopupType])
useEffect(() => {
@ -108,8 +113,12 @@ export function OverlayItemProfile() {
}
});
const uuid = crypto.randomUUID();
const layer = layers.find(l => l.name = addItemPopupType)
console.log(layers);
const layer = layers.find(l => l.name.toLocaleLowerCase().replace("s","") == addItemPopupType.toLocaleLowerCase())
console.log(layer);
let success = false;
try {
await layer?.api?.createItem!({ ...formItem, id: uuid, type: type });
@ -169,12 +178,13 @@ export function OverlayItemProfile() {
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Projects" checked={activeTab == 2 && true} onChange={() => setActiveTab(2)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4" >
<div className='tw-h-full'>
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-2'>
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-2 tw-pb-5'>
{relations && relations.map(i => {
if (i.type == 'project') return (
<div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4 tw-h-fit' onClick={() => navigate('/item/' + i.id)}>
<HeaderView item={i} />
<HeaderView loading={loading} item={i} api={i.layer?.api} editCallback={() => navigate("/edit-item/"+i.id)}></HeaderView>
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
<TextView truncate item={i} />
</div>
@ -206,7 +216,7 @@ export function OverlayItemProfile() {
</div>
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Events" checked={activeTab == 3 && true} onChange={() => setActiveTab(3)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1">
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4">
<div className='tw-h-full'>
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-2'>
{relations && relations.map(i => {

View File

@ -15,6 +15,7 @@ import { randomColor } from '../../Utils/RandomColor';
import { useAuth } from '../Auth';
import { useLayers } from '../Map/hooks/useLayers';
import { PermissionsProvider } from '../Map/hooks/usePermissions';
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
type breadcrumb = {
@ -33,7 +34,7 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
const tabRef = useRef<HTMLFormElement>(null);
function scroll() {
tabRef.current?.scrollIntoView();
tabRef.current?.scrollIntoView();
}
useEffect(() => {
@ -67,33 +68,51 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
evt.preventDefault();
const formItem: Item = {} as Item;
Array.from(evt.target).forEach((input: HTMLInputElement) => {
if (input.name) {
formItem[input.name] = input.value;
}
if (input.name) {
formItem[input.name] = input.value;
}
});
setLoading(true);
formItem.text && formItem.text.toLocaleLowerCase().match(hashTagRegex)?.map(tag => {
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() })
}
if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() })
}
});
const uuid = crypto.randomUUID();
let success = false;
try {
await api?.createItem!({ ...formItem, id: uuid, type: type });
success = true;
await api?.createItem!({ ...formItem, id: uuid, type: type });
success = true;
} catch (error) {
toast.error(error.toString());
toast.error(error.toString());
}
if (success) {
addItem({ ...formItem, id: uuid, type: type, layer: layers.find(l => l.name == addItemPopupType), user_created: user });
toast.success("New item created");
resetFilterTags();
addItem({ ...formItem, id: uuid, type: type, layer: layers.find(l => l.name == addItemPopupType), user_created: user });
toast.success("New item created");
resetFilterTags();
}
setLoading(false);
setAddItemPopupType("");
setItems(current => [...current,{ ...formItem, id: uuid, type: type, layer: layers.find(l => l.name == addItemPopupType), user_created: user } ])
}
setItems(current => [...current, { ...formItem, id: uuid, type: type, layer: layers.find(l => l.name == addItemPopupType), user_created: user }])
}
const deleteItem = async (item) => {
setLoading(true);
let success = false;
try {
await api?.deleteItem!(item.id)
success = true;
} catch (error) {
toast.error(error.toString());
}
if (success) {
toast.success("Item deleted");
}
setLoading(false);
setItems(items.filter(i=>i.id !=item.id))
console.log("chaka");
}
return (
@ -121,32 +140,12 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
{
items?.map((i, k) => {
return (
<div key={k} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-p-4 tw-mb-4 tw-h-fit' onClick={() => navigate(url + getValue(i,parameterField))}>
<div className='tw-grid tw-grid-cols-6 tw-pb-2'>
<div className='tw-col-span-5'>
<div className="tw-flex tw-flex-row">{
getValue(i, itemImageField) ?
<div className="tw-w-10 tw-min-w-[2.5em] tw-rounded-full">
<img className="tw-rounded-full" src={`${assetsApi.url}${getValue(i, itemImageField)}?width=80&height=80`} />
</div>
:
""
}
<b className={`tw-text-xl tw-font-bold ${getValue(i, itemImageField) ? "tw-ml-2 tw-mt-1" : ""}`}>{getValue(i, itemNameField)}</b>
</div>
</div>
<div className='tw-col-span-1'>
</div>
</div>
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
<TextView truncate item={i} itemTextField={itemTextField} />
</div>
<div key={k} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-p-4 tw-mb-4 tw-h-fit' onClick={() => navigate(url + getValue(i, parameterField))}>
<HeaderView loading={loading} item={i} api={api} itemAvatarField={itemImageField} itemNameField={itemNameField} editCallback={() => navigate("/edit-item/"+i.id)} deleteCallback={()=>deleteItem(i)}></HeaderView>
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
<TextView truncate item={i} itemTextField={itemTextField} />
</div>
</div>
)
@ -154,7 +153,7 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
}
{addItemPopupType == "project" ?
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
<div className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-p-6 tw-mb-10'>
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => {
@ -171,7 +170,7 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
}
</div>
</div>
<PlusButton triggerAction={() => {setAddItemPopupType("project"); scroll();}} color={'#777'} collection='items'/>
<PlusButton triggerAction={() => { setAddItemPopupType("project"); scroll(); }} color={'#777'} collection='items' />
{children}
</main>