mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
170 lines
5.3 KiB
TypeScript
170 lines
5.3 KiB
TypeScript
import React, { FunctionComponent, ReactElement, useState } from "react";
|
|
import User from "../../../Models/DatabaseModels/User";
|
|
import { GetReactElementFunction } from "../../Types/FunctionTypes";
|
|
import Image from "../Image/Image";
|
|
import Route from "../../../Types/API/Route";
|
|
import BlankProfilePic from "../../Images/users/blank-profile.svg";
|
|
import UserUtil from "../../Utils/User";
|
|
import ObjectID from "../../../Types/ObjectID";
|
|
import OneUptimeDate from "../../../Types/Date";
|
|
import Tooltip from "../Tooltip/Tooltip";
|
|
import MarkdownViewer from "../Markdown.tsx/MarkdownViewer";
|
|
import Button, { ButtonSize, ButtonStyleType } from "../Button/Button";
|
|
import ConfirmModal from "../Modal/ConfirmModal";
|
|
import Icon from "../Icon/Icon";
|
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
import Color from "../../../Types/Color";
|
|
|
|
export interface FeedItemProps {
|
|
key: string;
|
|
textInMarkdown: string;
|
|
element?: ReactElement;
|
|
moreTextInMarkdown?: string;
|
|
user?: User | undefined;
|
|
itemDateTime: Date;
|
|
icon: IconProp;
|
|
color: Color;
|
|
}
|
|
|
|
export interface ComponentProps extends FeedItemProps {
|
|
isLastItem: boolean;
|
|
}
|
|
|
|
const FeedItem: FunctionComponent<ComponentProps> = (
|
|
props: ComponentProps,
|
|
): ReactElement => {
|
|
const [showMoreInformationModal, setShowMoreInformationModal] =
|
|
useState<boolean>(false);
|
|
|
|
const getMoreInformationModal: GetReactElementFunction = (): ReactElement => {
|
|
if (showMoreInformationModal) {
|
|
return (
|
|
<ConfirmModal
|
|
title={`More Information`}
|
|
description={
|
|
<div>
|
|
<MarkdownViewer text={props.moreTextInMarkdown || ""} />
|
|
</div>
|
|
}
|
|
isLoading={false}
|
|
submitButtonText={"Close"}
|
|
onSubmit={() => {
|
|
return setShowMoreInformationModal(false);
|
|
}}
|
|
submitButtonType={ButtonStyleType.NORMAL}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return <></>;
|
|
};
|
|
|
|
const getUserIcon: GetReactElementFunction = (): ReactElement => {
|
|
const userImageRoute: Route = props.user?.id
|
|
? UserUtil.getProfilePictureRoute(props.user.id as ObjectID)
|
|
: Route.fromString(`${BlankProfilePic}`);
|
|
|
|
return (
|
|
<div>
|
|
<Image
|
|
className="flex size-10 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white"
|
|
imageUrl={userImageRoute}
|
|
/>
|
|
|
|
{props.icon && (
|
|
<span className="absolute -bottom-0.5 -right-1 rounded-tl bg-white px-0.5 py-px">
|
|
<Icon
|
|
className="size-5 text-gray-500"
|
|
icon={props.icon}
|
|
color={props.color}
|
|
/>
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const getItem: GetReactElementFunction = (): ReactElement => {
|
|
return (
|
|
<li key={props.key}>
|
|
<div className="relative pb-8">
|
|
{!props.isLastItem && (
|
|
<span
|
|
className="absolute left-5 top-5 -ml-px h-full w-0.5 bg-gray-200"
|
|
aria-hidden="true"
|
|
></span>
|
|
)}
|
|
<div className="relative flex items-start space-x-3">
|
|
<div className="relative">
|
|
{props.user && getUserIcon()}
|
|
{!props.user && props.icon && getIconItem()}
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<div>
|
|
{props.user?.name && (
|
|
<div className="text-sm">
|
|
<div className="font-medium text-gray-900">
|
|
{props.user?.name?.toString() || "Unknown User"}
|
|
</div>
|
|
</div>
|
|
)}
|
|
<div className="mt-0.5 text-sm text-gray-500 w-fit">
|
|
<Tooltip
|
|
text={OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
props.itemDateTime,
|
|
)}
|
|
>
|
|
<div className="w-fit">
|
|
{OneUptimeDate.fromNow(props.itemDateTime)}
|
|
</div>
|
|
</Tooltip>
|
|
</div>
|
|
</div>
|
|
<div className="mt-2 text-sm text-gray-700">
|
|
{props.textInMarkdown && (
|
|
<div>
|
|
<MarkdownViewer text={props.textInMarkdown} />
|
|
</div>
|
|
)}
|
|
{props.element && <div>{props.element}</div>}
|
|
{props.moreTextInMarkdown && (
|
|
<div className="-ml-3 w-fit">
|
|
<Button
|
|
onClick={() => {
|
|
return setShowMoreInformationModal(true);
|
|
}}
|
|
title="More Information"
|
|
buttonStyle={ButtonStyleType.NORMAL}
|
|
buttonSize={ButtonSize.Small}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{getMoreInformationModal()}
|
|
</li>
|
|
);
|
|
};
|
|
|
|
const getIconItem: GetReactElementFunction = (): ReactElement => {
|
|
if (!props.icon) {
|
|
return <></>;
|
|
}
|
|
return (
|
|
<div className="flex size-10 items-center justify-center rounded-full bg-gray-100 ring-10 ring-white">
|
|
<Icon
|
|
className="size-5 text-gray-500"
|
|
icon={props.icon}
|
|
color={props.color}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return getItem();
|
|
};
|
|
|
|
export default FeedItem;
|