change(ui): notes slack sharing
This commit is contained in:
parent
c3fcda45d4
commit
1122d1daab
7 changed files with 91 additions and 37 deletions
|
|
@ -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 }>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(() => {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue