diff --git a/frontend/app/components/Session_/Autoplay/Autoplay.js b/frontend/app/components/Session_/Autoplay/Autoplay.js index 2e147672e..8ce20e11c 100644 --- a/frontend/app/components/Session_/Autoplay/Autoplay.js +++ b/frontend/app/components/Session_/Autoplay/Autoplay.js @@ -17,7 +17,7 @@ function Autoplay(props) { return (
-
+
void; + session: Record; + width: number; + height: number; +} + +function BugReportModal({ hideModal, session, width, height }: Props) { + const { + userBrowser, + userDevice, + userCountry, + userBrowserVersion, + userOs, + userOsVersion, + userDisplayName, + userDeviceType, + revId, + metadata, + sessionId, + } = session; + + console.log(session.toJS()) + const envObject = { + Device: `${userDevice}${userDeviceType !== userDevice ? ` ${userDeviceType}` : ''}`, + Resolution: `${width}x${height}`, + Browser: `${userBrowser} v${userBrowserVersion}`, + OS: `${userOs} v${userOsVersion}`, + // @ts-ignore + Country: countries[userCountry], + }; + if (revId) { + Object.assign(envObject, { Rev: revId }) + } + return ( +
+ + <MetaInfo envObject={envObject} metadata={metadata} /> + <Session user={userDisplayName} sessionId={sessionId} /> + </div> + ); +} + +function Title() { + return ( + <div className="flex items-center py-2 px-3 justify-between bg-gray-lightest rounded"> + <div className="flex flex-col gap-2"> + <div>Title</div> + <div className="text-gray-medium">By author</div> + </div> + <div> + <div>Severity</div> + <div>select here</div> + </div> + </div> + ); +} + +interface EnvObj { + Device: string; + Resolution: string; + Browser: string; + OS: string; + Country: string; + Rev?: string; +} + +function MetaInfo({ envObject, metadata }: { envObject: EnvObj, metadata: Record<string, any> }) { + return ( + <div className="flex gap-8"> + <div className="flex flex-col gap-2"> + <SectionTitle>Environment</SectionTitle> + {Object.keys(envObject).map((envTag) => ( + <div className="flex items-center"> + <div className="py-1 px-2">{envTag}</div> + <div className="py-1 px-2 text-gray-medium bg-light-blue-bg rounded"> + {/* @ts-ignore */} + {envObject[envTag]} + </div> + </div> + ))} + </div> + + <div className="flex flex-col gap-2"> + <SectionTitle>Metadata</SectionTitle> + {Object.keys(metadata).map((meta) => ( + <div className="flex items-center rounded overflow-hidden bg-gray-lightest"> + <div className="bg-gray-light-shade py-1 px-2">{meta}</div> + <div className="py-1 px-2 text-gray-medium">{metadata[meta]}</div> + </div> + ))} + </div> + </div> + ); +} + +function Session({ user, sessionId }: { user: string, sessionId: string }) { + return ( + <div> + <SectionTitle>Session recording</SectionTitle> + <div className="border rounded flex items-center justify-between p-2"> + <div className="flex flex-col"> + <div className="text-lg">{user}</div> + <div className="text-disabled-text"> + {`${window.location.origin}/${window.location.pathname.split('/')[1]}${sessionRoute(sessionId)}`} + </div> + </div> + <PlayLink isAssist={false} viewed={false} sessionId={sessionId} /> + </div> + </div> + ); +} + +function SectionTitle({ children }: { children: React.ReactNode }) { + return <div className="text-xl font-semibold mb-2">{children}</div>; +} + +const WithUIState = connect((state) => ({ session: state.getIn(['sessions', 'current']) }))( + BugReportModal +); + +export default WithUIState diff --git a/frontend/app/components/Session_/BugReport/types.ts b/frontend/app/components/Session_/BugReport/types.ts new file mode 100644 index 000000000..3b514eb05 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/types.ts @@ -0,0 +1,69 @@ +export interface BugReportPdf { + author: string; + env: EnvData; + meta: { + [key: string]: string; + }; + session: { + user: string; + url: string; + id: string; + }; + comment?: string; + steps: Step[]; + activity: { + network: NetworkError[]; + console: ConsoleError[]; + clickRage: ClickRage[]; + }; +} + +export interface EnvData { + browser: string; + os: string; + country: string; + device: string; + resolution: string; +} + +export interface NetworkError { + time: number; +} + +export interface ConsoleError { + time: number; +} + +export interface ClickRage { + time: number; +} + +export interface Step { + type: string; + icon: string; + details: string; + substeps?: SubStep[]; +} + +export type SubStep = Note | Error | Request; + +export interface Note { + author: string; + message: string; + step: 'note'; +} + +export interface Error { + timestamp: string; + error: string; + step: 'error'; +} + +export interface Request { + url: string; + status: number; + type: 'GET' | 'POST' | 'PUT' | 'DELETE'; + time: number; + name: string; + step: 'request'; +} diff --git a/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js b/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js index 480cd4e67..61684db5d 100644 --- a/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js +++ b/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js @@ -110,13 +110,6 @@ function UserCard({ className, request, session, width, height, similarSessions, </div> </div> </div> - - {/* <SlideModal - title={ <div>User Sessions</div> } - isDisplayed={ showUserSessions } - content={ showUserSessions && <SessionList similarSessions={ similarSessions } loading={ loading } /> } - onClose={ () => showUserSessions ? setShowUserSessions(false) : null } - /> */} </div> ); } diff --git a/frontend/app/components/Session_/Subheader.js b/frontend/app/components/Session_/Subheader.js index 446311a29..af4f34680 100644 --- a/frontend/app/components/Session_/Subheader.js +++ b/frontend/app/components/Session_/Subheader.js @@ -7,11 +7,14 @@ import copy from 'copy-to-clipboard'; import { Tooltip } from 'react-tippy'; import Issues from './Issues/Issues'; import NotePopup from './components/NotePopup'; -import { connectPlayer } from 'Player'; +import { connectPlayer, pause } from 'Player'; +import ItemMenu from './components/HeaderMenu'; +import { useModal } from 'App/components/Modal'; +import BugReportModal from './BugReport/BugReportModal'; function SubHeader(props) { const [isCopied, setCopied] = React.useState(false); - + const { showModal, hideModal } = useModal(); const isAssist = window.location.pathname.includes('/assist/'); const location = @@ -19,6 +22,11 @@ function SubHeader(props) { ? `${props.currentLocation.slice(0, 60)}...` : props.currentLocation; + const showReportModal = () => { + pause(); + showModal(<BugReportModal width={props.width} height={props.height} hideModal={hideModal} />, { right: true }); + }; + return ( <div className="w-full px-4 py-2 flex items-center border-b"> {location && ( @@ -45,39 +53,62 @@ function SubHeader(props) { )} {!isAssist ? ( <div - className="ml-auto text-sm flex items-center color-gray-medium" + className="ml-auto text-sm flex items-center color-gray-medium gap-2" style={{ width: 'max-content' }} > - <NotePopup /> - <div className="cursor-pointer mr-4 hover:bg-gray-light-shade rounded-md p-1"> - {props.jiraConfig && props.jiraConfig.token && <Issues sessionId={props.sessionId} />} - </div> - <div className="cursor-pointer"> - <SharePopup - entity="sessions" - id={props.sessionId} - showCopyLink={true} - trigger={ - <div className="flex items-center hover:bg-gray-light-shade rounded-md p-1"> - <Icon className="mr-2" disabled={props.disabled} name="share-alt" size="16" /> - <span>Share</span> - </div> - } - /> - </div> - <div className="mx-4 hover:bg-gray-light-shade rounded-md p-1"> - <Bookmark noMargin sessionId={props.sessionId} /> + <div + onClick={showReportModal} + className="cursor-pointer rounded flex items-center p-2 gap-1 hover:bg-gray-light-shade" + > + <Icon name="file-pdf" size={16} /> + <span>Create Bug Report</span> </div> + <ItemMenu + items={[ + { key: 1, component: <NotePopup /> }, + { + key: 2, + component: props.jiraConfig && props.jiraConfig.token && ( + <Issues sessionId={props.sessionId} /> + ), + }, + { + key: 3, + component: ( + <SharePopup + entity="sessions" + id={props.sessionId} + showCopyLink={true} + trigger={ + <div className="flex items-center"> + <Icon + className="mr-2" + disabled={props.disabled} + name="share-alt" + size="16" + /> + <span>Share</span> + </div> + } + /> + ), + }, + { + key: 4, + component: <Bookmark noMargin sessionId={props.sessionId} />, + }, + ]} + /> + <div> <Autoplay /> </div> - <div></div> </div> ) : null} </div> ); } -const SubH = connectPlayer((state) => ({ currentLocation: state.location }))(SubHeader); +const SubH = connectPlayer((state) => ({ width: state.width, height: state.height, currentLocation: state.location }))(SubHeader); export default React.memo(SubH); diff --git a/frontend/app/components/Session_/components/HeaderMenu.tsx b/frontend/app/components/Session_/components/HeaderMenu.tsx new file mode 100644 index 000000000..7b72f4dc0 --- /dev/null +++ b/frontend/app/components/Session_/components/HeaderMenu.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { Icon } from 'UI'; +import styles from './menu.module.css'; +import cn from 'classnames'; + +interface MenuItem { + key: number; + component?: React.ReactElement; +} + +interface Props { + items: MenuItem[]; +} + +export default class ItemMenu extends React.PureComponent<Props> { + state = { + displayed: false, + }; + + handleEsc = (e: KeyboardEvent) => e.key === 'Escape' && this.state.displayed && this.toggleMenu(); + + componentDidMount() { + document.addEventListener('keydown', this.handleEsc, false); + } + componentWillUnmount() { + document.removeEventListener('keydown', this.handleEsc, false); + } + + toggleMenu = () => { + this.setState({ displayed: !this.state.displayed }); + }; + + render() { + const { items } = this.props; + const { displayed } = this.state; + + return ( + <div className={styles.wrapper}> + <div + onClick={this.toggleMenu} + className={cn( + 'flex items-center cursor-pointer select-none', + 'rounded p-2 hover:bg-gray-light-shade', + { + 'bg-gray-light': displayed, + } + )} + > + <div + className={cn('rounded-full flex items-center justify-center', { + 'bg-gray-light': displayed, + })} + role="button" + > + <Icon name="ellipsis-v" size="16" /> + </div> + <span className={'mr-1 text-disabled-text'}>More</span> + </div> + <div className={cn(styles.menu, styles.menuDim)} data-displayed={displayed}> + {items.map((item) => + item.component ? ( + <div + key={item.key} + role="menuitem" + className="w-full h-full p-3 hover:bg-gray-light-shade cursor-pointer flex items-center" + > + {item.component} + </div> + ) : null + )} + </div> + </div> + ); + } +} diff --git a/frontend/app/components/Session_/components/NotePopup.tsx b/frontend/app/components/Session_/components/NotePopup.tsx index c5c7b7016..ac4e18ee5 100644 --- a/frontend/app/components/Session_/components/NotePopup.tsx +++ b/frontend/app/components/Session_/components/NotePopup.tsx @@ -28,7 +28,7 @@ function NotePopup({ <div onClick={toggleNotePopup} className={cn( - 'mr-4 hover:bg-gray-light-shade rounded-md p-1 flex items-center', + 'mr-4 hover:bg-gray-light-shade rounded-md flex items-center', tooltipActive ? 'cursor-not-allowed' : 'cursor-pointer' )} > diff --git a/frontend/app/components/Session_/components/menu.module.css b/frontend/app/components/Session_/components/menu.module.css new file mode 100644 index 000000000..857d810d4 --- /dev/null +++ b/frontend/app/components/Session_/components/menu.module.css @@ -0,0 +1,102 @@ +@import 'icons.css'; + +.wrapper { + position: relative; + display: inline-block; +} + +.menuBtn { + @mixin icon-before ellipsis-v, $gray-darkest, 18px { + margin: 5px; + } + width: 36px; + height: 36px; + border-radius: 18px; + border: 1px solid transparent; + transition: all 0.2s; + margin: 0 auto; + cursor: pointer; + + &:hover { + border-color: $active-blue-border; + transition: all 0.2s; + background-color: #fff; + } +} + +.menuDim { + border: none!important; + box-shadow: 0 1px 3px 0 $gray-light!important; + + & .menuItem { + color: $gray-dark!important; + } +} + +.menu { + &[data-displayed=false] { + display: none; + } + + white-space: nowrap; + z-index: 20; + position: absolute; + right: 0px; + top: 37px; + min-width: 150px; + background-color: $white; + border-radius: 3px; + border: 1px solid rgba(34,36,38,.15); + box-shadow: 0 2px 3px 0 rgb(34 36 38 / 15%); + + + & .menuItem { + cursor: pointer; + padding: 10px; + color: black; + display: flex; + align-items: center; + border-bottom: 1px solid $gray-light; + position: relative; + + & .iconWrapper { + width: 13px; + height: 13px ; + margin-right: 8px; + } + + &:hover { + background-color: $active-blue; + } + + &:last-child { + border: none; + } + + & .edit { + @mixin icon pencil, $gray-medium, 15px; + margin-right: 10px; + } + + & .copy { + @mixin icon copy, $gray-medium, 15px; + margin-right: 10px; + } + + & .remove { + @mixin icon trash, $gray-medium, 15px; + margin-right: 10px; + } + + & .enabled { + @mixin icon eye, $gray-medium, 15px; + margin-right: 10px; + } + + & .disabled { + @mixin icon eye-slash, $gray-medium, 15px; + margin-right: 10px; + } + + } +} diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index 1d3387c8f..fd1703577 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -1,7 +1,7 @@ import React from 'react'; -export type IconNames = 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-bar-left' | 'arrow-clockwise' | 'arrow-down' | 'arrow-repeat' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_bear' | 'avatar/icn_beaver' | 'avatar/icn_bird' | 'avatar/icn_bison' | 'avatar/icn_camel' | 'avatar/icn_chameleon' | 'avatar/icn_deer' | 'avatar/icn_dog' | 'avatar/icn_dolphin' | 'avatar/icn_elephant' | 'avatar/icn_fish' | 'avatar/icn_fox' | 'avatar/icn_gorilla' | 'avatar/icn_hippo' | 'avatar/icn_horse' | 'avatar/icn_hyena' | 'avatar/icn_kangaroo' | 'avatar/icn_lemur' | 'avatar/icn_mammel' | 'avatar/icn_monkey' | 'avatar/icn_moose' | 'avatar/icn_panda' | 'avatar/icn_penguin' | 'avatar/icn_porcupine' | 'avatar/icn_quail' | 'avatar/icn_rabbit' | 'avatar/icn_rhino' | 'avatar/icn_sea_horse' | 'avatar/icn_sheep' | 'avatar/icn_snake' | 'avatar/icn_squirrel' | 'avatar/icn_tapir' | 'avatar/icn_turtle' | 'avatar/icn_vulture' | 'avatar/icn_wild1' | 'avatar/icn_wild_bore' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'bell-fill' | 'bell-plus' | 'bell-slash' | 'bell' | 'binoculars' | 'book' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'call' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-right-text' | 'chat-square-quote' | 'check-circle-fill' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'clipboard-list-check' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-front' | 'cubes' | 'dashboard-icn' | 'desktop' | 'device' | 'diagram-3' | 'dizzy' | 'door-closed' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'enter' | 'envelope' | 'errors-icon' | 'event/click' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/link' | 'event/location' | 'event/resize' | 'event/view' | 'exclamation-circle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'file-code' | 'file-medical-alt' | 'file' | 'filter' | 'filters/arrow-return-right' | 'filters/browser' | 'filters/click' | 'filters/clickrage' | 'filters/code' | 'filters/console' | 'filters/country' | 'filters/cpu-load' | 'filters/custom' | 'filters/device' | 'filters/dom-complete' | 'filters/duration' | 'filters/error' | 'filters/fetch-failed' | 'filters/fetch' | 'filters/file-code' | 'filters/graphql' | 'filters/i-cursor' | 'filters/input' | 'filters/lcpt' | 'filters/link' | 'filters/location' | 'filters/memory-load' | 'filters/metadata' | 'filters/os' | 'filters/perfromance-network-request' | 'filters/platform' | 'filters/referrer' | 'filters/resize' | 'filters/rev-id' | 'filters/state-action' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'folder-plus' | 'folder2' | 'fullscreen' | 'funnel/cpu-fill' | 'funnel/cpu' | 'funnel/dizzy' | 'funnel/emoji-angry-fill' | 'funnel/emoji-angry' | 'funnel/emoji-dizzy-fill' | 'funnel/exclamation-circle-fill' | 'funnel/exclamation-circle' | 'funnel/file-earmark-break-fill' | 'funnel/file-earmark-break' | 'funnel/file-earmark-minus-fill' | 'funnel/file-earmark-minus' | 'funnel/file-medical-alt' | 'funnel/file-x' | 'funnel/hdd-fill' | 'funnel/hourglass-top' | 'funnel/image-fill' | 'funnel/image' | 'funnel/microchip' | 'funnel/mouse' | 'funnel/patch-exclamation-fill' | 'funnel/sd-card' | 'funnel-fill' | 'funnel-new' | 'funnel' | 'gear-fill' | 'gear' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-3x3' | 'grid-check' | 'grid-horizontal' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'inspect' | 'integrations/assist' | 'integrations/bugsnag-text' | 'integrations/bugsnag' | 'integrations/cloudwatch-text' | 'integrations/cloudwatch' | 'integrations/datadog' | 'integrations/elasticsearch-text' | 'integrations/elasticsearch' | 'integrations/github' | 'integrations/graphql' | 'integrations/jira-text' | 'integrations/jira' | 'integrations/mobx' | 'integrations/newrelic-text' | 'integrations/newrelic' | 'integrations/ngrx' | 'integrations/openreplay-text' | 'integrations/openreplay' | 'integrations/redux' | 'integrations/rollbar-text' | 'integrations/rollbar' | 'integrations/segment' | 'integrations/sentry-text' | 'integrations/sentry' | 'integrations/slack-bw' | 'integrations/slack' | 'integrations/stackdriver' | 'integrations/sumologic-text' | 'integrations/sumologic' | 'integrations/vuejs' | 'journal-code' | 'layer-group' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-arrow' | 'list-ul' | 'list' | 'lock-alt' | 'map-marker-alt' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'percent' | 'performance-icon' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plus-circle' | 'plus' | 'prev1' | 'puzzle-piece' | 'puzzle' | 'question-circle' | 'question-lg' | 'quote-left' | 'quote-right' | 'quotes' | 'redo-back' | 'redo' | 'remote-control' | 'replay-10' | 'resources-icon' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slack' | 'slash-circle' | 'sliders' | 'social/slack' | 'social/trello' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'text-paragraph' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'web-vitals' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; +export type IconNames = 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-bar-left' | 'arrow-clockwise' | 'arrow-down' | 'arrow-repeat' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_bear' | 'avatar/icn_beaver' | 'avatar/icn_bird' | 'avatar/icn_bison' | 'avatar/icn_camel' | 'avatar/icn_chameleon' | 'avatar/icn_deer' | 'avatar/icn_dog' | 'avatar/icn_dolphin' | 'avatar/icn_elephant' | 'avatar/icn_fish' | 'avatar/icn_fox' | 'avatar/icn_gorilla' | 'avatar/icn_hippo' | 'avatar/icn_horse' | 'avatar/icn_hyena' | 'avatar/icn_kangaroo' | 'avatar/icn_lemur' | 'avatar/icn_mammel' | 'avatar/icn_monkey' | 'avatar/icn_moose' | 'avatar/icn_panda' | 'avatar/icn_penguin' | 'avatar/icn_porcupine' | 'avatar/icn_quail' | 'avatar/icn_rabbit' | 'avatar/icn_rhino' | 'avatar/icn_sea_horse' | 'avatar/icn_sheep' | 'avatar/icn_snake' | 'avatar/icn_squirrel' | 'avatar/icn_tapir' | 'avatar/icn_turtle' | 'avatar/icn_vulture' | 'avatar/icn_wild1' | 'avatar/icn_wild_bore' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'bell-fill' | 'bell-plus' | 'bell-slash' | 'bell' | 'binoculars' | 'book' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'call' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-right-text' | 'chat-square-quote' | 'check-circle-fill' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'clipboard-list-check' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-front' | 'cubes' | 'dashboard-icn' | 'desktop' | 'device' | 'diagram-3' | 'dizzy' | 'door-closed' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'enter' | 'envelope' | 'errors-icon' | 'event/click' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/link' | 'event/location' | 'event/resize' | 'event/view' | 'exclamation-circle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'file-code' | 'file-medical-alt' | 'file-pdf' | 'file' | 'filter' | 'filters/arrow-return-right' | 'filters/browser' | 'filters/click' | 'filters/clickrage' | 'filters/code' | 'filters/console' | 'filters/country' | 'filters/cpu-load' | 'filters/custom' | 'filters/device' | 'filters/dom-complete' | 'filters/duration' | 'filters/error' | 'filters/fetch-failed' | 'filters/fetch' | 'filters/file-code' | 'filters/graphql' | 'filters/i-cursor' | 'filters/input' | 'filters/lcpt' | 'filters/link' | 'filters/location' | 'filters/memory-load' | 'filters/metadata' | 'filters/os' | 'filters/perfromance-network-request' | 'filters/platform' | 'filters/referrer' | 'filters/resize' | 'filters/rev-id' | 'filters/state-action' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'folder-plus' | 'folder2' | 'fullscreen' | 'funnel/cpu-fill' | 'funnel/cpu' | 'funnel/dizzy' | 'funnel/emoji-angry-fill' | 'funnel/emoji-angry' | 'funnel/emoji-dizzy-fill' | 'funnel/exclamation-circle-fill' | 'funnel/exclamation-circle' | 'funnel/file-earmark-break-fill' | 'funnel/file-earmark-break' | 'funnel/file-earmark-minus-fill' | 'funnel/file-earmark-minus' | 'funnel/file-medical-alt' | 'funnel/file-x' | 'funnel/hdd-fill' | 'funnel/hourglass-top' | 'funnel/image-fill' | 'funnel/image' | 'funnel/microchip' | 'funnel/mouse' | 'funnel/patch-exclamation-fill' | 'funnel/sd-card' | 'funnel-fill' | 'funnel-new' | 'funnel' | 'gear-fill' | 'gear' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-3x3' | 'grid-check' | 'grid-horizontal' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'inspect' | 'integrations/assist' | 'integrations/bugsnag-text' | 'integrations/bugsnag' | 'integrations/cloudwatch-text' | 'integrations/cloudwatch' | 'integrations/datadog' | 'integrations/elasticsearch-text' | 'integrations/elasticsearch' | 'integrations/github' | 'integrations/graphql' | 'integrations/jira-text' | 'integrations/jira' | 'integrations/mobx' | 'integrations/newrelic-text' | 'integrations/newrelic' | 'integrations/ngrx' | 'integrations/openreplay-text' | 'integrations/openreplay' | 'integrations/redux' | 'integrations/rollbar-text' | 'integrations/rollbar' | 'integrations/segment' | 'integrations/sentry-text' | 'integrations/sentry' | 'integrations/slack-bw' | 'integrations/slack' | 'integrations/stackdriver' | 'integrations/sumologic-text' | 'integrations/sumologic' | 'integrations/vuejs' | 'journal-code' | 'layer-group' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-arrow' | 'list-ul' | 'list' | 'lock-alt' | 'map-marker-alt' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'percent' | 'performance-icon' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plus-circle' | 'plus' | 'prev1' | 'puzzle-piece' | 'puzzle' | 'question-circle' | 'question-lg' | 'quote-left' | 'quote-right' | 'quotes' | 'redo-back' | 'redo' | 'remote-control' | 'replay-10' | 'resources-icon' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slack' | 'slash-circle' | 'sliders' | 'social/slack' | 'social/trello' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'text-paragraph' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'web-vitals' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; interface Props { name: IconNames; @@ -166,6 +166,7 @@ const SVG = (props: Props) => { case 'fetch': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"/></svg>; case 'file-code': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/><path d="M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708z"/></svg>; case 'file-medical-alt': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/><path d="m10.273 2.513-.921-.944.715-.698.622.637.89-.011a2.89 2.89 0 0 1 2.924 2.924l-.01.89.636.622a2.89 2.89 0 0 1 0 4.134l-.637.622.011.89a2.89 2.89 0 0 1-2.924 2.924l-.89-.01-.622.636a2.89 2.89 0 0 1-4.134 0l-.622-.637-.89.011a2.89 2.89 0 0 1-2.924-2.924l.01-.89-.636-.622a2.89 2.89 0 0 1 0-4.134l.637-.622-.011-.89a2.89 2.89 0 0 1 2.924-2.924l.89.01.622-.636a2.89 2.89 0 0 1 4.134 0l-.715.698a1.89 1.89 0 0 0-2.704 0l-.92.944-1.32-.016a1.89 1.89 0 0 0-1.911 1.912l.016 1.318-.944.921a1.89 1.89 0 0 0 0 2.704l.944.92-.016 1.32a1.89 1.89 0 0 0 1.912 1.911l1.318-.016.921.944a1.89 1.89 0 0 0 2.704 0l.92-.944 1.32.016a1.89 1.89 0 0 0 1.911-1.912l-.016-1.318.944-.921a1.89 1.89 0 0 0 0-2.704l-.944-.92.016-1.32a1.89 1.89 0 0 0-1.912-1.911l-1.318.016z"/></svg>; + case 'file-pdf': return <svg viewBox="0 0 13 14" width={ `${ width }px` } height={ `${ height }px` } ><g clipPath="url(#a)"><path d="M3.493.662A1.584 1.584 0 0 0 1.91 2.247v9.506a1.584 1.584 0 0 0 1.584 1.585h6.338a1.584 1.584 0 0 0 1.585-1.585V2.247A1.585 1.585 0 0 0 9.83.662H3.493Zm0 .792h6.338a.792.792 0 0 1 .792.793v9.506a.792.792 0 0 1-.792.793H3.493a.792.792 0 0 1-.792-.793V2.247a.792.792 0 0 1 .792-.793Z" fill-opacity=".6"/><path d="M3.971 10.238a.641.641 0 0 1-.347-.333c-.154-.307-.103-.615.063-.873.157-.243.417-.45.711-.623a6.084 6.084 0 0 1 1.174-.511c.317-.57.598-1.16.841-1.765a5.759 5.759 0 0 1-.34-1.026c-.068-.317-.095-.63-.037-.9.06-.28.217-.532.515-.652.152-.06.317-.095.477-.06a.555.555 0 0 1 .378.289c.07.13.095.282.1.426a2.54 2.54 0 0 1-.037.486c-.066.404-.213.899-.411 1.421.218.468.478.915.776 1.336a4.558 4.558 0 0 1 1.057.04c.288.051.581.154.76.368a.67.67 0 0 1 .159.41.922.922 0 0 1-.11.447.824.824 0 0 1-.28.33.678.678 0 0 1-.404.108c-.262-.01-.518-.155-.74-.33a4.528 4.528 0 0 1-.721-.753 9.223 9.223 0 0 0-1.582.322 8.96 8.96 0 0 1-.809 1.196c-.23.278-.482.52-.734.624a.628.628 0 0 1-.459.023Zm1.092-1.506c-.131.06-.253.123-.363.188-.26.154-.429.304-.513.434-.074.115-.076.198-.031.286a.18.18 0 0 0 .02.035.213.213 0 0 0 .028-.01c.108-.044.281-.186.503-.453a6.48 6.48 0 0 0 .356-.48Zm1.3-1.054c.264-.062.531-.113.8-.153a9.243 9.243 0 0 1-.404-.68c-.124.281-.256.559-.396.832v.001Zm1.938.357c.118.128.234.237.344.324.19.151.323.2.395.203a.085.085 0 0 0 .055-.012.243.243 0 0 0 .075-.099.345.345 0 0 0 .046-.158.075.075 0 0 0-.02-.05c-.041-.05-.159-.12-.41-.166a3.075 3.075 0 0 0-.485-.042ZM6.724 5.257c.067-.215.12-.434.158-.656.025-.149.034-.272.03-.368a.486.486 0 0 0-.025-.157.41.41 0 0 0-.115.032c-.069.027-.125.084-.155.224-.032.152-.024.371.036.651.02.088.043.18.072.274h-.001Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(.324 .662)" d="M0 0h12.676v12.676H0z"/></clipPath></defs></svg>; case 'file': return <svg viewBox="0 0 384 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M369.9 97.9 286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zm-22.6 22.7c2.1 2.1 3.5 4.6 4.2 7.4H256V32.5c2.8.7 5.3 2.1 7.4 4.2l83.9 83.9zM336 480H48c-8.8 0-16-7.2-16-16V48c0-8.8 7.2-16 16-16h176v104c0 13.3 10.7 24 24 24h104v304c0 8.8-7.2 16-16 16z"/></svg>; case 'filter': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z"/></svg>; case 'filters/arrow-return-right': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z"/></svg>; diff --git a/frontend/app/svg/icons/file-pdf.svg b/frontend/app/svg/icons/file-pdf.svg new file mode 100644 index 000000000..f6cfbebca --- /dev/null +++ b/frontend/app/svg/icons/file-pdf.svg @@ -0,0 +1,11 @@ +<svg viewBox="0 0 13 14" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_2148_10595)"> +<path d="M3.49328 0.66217C3.07306 0.66217 2.67005 0.829104 2.3729 1.12625C2.07576 1.42339 1.90883 1.8264 1.90883 2.24662V11.7533C1.90883 12.1736 2.07576 12.5766 2.3729 12.8737C2.67005 13.1709 3.07306 13.3378 3.49328 13.3378H9.8311C10.2513 13.3378 10.6543 13.1709 10.9515 12.8737C11.2486 12.5766 11.4156 12.1736 11.4156 11.7533V2.24662C11.4156 1.8264 11.2486 1.42339 10.9515 1.12625C10.6543 0.829104 10.2513 0.66217 9.8311 0.66217H3.49328ZM3.49328 1.4544H9.8311C10.0412 1.4544 10.2427 1.53786 10.3913 1.68644C10.5399 1.83501 10.6233 2.03651 10.6233 2.24662V11.7533C10.6233 11.9635 10.5399 12.165 10.3913 12.3135C10.2427 12.4621 10.0412 12.5456 9.8311 12.5456H3.49328C3.28317 12.5456 3.08167 12.4621 2.93309 12.3135C2.78452 12.165 2.70106 11.9635 2.70106 11.7533V2.24662C2.70106 2.03651 2.78452 1.83501 2.93309 1.68644C3.08167 1.53786 3.28317 1.4544 3.49328 1.4544Z" fill-opacity="0.6"/> +<path d="M3.97099 10.2378C3.81658 10.1761 3.69217 10.0568 3.62399 9.9051C3.46951 9.59772 3.521 9.29033 3.68737 9.03207C3.84423 8.78885 4.10408 8.58208 4.398 8.40859C4.7703 8.19743 5.16384 8.02616 5.57208 7.8976C5.88911 7.32766 6.17011 6.73841 6.41343 6.13331C6.26796 5.80277 6.1539 5.45928 6.07277 5.10738C6.00464 4.79048 5.97849 4.47676 6.03633 4.20741C6.09574 3.92696 6.2534 3.67503 6.55127 3.5554C6.70338 3.4944 6.86816 3.46034 7.02819 3.4944C7.10869 3.51154 7.18437 3.54638 7.24973 3.59639C7.31509 3.64641 7.3685 3.71034 7.40609 3.78356C7.4758 3.91349 7.50115 4.0656 7.5067 4.20978C7.51224 4.35793 7.49719 4.52271 7.46946 4.69621C7.40292 5.10024 7.25556 5.59459 7.05751 6.11746C7.27607 6.58489 7.5359 7.0319 7.83389 7.45316C8.18651 7.42531 8.54117 7.4386 8.89072 7.49277C9.17909 7.54427 9.47221 7.64725 9.65126 7.86116C9.74632 7.97524 9.80416 8.11467 9.8097 8.27153C9.81525 8.42364 9.77247 8.57416 9.70038 8.71755C9.63793 8.85044 9.5411 8.96422 9.41993 9.04712C9.30015 9.12525 9.15873 9.16352 9.01589 9.15645C8.75366 9.14536 8.49777 9.00117 8.27674 8.82609C8.00799 8.60385 7.76581 8.3513 7.55502 8.07347C7.01928 8.13424 6.48989 8.24186 5.97295 8.39512C5.73595 8.81498 5.46545 9.21504 5.16408 9.59138C4.93434 9.86866 4.68241 10.1103 4.43048 10.2149C4.28573 10.2803 4.12155 10.2886 3.97099 10.2378ZM5.06347 8.73181C4.93196 8.79202 4.80996 8.8554 4.69984 8.92036C4.43999 9.07406 4.27124 9.22379 4.18727 9.35371C4.1128 9.46859 4.11121 9.55177 4.15558 9.63971C4.1635 9.65714 4.17142 9.66823 4.17618 9.67456C4.18563 9.67203 4.19489 9.66886 4.2039 9.66506C4.31244 9.62069 4.48514 9.47888 4.70697 9.2119C4.83313 9.05744 4.95209 8.89724 5.06347 8.73181ZM6.36272 7.67815C6.62726 7.61636 6.89419 7.56535 7.16287 7.52525C7.01856 7.30454 6.88376 7.07776 6.75884 6.84552C6.6346 7.12645 6.50251 7.40384 6.36272 7.67736V7.67815ZM8.30051 8.03465C8.41934 8.16299 8.53501 8.27232 8.64513 8.35947C8.83526 8.50999 8.96757 8.5599 9.03966 8.56228C9.05896 8.5648 9.07854 8.56061 9.09511 8.55039C9.12807 8.52437 9.15373 8.49025 9.16958 8.45137C9.19775 8.40311 9.21379 8.34874 9.21632 8.29292C9.21587 8.27431 9.20853 8.25653 9.19573 8.24301C9.15453 8.19389 9.03728 8.12259 8.78535 8.07743C8.6251 8.05065 8.46298 8.03661 8.30051 8.03545V8.03465ZM6.72398 5.25711C6.79065 5.04203 6.84358 4.82294 6.88242 4.60114C6.90698 4.4522 6.91649 4.32941 6.91253 4.23276C6.91275 4.17943 6.90418 4.12644 6.88718 4.0759C6.84755 4.0808 6.80885 4.09148 6.7723 4.10758C6.70338 4.13531 6.64713 4.19156 6.61703 4.33178C6.58534 4.48389 6.59326 4.70334 6.65347 4.983C6.67248 5.07093 6.69625 5.16283 6.72477 5.25711H6.72398Z" /> +</g> +<defs> +<clipPath id="clip0_2148_10595"> +<rect width="12.6756" height="12.6756" fill="white" transform="translate(0.324371 0.66217)"/> +</clipPath> +</defs> +</svg>