From 2f0b5359b7778994e3e50700f5416063e004b45d Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 20 Oct 2022 09:17:49 +0200 Subject: [PATCH] feat(ui): create template types and components for bug report --- .../components/Session_/Autoplay/Autoplay.js | 2 +- .../Session_/BugReport/BugReportModal.tsx | 131 ++++++++++++++++++ .../components/Session_/BugReport/types.ts | 69 +++++++++ .../Session_/EventsBlock/UserCard/UserCard.js | 7 - frontend/app/components/Session_/Subheader.js | 79 +++++++---- .../Session_/components/HeaderMenu.tsx | 75 ++++++++++ .../Session_/components/NotePopup.tsx | 2 +- .../Session_/components/menu.module.css | 102 ++++++++++++++ frontend/app/components/ui/SVG.tsx | 3 +- frontend/app/svg/icons/file-pdf.svg | 11 ++ 10 files changed, 447 insertions(+), 34 deletions(-) create mode 100644 frontend/app/components/Session_/BugReport/BugReportModal.tsx create mode 100644 frontend/app/components/Session_/BugReport/types.ts create mode 100644 frontend/app/components/Session_/components/HeaderMenu.tsx create mode 100644 frontend/app/components/Session_/components/menu.module.css create mode 100644 frontend/app/svg/icons/file-pdf.svg 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>