* start moving ui to redux tlk * remove unused reducer * changes for gdpr and site types * ui: migrating duck/roles to mobx * ui: drop unreferenced types * ui: drop unreferenced types * ui: move player slice reducer to mobx family * ui: move assignments to issueReportingStore.ts * remove issues store * some fixes after issues store * remove errors reducer, drop old components * finish removing errors reducer * start moving integrations state to mobx * change(ui): funnel duck cleanup * change(ui): custom fields * change(ui): customMetrics cleanup * change(ui): customMetrics cleanup * change(ui): duck/filters minor cleanup * change(ui): duck/filters cleanup * change(ui): duck/customMetrics cleanup and upgrades * fix integrations service, fix babel config to >.25 + not ie * refactoring integrations reducers etc WIP * finish removing integrations state * some fixes for integrated check * start of projects refactoring * move api and "few" files to new project store * new batch for site -> projects * fix setid context * move all critical components, drop site duck * remove all duck/site refs, remove old components * fixup for SessionTags.tsx, remove duck/sources (?) * move session store * init sessionstore outside of context * fix userfilter * replace simple actions for session store * sessions sotre * Rtm temp (#2597) * change(ui): duck/search wip * change(ui): duck/search wip * change(ui): duck/search wip * change(ui): duck/searchLive wip * change(ui): duck/searchLive wip * change(ui): duck/searchLive wip * change(ui): duck/searchLive wip * change(ui): search states * change(ui): search states * change(ui): search states * change(ui): fix savedSearch store * change(ui): fix savedSearch store * some fixes for session connector * change(ui): fix savedSearch store * change(ui): fix searchLive * change(ui): fix searchLive * fixes for session replay * change(ui): bookmark fetch * last components for sessions * add fetchautoplaylist * finish session reducer, remove deleted reducers * change(ui): fix the search fetch * change(ui): fix the search fetch * fix integrations call ctx * ensure ctx for sessionstore * fix(ui): checking for latest sessions path * start removing user reducer * removing user reducer pt2... * finish user store * remove rand log * fix crashes * tinkering workflow file for tracker test * making sure prefetched sessions work properly * fix conflict * fix router redirects during loading --------- Co-authored-by: Shekar Siri <sshekarsiri@gmail.com>
321 lines
8.4 KiB
TypeScript
321 lines
8.4 KiB
TypeScript
import { Tag } from 'antd';
|
|
import { Duration } from 'luxon';
|
|
import React from 'react';
|
|
import { toast } from 'react-toastify';
|
|
import { observer } from 'mobx-react-lite';
|
|
import { useStore } from 'App/mstore';
|
|
import {
|
|
Note,
|
|
TAGS,
|
|
WriteNote,
|
|
iTag,
|
|
tagProps,
|
|
} from 'App/services/NotesService';
|
|
import { Button, Checkbox, Icon } from 'UI';
|
|
|
|
import Select from 'Shared/Select';
|
|
|
|
interface Props {
|
|
time: number;
|
|
isEdit?: boolean;
|
|
editNote?: WriteNote;
|
|
hideModal: () => void;
|
|
}
|
|
|
|
function CreateNote({
|
|
time,
|
|
isEdit,
|
|
editNote,
|
|
hideModal,
|
|
}: Props) {
|
|
const { notesStore, integrationsStore, sessionStore } = useStore();
|
|
const sessionId = sessionStore.current.sessionId;
|
|
const updateNote = sessionStore.updateNote;
|
|
const slackChannels = integrationsStore.slack.list;
|
|
const fetchSlack = integrationsStore.slack.fetchIntegrations;
|
|
const teamsChannels = integrationsStore.msteams.list;
|
|
const fetchTeams = integrationsStore.msteams.fetchIntegrations;
|
|
const [text, setText] = React.useState('');
|
|
const [slackChannel, setSlackChannel] = React.useState('');
|
|
const [teamsChannel, setTeamsChannel] = React.useState('');
|
|
const [isPublic, setPublic] = React.useState(false);
|
|
const [tag, setTag] = React.useState<iTag>(TAGS[0]);
|
|
const [useTimestamp, setUseTs] = React.useState(true);
|
|
const [useSlack, setSlack] = React.useState(false);
|
|
const [useTeams, setTeams] = React.useState(false);
|
|
|
|
const inputRef = React.createRef<HTMLTextAreaElement>();
|
|
|
|
React.useEffect(() => {
|
|
if (isEdit && editNote) {
|
|
setTag(editNote.tag);
|
|
setText(editNote.message);
|
|
setPublic(editNote.isPublic);
|
|
if (editNote.timestamp > 0) {
|
|
setUseTs(true);
|
|
}
|
|
}
|
|
}, [isEdit]);
|
|
|
|
React.useEffect(() => {
|
|
if (inputRef.current) {
|
|
inputRef.current.focus();
|
|
fetchSlack();
|
|
fetchTeams();
|
|
}
|
|
}, []);
|
|
|
|
const duration = Duration.fromMillis(time || 0).toFormat('mm:ss');
|
|
|
|
const cleanUp = () => {
|
|
setText('');
|
|
setTag(TAGS[0]);
|
|
hideModal();
|
|
};
|
|
const onSubmit = () => {
|
|
if (text === '') return;
|
|
|
|
const note: WriteNote = {
|
|
message: text,
|
|
tag,
|
|
timestamp: useTimestamp
|
|
? Math.floor(isEdit && editNote ? editNote.timestamp : time)
|
|
: -1,
|
|
isPublic,
|
|
};
|
|
const onSuccess = (noteId: string) => {
|
|
if (slackChannel) {
|
|
notesStore.sendSlackNotification(noteId, slackChannel);
|
|
}
|
|
if (teamsChannel) {
|
|
notesStore.sendMsTeamsNotification(noteId, teamsChannel);
|
|
}
|
|
};
|
|
if (isEdit && editNote) {
|
|
return notesStore
|
|
.updateNote(editNote.noteId!, note)
|
|
.then((r) => {
|
|
toast.success('Note updated');
|
|
notesStore.fetchSessionNotes(sessionId).then(() => {
|
|
onSuccess(editNote.noteId!);
|
|
updateNote(r as Note);
|
|
});
|
|
})
|
|
.catch((e) => {
|
|
toast.error('Error updating note');
|
|
console.error(e);
|
|
})
|
|
.finally(() => {
|
|
cleanUp();
|
|
});
|
|
} else {
|
|
return notesStore
|
|
.addNote(sessionId, note)
|
|
.then((r) => {
|
|
onSuccess(r!.noteId as unknown as string);
|
|
toast.success('Note added');
|
|
})
|
|
.catch((e) => {
|
|
toast.error('Error adding note');
|
|
console.error(e);
|
|
})
|
|
.finally(() => {
|
|
cleanUp();
|
|
});
|
|
}
|
|
};
|
|
|
|
const closeTooltip = () => {
|
|
hideModal();
|
|
};
|
|
|
|
const tagActive = (noteTag: iTag) => tag === noteTag;
|
|
|
|
const addTag = (tag: iTag) => {
|
|
setTag(tag);
|
|
};
|
|
|
|
const slackChannelsOptions = slackChannels
|
|
.map(({ webhookId, name }) => ({
|
|
value: webhookId,
|
|
label: name,
|
|
})) as unknown as { value: string; label: string }[];
|
|
const teamsChannelsOptions = teamsChannels
|
|
.map(({ webhookId, name }) => ({
|
|
value: webhookId,
|
|
label: name,
|
|
})) as unknown as { value: string; label: string }[];
|
|
|
|
slackChannelsOptions.unshift({
|
|
// @ts-ignore
|
|
value: null,
|
|
// @ts-ignore
|
|
label: <div className={'text-disabled-text'}>Pick a channel</div>,
|
|
disabled: true,
|
|
});
|
|
teamsChannelsOptions.unshift({
|
|
// @ts-ignore
|
|
value: null,
|
|
// @ts-ignore
|
|
label: <div className={'text-disabled-text'}>Pick a channel</div>,
|
|
disabled: true,
|
|
});
|
|
|
|
const changeSlackChannel = ({
|
|
value,
|
|
}: {
|
|
value: Record<string, string>;
|
|
name: string;
|
|
}) => {
|
|
if (value) {
|
|
setSlackChannel(value.value);
|
|
}
|
|
};
|
|
|
|
const changeTeamsChannel = ({
|
|
value,
|
|
}: {
|
|
value: Record<string, string>;
|
|
name: string;
|
|
}) => {
|
|
if (value) {
|
|
setTeamsChannel(value.value);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className={'bg-white h-screen w-full p-4 flex flex-col gap-4'}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center">
|
|
<Icon name="quotes" size={20} />
|
|
<h3 className="text-xl ml-2 mr-4 font-semibold">
|
|
{isEdit ? 'Edit Note' : 'Add Note'}
|
|
</h3>
|
|
<div className="ml-auto cursor-pointer" onClick={closeTooltip}>
|
|
<Icon name="close" size={20} />
|
|
</div>
|
|
</div>
|
|
<div
|
|
className="flex items-center cursor-pointer gap-2"
|
|
onClick={() => setUseTs(!useTimestamp)}
|
|
>
|
|
<Checkbox checked={useTimestamp} />
|
|
<span>Add note at current time frame</span>
|
|
<div className={'border px-1 bg-gray-lightest rounded'}>{duration}</div>
|
|
</div>
|
|
|
|
<div className="">
|
|
<div className={'font-semibold'}>Note</div>
|
|
<textarea
|
|
ref={inputRef}
|
|
name="message"
|
|
id="message"
|
|
placeholder="Enter your note here..."
|
|
rows={3}
|
|
value={text}
|
|
autoFocus
|
|
onChange={(e) => {
|
|
setText(e.target.value);
|
|
}}
|
|
className="text-area"
|
|
/>
|
|
|
|
<div className="flex items-center gap-1" style={{ lineHeight: '15px' }}>
|
|
{TAGS.map((tag) => (
|
|
<Tag
|
|
onClick={() => addTag(tag)}
|
|
key={tag}
|
|
className='cursor-pointer rounded-lg hover:bg-indigo-50'
|
|
color={tagActive(tag) ? tagProps[tag] : undefined}
|
|
bordered={false}
|
|
|
|
>
|
|
<div className={'flex items-center gap-2'}>
|
|
{tagActive(tag) ? (
|
|
<Icon name="check-circle-fill" color="inherit" size={13} />
|
|
) : null}
|
|
{tag}
|
|
</div>
|
|
</Tag>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={'flex items-center gap-2 cursor-pointer'}
|
|
onClick={() => setPublic(!isPublic)}
|
|
>
|
|
<Checkbox checked={isPublic} />
|
|
<div>Visible to team members</div>
|
|
</div>
|
|
{slackChannelsOptions.length > 1 ? (
|
|
<div className="flex flex-col">
|
|
<div
|
|
className="flex items-center cursor-pointer"
|
|
onClick={() => setSlack(!useSlack)}
|
|
>
|
|
<Checkbox checked={useSlack} />
|
|
<span className="ml-1 mr-3"> Share via Slack </span>
|
|
</div>
|
|
|
|
{useSlack && (
|
|
<div>
|
|
<Select
|
|
options={slackChannelsOptions}
|
|
// @ts-ignore
|
|
defaultValue
|
|
// @ts-ignore
|
|
onChange={changeSlackChannel}
|
|
value={slackChannel}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
|
|
{teamsChannelsOptions.length > 1 ? (
|
|
<div className="flex flex-col">
|
|
<div
|
|
className="flex items-center cursor-pointer"
|
|
onClick={() => setTeams(!useTeams)}
|
|
>
|
|
<Checkbox checked={useTeams} />
|
|
<span className="ml-1 mr-3"> Share via MS Teams </span>
|
|
</div>
|
|
|
|
{useTeams && (
|
|
<div>
|
|
<Select
|
|
options={teamsChannelsOptions}
|
|
// @ts-ignore
|
|
defaultValue
|
|
// @ts-ignore
|
|
onChange={changeTeamsChannel}
|
|
value={teamsChannel}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
|
|
<div className="flex">
|
|
<Button
|
|
variant="primary"
|
|
className="mr-4"
|
|
disabled={text === ''}
|
|
onClick={onSubmit}
|
|
>
|
|
{isEdit
|
|
? 'Save Note'
|
|
: `Add Note ${useTeams || useSlack ? '& Share' : ''}`}
|
|
</Button>
|
|
<Button variant={'text'} onClick={closeTooltip}>
|
|
Cancel
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default observer(CreateNote);
|