change(ui): notes ui changes, filtering change, link change to session, link note to session with note on click
This commit is contained in:
parent
a04ff25381
commit
9eae28e09e
14 changed files with 127 additions and 89 deletions
|
|
@ -11,7 +11,7 @@ import { setEditNoteTooltip } from 'Duck/sessions';
|
|||
|
||||
// TODO: incapsulate toggler in LocationEvent
|
||||
@withToggle("showLoadInfo", "toggleLoadInfo")
|
||||
@connect(state => ({members: state.getIn(['members', 'list']), currentUserId: state.getIn(['account', 'id']) }), { setEditNoteTooltip })
|
||||
@connect(state => ({members: state.getIn(['members', 'list']), currentUserId: state.getIn(['user', 'account', 'id']) }), { setEditNoteTooltip })
|
||||
class EventGroupWrapper extends React.Component {
|
||||
|
||||
toggleLoadInfo = (e) => {
|
||||
|
|
@ -52,6 +52,8 @@ class EventGroupWrapper extends React.Component {
|
|||
|
||||
const whiteBg = isLastInGroup && event.type !== TYPES.LOCATION || (!isLastEvent && event.type !== TYPES.LOCATION)
|
||||
const safeRef = String(event.referrer || '');
|
||||
|
||||
console.log(this.props.currentUserId, event.userId)
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ function NoteEvent(props: Props) {
|
|||
const { settingsStore, notesStore } = useStore();
|
||||
const { timezone } = settingsStore.sessionSettings;
|
||||
|
||||
console.log(props.noEdit)
|
||||
const onEdit = () => {
|
||||
props.onEdit({
|
||||
isVisible: true,
|
||||
|
|
@ -40,14 +41,14 @@ function NoteEvent(props: Props) {
|
|||
isPublic: props.isPublic,
|
||||
message: props.message,
|
||||
sessionId: props.sessionId,
|
||||
noteId: props.noteId
|
||||
noteId: props.noteId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onCopy = () => {
|
||||
copy(
|
||||
`${window.location.origin}${session(props.sessionId)}${
|
||||
`${window.location.origin}/${window.location.pathname.split('/')[1]}${session(props.sessionId)}${
|
||||
props.timestamp > 0 ? '?jumpto=' + props.timestamp : ''
|
||||
}`
|
||||
);
|
||||
|
|
@ -70,7 +71,7 @@ function NoteEvent(props: Props) {
|
|||
}
|
||||
};
|
||||
const menuItems = [
|
||||
{ icon: 'pencil', text: 'Edit', onClick: onEdit, disabled: props.onEdit },
|
||||
{ icon: 'pencil', text: 'Edit', onClick: onEdit, disabled: props.noEdit },
|
||||
{ icon: 'link-45deg', text: 'Copy URL', onClick: onCopy },
|
||||
{ icon: 'trash', text: 'Delete', onClick: onDelete },
|
||||
];
|
||||
|
|
@ -101,8 +102,13 @@ function NoteEvent(props: Props) {
|
|||
{props.tags.map((tag) => (
|
||||
<div
|
||||
key={tag}
|
||||
style={{ background: tagProps[tag], userSelect: 'none' }}
|
||||
className="rounded-xl text-sm px-2 py-1 text-white"
|
||||
style={{
|
||||
background: tagProps[tag],
|
||||
userSelect: 'none',
|
||||
minWidth: 60,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
className="rounded-full text-sm px-2 py-1 text-white"
|
||||
>
|
||||
{tag}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -227,10 +227,12 @@ export default class Timeline extends React.PureComponent {
|
|||
background: 'white',
|
||||
zIndex: 3,
|
||||
pointerEvents: 'none',
|
||||
height: 10,
|
||||
width: 16,
|
||||
left: `${getTimelinePosition(note.timestamp, scale)}%`,
|
||||
}}
|
||||
>
|
||||
<Icon name="quotes" size={16} color="main" />
|
||||
<Icon name="quotes" style={{ width: 16, height: 10 }} color="main" />
|
||||
</div>
|
||||
) : null)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ function CreateNote({
|
|||
const [text, setText] = React.useState('');
|
||||
const [isPublic, setPublic] = React.useState(false);
|
||||
const [tags, setTags] = React.useState([]);
|
||||
const [useTimestamp, setUseTs] = React.useState(false);
|
||||
const [useTimestamp, setUseTs] = React.useState(true);
|
||||
|
||||
const { notesStore } = useStore();
|
||||
|
||||
|
|
@ -105,11 +105,9 @@ function CreateNote({
|
|||
};
|
||||
|
||||
const tagActive = (tag: iTag) => tags.includes(tag);
|
||||
const removeTag = (tag: iTag) => {
|
||||
setTags(tags.filter((t) => t !== tag));
|
||||
};
|
||||
|
||||
const addTag = (tag: iTag) => {
|
||||
setTags([...tags, tag]);
|
||||
setTags([tag]);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -145,6 +143,7 @@ function CreateNote({
|
|||
placeholder="Note..."
|
||||
rows={3}
|
||||
value={text}
|
||||
autoFocus
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
style={{
|
||||
border: 'solid thin #ddd',
|
||||
|
|
@ -162,9 +161,11 @@ function CreateNote({
|
|||
style={{
|
||||
background: tagActive(tag) ? tagProps[tag] : 'rgba(0,0,0, 0.38)',
|
||||
userSelect: 'none',
|
||||
minWidth: 60,
|
||||
textAlign: 'center'
|
||||
}}
|
||||
className="cursor-pointer rounded-xl px-2 py-1 mr-2 text-white"
|
||||
onClick={() => (tagActive(tag) ? removeTag(tag) : addTag(tag))}
|
||||
className="cursor-pointer rounded-full px-2 py-1 mr-2 text-white"
|
||||
onClick={() => addTag(tag)}
|
||||
>
|
||||
{tag}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ function ReadNote(props: Props) {
|
|||
return (
|
||||
<div style={{ position: 'absolute', top: '45%', left: 'calc(50% - 200px)' }}>
|
||||
<div
|
||||
className="flex items-start flex-col p-4 border gap-2"
|
||||
className="flex items-start flex-col p-4 border gap-2 rounded"
|
||||
style={{ background: '#FFFEF5', width: 400 }}
|
||||
>
|
||||
<div className="flex items-start font-semibold w-full text-xl">
|
||||
|
|
@ -50,8 +50,8 @@ function ReadNote(props: Props) {
|
|||
return (
|
||||
<div style={{ position: 'absolute', top: '45%', left: 'calc(50% - 300px)' }}>
|
||||
<div
|
||||
className="flex items-start flex-col p-4 border gap-2"
|
||||
style={{ background: '#FFFEF5', width: 600 }}
|
||||
className="flex items-start !text-lg flex-col p-4 border gap-2 rounded"
|
||||
style={{ background: '#FFFEF5', width: 500 }}
|
||||
>
|
||||
<div className="flex items-center w-full">
|
||||
<div className="p-2 bg-gray-light rounded-full">
|
||||
|
|
@ -63,7 +63,7 @@ function ReadNote(props: Props) {
|
|||
{formatTimeOrDate(props.date as unknown as number, timezone)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-auto cursor-pointer" onClick={props.onClose}>
|
||||
<div className="ml-auto cursor-pointer self-start" onClick={props.onClose}>
|
||||
<Icon name="close" size={18} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@
|
|||
.noteTooltip {
|
||||
position: absolute;
|
||||
padding: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
background: #F5F5F5;
|
||||
top: -35px;
|
||||
color: black;
|
||||
border-radius: 12px;
|
||||
cursor: default;
|
||||
box-shadow: 0 4px 20px 4px rgb(0 20 60 / 10%), 0 4px 80px -8px rgb(0 20 60 / 20%);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,37 @@
|
|||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import cn from 'classnames';
|
||||
import { Icon } from 'UI';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import cls from './PlayIconLayer.module.css';
|
||||
import clsOv from './overlay.module.css';
|
||||
|
||||
interface Props {
|
||||
togglePlay: () => void,
|
||||
playing: boolean,
|
||||
togglePlay: () => void;
|
||||
playing: boolean;
|
||||
notesEdit: boolean;
|
||||
}
|
||||
|
||||
export default function PlayIconLayer({ playing, togglePlay }: Props) {
|
||||
const [ showPlayOverlayIcon, setShowPlayOverlayIcon ] = useState(false);
|
||||
function PlayIconLayer({ playing, togglePlay, notesEdit }: Props) {
|
||||
const [showPlayOverlayIcon, setShowPlayOverlayIcon] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// TODO Find a better way to do this
|
||||
document.addEventListener('keydown', onKeyDown);
|
||||
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', onKeyDown);
|
||||
}
|
||||
}, [])
|
||||
};
|
||||
}, [notesEdit]);
|
||||
|
||||
const onKeyDown = (e) => {
|
||||
const getIsEdit = React.useCallback(() => notesEdit, [notesEdit])
|
||||
|
||||
const onKeyDown = (e: any) => {
|
||||
console.log(getIsEdit())
|
||||
if (getIsEdit()) return;
|
||||
if (e.key === ' ') {
|
||||
togglePlayAnimated()
|
||||
togglePlayAnimated();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const togglePlayAnimated = useCallback(() => {
|
||||
setShowPlayOverlayIcon(true);
|
||||
|
|
@ -35,18 +40,19 @@ export default function PlayIconLayer({ playing, togglePlay }: Props) {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className={ clsOv.overlay } onClick={ togglePlayAnimated }>
|
||||
<div
|
||||
className={ cn(cls.iconWrapper, {
|
||||
[ cls.zoomIcon ]: showPlayOverlayIcon
|
||||
}) }
|
||||
<div className={clsOv.overlay} onClick={togglePlayAnimated}>
|
||||
<div
|
||||
className={cn(cls.iconWrapper, {
|
||||
[cls.zoomIcon]: showPlayOverlayIcon,
|
||||
})}
|
||||
>
|
||||
<Icon
|
||||
name={ playing ? "play" : "pause" }
|
||||
color="gray-medium"
|
||||
size={30}
|
||||
/>
|
||||
<Icon name={playing ? 'play' : 'pause'} color="gray-medium" size={30} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect((state) => ({
|
||||
// @ts-ignore
|
||||
notesEdit: state.getIn(['sessions', 'createNoteTooltip', 'isVisible']),
|
||||
}))(PlayIconLayer);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ function NotePopup({ setCreateNoteTooltip, time }: { setCreateNoteTooltip: (args
|
|||
setCreateNoteTooltip({ time: time, isVisible: true })
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => setCreateNoteTooltip({ time: -1, isVisible: false })
|
||||
})
|
||||
return (
|
||||
<div
|
||||
onClick={toggleNotePopup}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Icon } from 'UI';
|
||||
import { Icon, Link } from 'UI';
|
||||
import PlayLink from 'Shared/SessionItem/PlayLink';
|
||||
import { tagProps, iTag } from 'App/services/NotesService';
|
||||
import { formatTimeOrDate } from 'App/date';
|
||||
|
|
@ -8,7 +8,7 @@ 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 { session } from 'App/routes';
|
||||
|
||||
interface Props {
|
||||
userId: number;
|
||||
|
|
@ -27,63 +27,73 @@ function NoteItem(props: Props) {
|
|||
const { timezone } = settingsStore.sessionSettings;
|
||||
|
||||
const onCopy = () => {
|
||||
copy(`${window.location.origin}${session(props.sessionId)}${props.timestamp > 0 ? '?jumpto=' + props.timestamp : ''}`);
|
||||
toast.success('Note URL copied to clipboard')
|
||||
}
|
||||
copy(
|
||||
`${window.location.origin}/${window.location.pathname.split('/')[1]}${session(
|
||||
props.sessionId
|
||||
)}${props.timestamp > 0 ? '?jumpto=' + props.timestamp : ''}`
|
||||
);
|
||||
toast.success('Note URL copied to clipboard');
|
||||
};
|
||||
const onDelete = () => {
|
||||
notesStore.deleteNote(props.noteId).then(r => {
|
||||
notesStore.fetchNotes()
|
||||
toast.success('Note deleted')
|
||||
})
|
||||
notesStore.deleteNote(props.noteId).then((r) => {
|
||||
notesStore.fetchNotes();
|
||||
toast.success('Note deleted');
|
||||
});
|
||||
};
|
||||
const menuItems = [
|
||||
{ icon: 'link-45deg', text: 'Copy URL', onClick: onCopy },
|
||||
{ icon: 'trash', text: 'Delete', onClick: onDelete },
|
||||
]
|
||||
];
|
||||
return (
|
||||
<div
|
||||
className="flex items-center p-4 border-b"
|
||||
style={{ background: 'rgba(253, 243, 155, 0.1)' }}
|
||||
>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div>{props.description}</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{props.tags.length ? (
|
||||
<div className="flex items-center gap-1">
|
||||
{props.tags.map((tag) => (
|
||||
<div
|
||||
key={tag}
|
||||
style={{ background: tagProps[tag], userSelect: 'none' }}
|
||||
className="rounded-xl px-2 py-1 mr-2 text-white"
|
||||
>
|
||||
{tag}
|
||||
</div>
|
||||
))}
|
||||
<Link style={{ width: '90%' }} to={session(props.sessionId)+(props.timestamp > 0 ? `?jumpto=${props.timestamp}¬e=${props.noteId}` : '')}>
|
||||
<div className="flex flex-col gap-1 cursor-pointer">
|
||||
<div>{props.description}</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{props.tags.length ? (
|
||||
<div className="flex items-center gap-1">
|
||||
{props.tags.map((tag) => (
|
||||
<div
|
||||
key={tag}
|
||||
style={{
|
||||
background: tagProps[tag],
|
||||
userSelect: 'none',
|
||||
minWidth: 60,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
className="rounded-full px-2 py-1 mr-2 text-white"
|
||||
>
|
||||
{tag}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="text-disabled-text flex items-center">
|
||||
<span className="text-figmaColors-text-primary mr-1">By </span>
|
||||
{props.userEmail}, {formatTimeOrDate(props.date as unknown as number, timezone)}
|
||||
{!props.isPublic ? null : (
|
||||
<>
|
||||
<Icon name="user-friends" className="ml-4 mr-1" color="gray-dark" /> Team
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="text-disabled-text flex items-center">
|
||||
<span className="text-figmaColors-text-primary mr-1">By </span>
|
||||
{props.userEmail}, {formatTimeOrDate(props.date as unknown as number, timezone)}
|
||||
{!props.isPublic ? null : (
|
||||
<>
|
||||
<Icon name="user-friends" className="ml-4 mr-1" color="gray-dark" /> Team
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="ml-auto">
|
||||
<PlayLink
|
||||
isAssist={false}
|
||||
viewed={false}
|
||||
sessionId={props.sessionId + (props.timestamp > 0 ? `?jumpto=${props.timestamp}¬e=${props.noteId}` : '')}
|
||||
sessionId={
|
||||
props.sessionId
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-2 cursor-pointer">
|
||||
<ItemMenu
|
||||
bold
|
||||
items={menuItems}
|
||||
/>
|
||||
<ItemMenu bold items={menuItems} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ function NotesList({ members }: {members: Array<Record<string, any>>}) {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<div className="mt-3 border-b rounded bg-white">
|
||||
<div className="border-b rounded bg-white">
|
||||
{sliceListPerPage(list, notesStore.page - 1, notesStore.pageSize).map(note => (
|
||||
<React.Fragment key={note.noteId}>
|
||||
<NoteItem
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ function NoteTags() {
|
|||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div>
|
||||
<TagItem
|
||||
onClick={() => notesStore.toggleTag()}
|
||||
label="ALL"
|
||||
isActive={notesStore.activeTags.length === 0}
|
||||
/>
|
||||
</div>
|
||||
{TAGS.map((tag: iTag) => (
|
||||
<div key={tag}>
|
||||
<TagItem
|
||||
|
|
@ -26,7 +33,7 @@ function NoteTags() {
|
|||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="ml-2" />
|
||||
<Select name="sortSessions" plain right options={sortOptions} onChange={({ value }) => notesStore.toggleSort(value.value)} defaultValue={defaultOption} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ function SessionHeader(props: Props) {
|
|||
return (
|
||||
<div className="flex items-center px-4 justify-between">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="mr-3 text-lg flex items-center gap-2">
|
||||
<div className="mr-3 text-lg flex items-center gap-4">
|
||||
<Tab
|
||||
onClick={() => props.setActiveTab({ type: 'all' })}
|
||||
addBorder={activeTab === 'all'}
|
||||
|
|
|
|||
|
|
@ -100,12 +100,12 @@ export default class NotesStore {
|
|||
this.page = page
|
||||
}
|
||||
|
||||
toggleTag(tag: iTag) {
|
||||
if (this.activeTags.includes(tag)) {
|
||||
this.activeTags = this.activeTags.filter(exTag => tag !== exTag)
|
||||
toggleTag(tag?: iTag) {
|
||||
if (!tag) {
|
||||
this.activeTags = []
|
||||
this.fetchNotes()
|
||||
} else {
|
||||
this.activeTags = [...this.activeTags, tag]
|
||||
this.activeTags = [tag]
|
||||
this.fetchNotes()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ export const tagProps = {
|
|||
'ISSUE': '#CC0000',
|
||||
'TASK': '#7986CB',
|
||||
'OTHER': 'rgba(0, 0, 0, 0.26)',
|
||||
'ALL': ''
|
||||
}
|
||||
|
||||
export type iTag = keyof typeof tagProps
|
||||
export type iTag = keyof typeof tagProps | "ALL"
|
||||
|
||||
export const TAGS = Object.keys(tagProps) as unknown as (keyof typeof tagProps)[]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue