openreplay/frontend/app/components/shared/SessionsTabOverview/components/Notes/NoteItem.tsx
Delirium 2cd96b0df0
Highlight UI (#2951)
* ui: start highlight ui

* ui: tag items

* ui: connecting highlights to notes api...

* Highlight feature refinements (#2948)

* ui: move clips player to foss, connect notes api to hl

* ui: tune note/hl editing, prevent zoom slider body from jumping around

* ui: safe check for tag

* ui: fix thumbnail gen

* ui: fix thumbnail gen

* ui: make player modal wider, add shadow

* ui: custom warn barge for clips

* ui: swap icon for note event wrapper

* ui: rm other, fix cancel

* ui: moving around creation modal

* ui: bg tint

* ui: rm disabled for text btn

* ui: fix ownership sorting

* ui: close player on bg click

* ui: fix query, fix min distance for default range

* ui: move hl list header out of list comp

* ui: spot list header segmented size

* Various improvements in highlights (#2955)

* ui: update hl in hlPanel comp

* ui: rm debug

* ui: fix icons file

---------

Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
2025-01-24 09:59:54 +01:00

100 lines
3.3 KiB
TypeScript

import React from 'react';
import { Link, confirm } from 'UI';
import { tagProps, Note } from 'App/services/NotesService';
import { formatTimeOrDate } from 'App/date';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { ItemMenu } from 'UI';
import copy from 'copy-to-clipboard';
import { toast } from 'react-toastify';
import { session } from 'App/routes';
import TeamBadge from './TeamBadge';
import { Tag } from 'antd'
interface Props {
note: Note;
}
function NoteItem(props: Props) {
const { settingsStore, notesStore } = useStore();
const { timezone } = settingsStore.sessionSettings;
const onCopy = () => {
copy(
`${window.location.origin}/${window.location.pathname.split('/')[1]}${session(
props.note.sessionId
)}${props.note.timestamp > 0 ? `?jumpto=${props.note.timestamp}&note=${props.note.noteId}` : `?note=${props.note.noteId}`}`
);
toast.success('Note URL copied to clipboard');
};
const onDelete = async () => {
if (await confirm({
header: 'Confirm',
confirmButton: 'Yes, delete',
confirmation: `Are you sure you want to delete this note?`,
})) {
notesStore.deleteNote(props.note.noteId).then((r) => {
notesStore.fetchNotes();
toast.success('Note deleted');
});
}
};
const menuItems = [
{ icon: 'link-45deg', text: 'Copy Link', onClick: onCopy },
{ icon: 'trash', text: 'Delete', onClick: onDelete },
];
const safeStrMessage =
props.note.message.length > 150 ? props.note.message.slice(0, 150) + '...' : props.note.message;
return (
<div className="flex items-center px-2 border-b hover:bg-amber-50 justify-between py-2">
<Link
style={{ width: '90%', }}
to={
session(props.note.sessionId) +
(props.note.timestamp > 0
? `?jumpto=${props.note.timestamp}&note=${props.note.noteId}`
: `?note=${props.note.noteId}`)
}
>
<div className="flex flex-col p-2 rounded cursor-pointer justify-between">
<div className="flex py-1 text-base">
{props.note.tag ? (
<Tag
color={tagProps[props.note.tag]}
className='border-0 rounded-lg hover:inherit gap-2 w-14 text-center'
bordered={false}
>
{props.note.tag}
</Tag>
) : null}
<div className='cap-first font-normal'>
{safeStrMessage}
</div>
</div>
<div className="flex items-center">
<div className="flex items-center text-sm text-start">
<span className="text-gray-600 mr-1 capitalize text-start">By </span>
{props.note.userName},{' '}
{formatTimeOrDate(props.note.createdAt as unknown as number, timezone)}
<div className="mx-2" />
{!props.note.isPublic ? null : <TeamBadge />}
</div>
</div>
</div>
</Link>
{/*
<div className="ml-auto">
<PlayLink isAssist={false} viewed={false} sessionId={props.note.sessionId} />
</div> */}
<div className="ml-2 cursor-pointer">
<ItemMenu bold items={menuItems} />
</div>
</div>
);
}
export default observer(NoteItem);