mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
sort items by date in index page and always show date in item popup
This commit is contained in:
parent
c67cef9576
commit
f022709cf8
@ -31,8 +31,6 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
||||
const setSelectPosition = useSetSelectPosition();
|
||||
|
||||
|
||||
const [infoExpanded, setInfoExpanded] = useState<Boolean>(false);
|
||||
|
||||
const handleEdit = (event: React.MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation();
|
||||
map.closePopup();
|
||||
@ -85,12 +83,8 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
||||
<div className='tw-flex -tw-mb-1 tw-flex-row tw-mr-2 tw-mt-1'>
|
||||
|
||||
|
||||
{
|
||||
infoExpanded ?
|
||||
<p className={`tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500 tw-cursor-pointer`} onClick={() => setInfoExpanded(false)}>{`posted ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ""} ${timeAgo(props.item.date_created!)}`}</p>
|
||||
:
|
||||
<p className="!tw-my-0 tw-min-h-[21px] tw-font-bold tw-cursor-pointer tw-text-gray-500" onClick={() => setInfoExpanded(true)}>ⓘ</p>
|
||||
}
|
||||
<p className={`tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500`} >{`${props.item.date_updated && props.item.date_updated != props.item.date_created ? "updated" : "posted" } ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ""} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created!)}`}</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> */
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import { useLayers } from '../Map/hooks/useLayers';
|
||||
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
||||
import { MapOverlayPage } from './MapOverlayPage';
|
||||
import { useAddItem, useItems, useRemoveItem } from '../Map/hooks/useItems';
|
||||
import { timeAgo } from '../../Utils/TimeAgo';
|
||||
|
||||
|
||||
type breadcrumb = {
|
||||
@ -22,7 +23,7 @@ type breadcrumb = {
|
||||
}
|
||||
|
||||
|
||||
export const OverlayItemsIndexPage = ({url, layerName, parameterField, breadcrumbs, itemNameField, itemTextField, itemImageField, itemSymbolField, itemSubnameField, plusButton = true, children }: { layerName: string, url: string, parameterField: string, breadcrumbs: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string, itemSubnameField: string, plusButton?: boolean, children?: ReactNode }) => {
|
||||
export const OverlayItemsIndexPage = ({ url, layerName, parameterField, breadcrumbs, itemNameField, itemTextField, itemImageField, itemSymbolField, itemSubnameField, plusButton = true, children }: { layerName: string, url: string, parameterField: string, breadcrumbs: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string, itemSubnameField: string, plusButton?: boolean, children?: ReactNode }) => {
|
||||
|
||||
console.log(itemSymbolField);
|
||||
|
||||
@ -52,10 +53,10 @@ export const OverlayItemsIndexPage = ({url, layerName, parameterField, breadcrum
|
||||
|
||||
useEffect(() => {
|
||||
console.log(items);
|
||||
|
||||
|
||||
|
||||
}, [items])
|
||||
|
||||
|
||||
const layer = layers.find(l => l.name == layerName);
|
||||
|
||||
|
||||
@ -76,7 +77,7 @@ export const OverlayItemsIndexPage = ({url, layerName, parameterField, breadcrum
|
||||
const uuid = crypto.randomUUID();
|
||||
let success = false;
|
||||
try {
|
||||
await layer?.api?.createItem!({ ...formItem, id: uuid});
|
||||
await layer?.api?.createItem!({ ...formItem, id: uuid });
|
||||
success = true;
|
||||
} catch (error) {
|
||||
toast.error(error.toString());
|
||||
@ -84,7 +85,7 @@ export const OverlayItemsIndexPage = ({url, layerName, parameterField, breadcrum
|
||||
if (success) {
|
||||
toast.success("New item created");
|
||||
}
|
||||
addItem({...formItem, user_created: user, id: uuid, layer: layer});
|
||||
addItem({ ...formItem, user_created: user, id: uuid, layer: layer });
|
||||
setLoading(false);
|
||||
setAddItemPopupType("");
|
||||
}
|
||||
@ -107,61 +108,76 @@ export const OverlayItemsIndexPage = ({url, layerName, parameterField, breadcrum
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
|
||||
|
||||
<MapOverlayPage className='tw-rounded-none tw-overflow-y-auto'>
|
||||
<div className='tw-h-fit'>
|
||||
{breadcrumbs &&
|
||||
<div className="tw-text-sm tw-breadcrumbs">
|
||||
<ul>
|
||||
{breadcrumbs.map((b, i) => <li key={i}><Link to={b.path} >{b.name}</Link></li>)}
|
||||
</ul>
|
||||
</div>}
|
||||
</div>
|
||||
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-6 tw-pt-4">
|
||||
{
|
||||
items?.filter(i=>i.layer?.name === layerName).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))}>
|
||||
<HeaderView loading={loading} item={i} api={layer?.api} itemAvatarField={itemImageField} itemNameField={itemNameField} itemSubnameField={itemSubnameField} 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} />
|
||||
<MapOverlayPage className='tw-rounded-none tw-overflow-y-auto'>
|
||||
<div className='tw-h-fit'>
|
||||
{breadcrumbs &&
|
||||
<div className="tw-text-sm tw-breadcrumbs">
|
||||
<ul>
|
||||
{breadcrumbs.map((b, i) => <li key={i}><Link to={b.path} >{b.name}</Link></li>)}
|
||||
</ul>
|
||||
</div>}
|
||||
</div>
|
||||
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-6 tw-pt-4">
|
||||
{
|
||||
items?.filter(i => i.layer?.name === layerName)
|
||||
.sort((a, b) => {
|
||||
// Convert date_created to milliseconds, handle undefined by converting to lowest possible date (0 milliseconds)
|
||||
const dateA = a.date_updated ? new Date(a.date_updated).getTime() : a.date_created ? new Date(a.date_created).getTime() : 0;
|
||||
const dateB = b.date_updated ? new Date(b.date_updated).getTime() : b.date_created ? new Date(b.date_created).getTime() : 0;
|
||||
return dateB - dateA; // Subtracts milliseconds which are numbers
|
||||
})
|
||||
.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))}>
|
||||
<HeaderView loading={loading} item={i} api={layer?.api} itemAvatarField={itemImageField} itemNameField={itemNameField} itemSubnameField={itemSubnameField} 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 className='tw-flex -tw-mb-1 tw-flex-row tw-mr-2 -tw-mt-2' >
|
||||
|
||||
<p className={`tw-italic tw-min-h-[21px] !tw-my-0 tw-text-gray-500 tw-cursor-pointer`} >{`${i.date_updated && i.date_updated != i.date_created ? "updated" : "posted" } ${i && i.user_created && i.user_created.first_name ? `by ${i.user_created.first_name}` : ""} ${i.date_updated ? timeAgo(i.date_updated) : timeAgo(i.date_created!)}`}</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> */
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
|
||||
})
|
||||
}
|
||||
{addItemPopupType == "place" ?
|
||||
|
||||
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e)} >
|
||||
|
||||
<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={() => {
|
||||
setAddItemPopupType("")
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form> : <></>
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
})
|
||||
}
|
||||
{addItemPopupType == "place" ?
|
||||
|
||||
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e)} >
|
||||
|
||||
<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={() => {
|
||||
setAddItemPopupType("")
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form> : <></>
|
||||
}
|
||||
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
{children}
|
||||
|
||||
|
||||
</MapOverlayPage>
|
||||
</MapOverlayPage>
|
||||
|
||||
|
||||
{plusButton && <PlusButton triggerAction={() => { setAddItemPopupType("place"); scroll(); }} color={'#777'} collection='items' />}
|
||||
{plusButton && <PlusButton triggerAction={() => { setAddItemPopupType("place"); scroll(); }} color={'#777'} collection='items' />}
|
||||
|
||||
</>
|
||||
</>
|
||||
|
||||
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user