change(ui): notes slack sharing

This commit is contained in:
sylenien 2022-10-07 17:34:05 +02:00
parent c3fcda45d4
commit 1122d1daab
7 changed files with 91 additions and 37 deletions

View file

@ -2,7 +2,6 @@ import React from 'react';
import { Duration } from 'luxon'; import { Duration } from 'luxon';
import { connectPlayer } from 'Player'; import { connectPlayer } from 'Player';
import styles from './time.module.css'; import styles from './time.module.css';
import { Tooltip } from 'react-tippy';
const Time = ({ time, isCustom, format = 'm:ss', }) => ( const Time = ({ time, isCustom, format = 'm:ss', }) => (
<div className={ !isCustom ? styles.time : undefined }> <div className={ !isCustom ? styles.time : undefined }>

View file

@ -8,6 +8,8 @@ import stl from './styles.module.css';
import { useStore } from 'App/mstore'; import { useStore } from 'App/mstore';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { injectNotes } from 'Player'; import { injectNotes } from 'Player';
import { fetchList as fetchSlack } from 'Duck/integrations/slack';
import Select from 'Shared/Select';
interface Props { interface Props {
isVisible: boolean; isVisible: boolean;
@ -18,6 +20,8 @@ interface Props {
sessionId: string; sessionId: string;
isEdit: string; isEdit: string;
editNote: WriteNote; editNote: WriteNote;
slackChannels: Record<string, string>[];
fetchSlack: () => void;
} }
function CreateNote({ function CreateNote({
@ -29,12 +33,15 @@ function CreateNote({
isEdit, isEdit,
editNote, editNote,
updateNote, updateNote,
slackChannels,
fetchSlack,
}: Props) { }: Props) {
const [text, setText] = React.useState(''); const [text, setText] = React.useState('');
const [channel, setChannel] = React.useState('');
const [isPublic, setPublic] = React.useState(false); const [isPublic, setPublic] = React.useState(false);
const [tag, setTag] = React.useState<iTag>(TAGS[0]); const [tag, setTag] = React.useState<iTag>(TAGS[0]);
const [useTimestamp, setUseTs] = React.useState(true); const [useTimestamp, setUseTs] = React.useState(true);
const inputRef = React.createRef<HTMLTextAreaElement>() const inputRef = React.createRef<HTMLTextAreaElement>();
const { notesStore } = useStore(); const { notesStore } = useStore();
React.useEffect(() => { React.useEffect(() => {
@ -50,14 +57,12 @@ function CreateNote({
React.useEffect(() => { React.useEffect(() => {
if (inputRef.current) { if (inputRef.current) {
inputRef.current.focus() fetchSlack();
inputRef.current.focus();
} }
}, [isVisible]) }, [isVisible]);
const duration = Duration.fromMillis(time).toFormat('mm:ss'); const duration = Duration.fromMillis(time).toFormat('mm:ss');
const stopEvents = (e: any) => {
e.stopPropagation();
};
const onSubmit = () => { const onSubmit = () => {
if (text === '') return; if (text === '') return;
@ -68,29 +73,37 @@ function CreateNote({
timestamp: useTimestamp ? (isEdit ? editNote.timestamp : time) : -1, timestamp: useTimestamp ? (isEdit ? editNote.timestamp : time) : -1,
isPublic, isPublic,
}; };
const onSuccess = (noteId: string) => {
if (channel) {
notesStore.sendSlackNotification(noteId, channel)
}
}
if (isEdit) { if (isEdit) {
return notesStore.updateNote(editNote.noteId, note).then((r) => { return notesStore
toast.success('Note updated'); .updateNote(editNote.noteId, note)
notesStore.fetchSessionNotes(sessionId).then((notes) => { .then((r) => {
injectNotes(notes); toast.success('Note updated');
updateNote(r); notesStore.fetchSessionNotes(sessionId).then((notes) => {
injectNotes(notes);
onSuccess(editNote.noteId)
updateNote(r);
});
})
.catch((e) => {
toast.error('Error updating note');
console.error(e);
})
.finally(() => {
setCreateNoteTooltip({ isVisible: false, time: 0 });
setText('');
setTag(undefined);
}); });
})
.catch((e) => {
toast.error('Error updating note');
console.error(e);
})
.finally(() => {
setCreateNoteTooltip({ isVisible: false, time: 0 });
setText('');
setTag(undefined);
});
} }
return notesStore return notesStore
.addNote(sessionId, note) .addNote(sessionId, note)
.then((r) => { .then((r) => {
onSuccess(r.noteId as unknown as string)
toast.success('Note added'); toast.success('Note added');
notesStore.fetchSessionNotes(sessionId).then((notes) => { notesStore.fetchSessionNotes(sessionId).then((notes) => {
injectNotes(notes); injectNotes(notes);
@ -109,7 +122,7 @@ function CreateNote({
}; };
const closeTooltip = () => { const closeTooltip = () => {
setCreateNoteTooltip({ isVisible: false, time: 0 }); setCreateNoteTooltip({ isVisible: false, time: 100 });
}; };
const tagActive = (noteTag: iTag) => tag === noteTag; const tagActive = (noteTag: iTag) => tag === noteTag;
@ -118,17 +131,27 @@ function CreateNote({
setTag(tag); setTag(tag);
}; };
const slackChannelsOptions = slackChannels.map(({ webhookId, name }) => ({
value: webhookId,
label: name,
}));
const changeChannel = ({ value, name }: { value: string; name: string }) => {
setChannel(value);
};
return ( return (
<div <div
className={stl.noteTooltip} className={stl.noteTooltip}
style={{ style={{
top: -260, top: -320,
width: 350, width: 350,
left: 'calc(50% - 175px)', left: 'calc(50% - 175px)',
display: isVisible ? 'flex' : 'none', display: isVisible ? 'flex' : 'none',
flexDirection: 'column', flexDirection: 'column',
gap: '1rem', gap: '1rem',
}} }}
onClick={(e) => e.stopPropagation()}
> >
<div className="flex items-center bg-gray-lightest"> <div className="flex items-center bg-gray-lightest">
<Icon name="quotes" size={20} /> <Icon name="quotes" size={20} />
@ -176,13 +199,23 @@ function CreateNote({
onClick={() => addTag(tag)} onClick={() => addTag(tag)}
> >
{tagActive(tag) ? <Icon name="check-circle-fill" color="white" size={13} /> : null} {tagActive(tag) ? <Icon name="check-circle-fill" color="white" size={13} /> : null}
<div> <div>{tag}</div>
{tag}
</div>
</div> </div>
))} ))}
</div> </div>
{slackChannelsOptions.length > 0 ? (
<div>
<Select
options={slackChannelsOptions}
defaultValue={"Share to Slack"}
// @ts-ignore
onChange={changeChannel}
className="mr-4"
/>
</div>
) : null}
<div className="flex"> <div className="flex">
<Button variant="primary" className="mr-4" disabled={text === ''} onClick={onSubmit}> <Button variant="primary" className="mr-4" disabled={text === ''} onClick={onSubmit}>
Add Note Add Note
@ -204,11 +237,13 @@ export default connect(
time = 0, time = 0,
isEdit, isEdit,
note: editNote, note: editNote,
// @ts-ignore // @ts-ignore
} = state.getIn(['sessions', 'createNoteTooltip']); } = state.getIn(['sessions', 'createNoteTooltip']);
// @ts-ignore // @ts-ignore
const slackChannels = state.getIn(['slack', 'list']);
// @ts-ignore
const sessionId = state.getIn(['sessions', 'current', 'sessionId']); const sessionId = state.getIn(['sessions', 'current', 'sessionId']);
return { isVisible, time, sessionId, isEdit, editNote }; return { isVisible, time, sessionId, isEdit, editNote, slackChannels };
}, },
{ setCreateNoteTooltip, addNote, updateNote } { setCreateNoteTooltip, addNote, updateNote, fetchSlack }
)(CreateNote); )(CreateNote);

View file

@ -28,7 +28,7 @@ const SET_TIMELINE_POINTER = 'sessions/SET_TIMELINE_POINTER';
const SET_TIMELINE_HOVER_POINTER = 'sessions/SET_TIMELINE_HOVER_POINTER'; const SET_TIMELINE_HOVER_POINTER = 'sessions/SET_TIMELINE_HOVER_POINTER';
const SET_CREATE_NOTE_TOOLTIP = 'sessions/SET_CREATE_NOTE_TOOLTIP' const SET_CREATE_NOTE_TOOLTIP = 'sessions/SET_CREATE_NOTE_TOOLTIP'
const SET_EDIT_NOTE_TOOLTIP = 'sessions/SET_CREATE_NOTE_TOOLTIP' const SET_EDIT_NOTE_TOOLTIP = 'sessions/SET_EDIT_NOTE_TOOLTIP'
const FILTER_OUT_NOTE = 'sessions/FILTER_OUT_NOTE' const FILTER_OUT_NOTE = 'sessions/FILTER_OUT_NOTE'
const ADD_NOTE = 'sessions/ADD_NOTE' const ADD_NOTE = 'sessions/ADD_NOTE'
const UPDATE_NOTE = 'sessions/UPDATE_NOTE' const UPDATE_NOTE = 'sessions/UPDATE_NOTE'

View file

@ -125,4 +125,13 @@ export default class NotesStore {
this.fetchNotes() this.fetchNotes()
} }
async sendSlackNotification(noteId: string, webhook: string) {
try {
const resp = await notesService.sendSlackNotification(noteId, webhook)
return resp
} catch (e) {
console.error(e)
}
}
} }

View file

@ -158,10 +158,10 @@ export default class Player extends MessageDistributor {
} }
} }
jump(time = getState().time, index: number) { jump(setTime: number, index: number) {
const { live, liveTimeTravel, endTime } = getState(); const { live, liveTimeTravel, endTime } = getState();
if (live && !liveTimeTravel) return; if (live && !liveTimeTravel) return;
const time = setTime ? setTime : getState().time
if (getState().playing) { if (getState().playing) {
cancelAnimationFrame(this._animationFrameRequestId); cancelAnimationFrame(this._animationFrameRequestId);
// this._animationFrameRequestId = requestAnimationFrame(() => { // this._animationFrameRequestId = requestAnimationFrame(() => {

View file

@ -1,7 +1,7 @@
import { createStore } from 'redux'; import { createStore } from 'redux';
import reducer, { import reducer, {
update as updateAction, update as updateAction,
clean as cleanAction, clean as cleanAction,
} from './duck'; } from './duck';
const store = createStore(reducer); const store = createStore(reducer);

View file

@ -108,4 +108,15 @@ export default class NotesService {
} }
}) })
} }
sendSlackNotification(noteId: number, webhook: string) {
return this.client.get(`/notes/${noteId}/slack/${webhook}`)
.then(r => {
if (r.ok) {
return r.json().then(r => r.data)
} else {
throw new Error('Error sending slack notif: ' + r.status)
}
})
}
} }