forked from testimio/root-cause
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Network logs ui iteration (testimio#4)
* Network logs UI iteration Co-authored-by: Benjamin Gruenbaum <[email protected]>
- Loading branch information
Bnaya Peretz
committed
Aug 25, 2020
1 parent
23d7e96
commit 191d1a0
Showing
36 changed files
with
316 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import '../src/fonts/MyFontsWebfontsKit.css'; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
packages/client/src/components/MenuDropDown/MenuDropDown.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from 'react'; | ||
import { MenuDropDown } from './MenuDropDown'; | ||
import { action } from '@storybook/addon-actions'; | ||
|
||
import HarIcon from '../../globalAssets/[email protected]'; | ||
import TestLogIcon from '../../globalAssets/TestLog.svg'; | ||
|
||
export default { | ||
title: 'Menu drop down', | ||
component: MenuDropDown, | ||
}; | ||
|
||
export function AsIs() { | ||
return ( | ||
<MenuDropDown | ||
onItemClick={action('item-click')} | ||
items={[ | ||
{ | ||
slug: 'download_har_file', | ||
text: 'Download HAR file', | ||
icon: HarIcon, | ||
}, | ||
{ | ||
slug: 'download_log_file', | ||
text: 'Download test log', | ||
icon: TestLogIcon, | ||
}, | ||
]} | ||
/> | ||
); | ||
} |
52 changes: 52 additions & 0 deletions
52
packages/client/src/components/MenuDropDown/MenuDropDown.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React from 'react'; | ||
import styles from './styles.module.css'; | ||
|
||
export interface MenuItem { | ||
slug: string; | ||
text: string; | ||
icon: string; | ||
} | ||
|
||
export function MenuDropDown({ | ||
items, | ||
onItemClick, | ||
}: { | ||
items: MenuItem[]; | ||
onItemClick(slug: string): void; | ||
}) { | ||
return ( | ||
<div className={styles.menuDropDownWrapper}> | ||
{items.map((item) => { | ||
return ( | ||
<MenuDropDownItem | ||
key={item.slug} | ||
text={item.text} | ||
icon={item.icon} | ||
onClick={() => { | ||
onItemClick(item.slug); | ||
}} | ||
/> | ||
); | ||
})} | ||
</div> | ||
); | ||
} | ||
|
||
function MenuDropDownItem({ | ||
text, | ||
icon, | ||
onClick, | ||
}: { | ||
text: string; | ||
icon?: string; | ||
onClick(): void; | ||
}) { | ||
return ( | ||
<div className={styles.menuItemWrapper} onClick={onClick}> | ||
<div className={styles.iconBox}> | ||
{icon ? <img src={icon} alt={`${text} icon`} /> : null} | ||
</div> | ||
<span className={styles.text}>{text}</span> | ||
</div> | ||
); | ||
} |
36 changes: 36 additions & 0 deletions
36
packages/client/src/components/MenuDropDown/styles.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
.menuDropDownWrapper { | ||
border: 1px solid #DBDFE3; | ||
background-color: #FFFFFF; | ||
box-shadow: 0 6px 12px 0 rgba(0,0,0,0.15); | ||
display: inline-block; | ||
} | ||
|
||
.menuItemWrapper { | ||
display: flex; | ||
align-items: center; | ||
height: 50px; | ||
width: 200px; | ||
user-select: none; | ||
transition: background-color 150ms; | ||
white-space: nowrap; | ||
letter-spacing: normal; | ||
} | ||
|
||
.menuItemWrapper:hover { | ||
background-color: #ECEEEF; | ||
cursor: pointer; | ||
} | ||
|
||
.menuItemWrapper .text { | ||
font-family: "Mont-Regular"; | ||
font-size: 14px; | ||
} | ||
|
||
|
||
.menuItemWrapper .iconBox { | ||
width: 56px; | ||
height: 100%; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,136 @@ | ||
import * as React from "react"; | ||
import styles from "./styles.module.css"; | ||
import type { TestSystemInfo, TestResultFile } from "@testim/root-cause-types"; | ||
import classnames from "classnames"; | ||
import * as React from 'react'; | ||
import styles from './styles.module.css'; | ||
import type { TestSystemInfo, TestResultFile } from '@testim/root-cause-types'; | ||
import classnames from 'classnames'; | ||
import ms from 'ms'; | ||
import downloadHarButton from "./../../globalAssets/archive.svg"; | ||
import { useExternalResourceUrl } from "../../stores/ExternalResourceUrlContext"; | ||
import { useExternalResourceUrl } from '../../stores/ExternalResourceUrlContext'; | ||
import { MenuDropDown } from '../MenuDropDown/MenuDropDown'; | ||
import HarIcon from '../../globalAssets/[email protected]'; | ||
// import TestLogIcon from '../../globalAssets/TestLog.svg'; | ||
|
||
export const TestResultTitlebar = React.memo(function TestResultTitlebar({ testMetadata, totalTime, isClickimMode }: { testMetadata: TestResultFile["metadata"], totalTime:number, isClickimMode:boolean }) { | ||
const testStatus: "success" | "failed" | "unknown" = testMetadata.testEndStatus ? testMetadata.testEndStatus.success ? "success" : "failed" : "unknown" | ||
export const TestResultTitlebar = React.memo(function TestResultTitlebar({ | ||
testMetadata, | ||
totalTime, | ||
isClickimMode, | ||
}: { | ||
testMetadata: TestResultFile['metadata']; | ||
totalTime: number; | ||
isClickimMode: boolean; | ||
}) { | ||
const testStatus: 'success' | 'failed' | 'unknown' = testMetadata.testEndStatus | ||
? testMetadata.testEndStatus.success | ||
? 'success' | ||
: 'failed' | ||
: 'unknown'; | ||
const getExternalResourceUrl = useExternalResourceUrl(); | ||
|
||
return ( | ||
<div className={styles.titleBar}> | ||
<div className={styles.logo}> | ||
{ !isClickimMode && ( | ||
{!isClickimMode && ( | ||
<> | ||
<div className={styles.logoSvg} /> | ||
<span className={styles.logoText}>Root Cause</span> | ||
<div className={styles.logoSvg} /> | ||
<span className={styles.logoText}>Root Cause</span> | ||
</> | ||
) } | ||
<span className={classnames(styles.testName, { [styles.clickimTitle]:isClickimMode })} title={testMetadata.testFullName}>{testMetadata.testName}</span> | ||
)} | ||
<span | ||
className={classnames(styles.testName, { | ||
[styles.clickimTitle]: isClickimMode, | ||
})} | ||
title={testMetadata.testFullName} | ||
> | ||
{testMetadata.testName} | ||
</span> | ||
</div> | ||
<div className={styles.testStatus}> | ||
{testMetadata.hasNetworkLogs && <a className={styles.downloadHar} role="button" href={getExternalResourceUrl('networklogs.har')} download="har.json"><img src={downloadHarButton} alt="Download HAR file" />Download HAR</a>} | ||
{testStatus === "success" && <div className={styles.success}>TEST PASSED</div>} | ||
{testStatus === "failed" && <div className={styles.fail}>TEST FAILED</div>} | ||
<div className={classnames(styles.info, { | ||
[styles.failed]: testStatus === "failed" | ||
})}> | ||
{/* {testMetadata.hasNetworkLogs && ( | ||
<a | ||
className={styles.downloadHar} | ||
role="button" | ||
href={getExternalResourceUrl('networklogs.har')} | ||
download="har.json" | ||
> | ||
<img src={downloadHarButton} alt="Download HAR file" /> | ||
Download HAR | ||
</a> | ||
)} */} | ||
{testStatus === 'success' && <div className={styles.success}>TEST PASSED</div>} | ||
{testStatus === 'failed' && <div className={styles.fail}>TEST FAILED</div>} | ||
<div | ||
className={classnames(styles.info, { | ||
[styles.failed]: testStatus === 'failed', | ||
})} | ||
> | ||
<div className={styles.whiteBackground}></div> | ||
<div className={styles.tooltipErrorSvg}></div> | ||
<div className={styles.popup}> | ||
<div className={styles.triangle}></div> | ||
{ | ||
testMetadata.systemInfo && <TestInfoPopupFields fields={mapTestSystemDataToTestFields(testMetadata.systemInfo)} totalTime={totalTime} /> | ||
} | ||
{testMetadata.systemInfo && ( | ||
<TestInfoPopupFields | ||
fields={mapTestSystemDataToTestFields(testMetadata.systemInfo)} | ||
totalTime={totalTime} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
{testMetadata.hasNetworkLogs && ( | ||
<> | ||
<div className={classnames(styles.statusMenuSeparator)}></div> | ||
<div className={classnames(styles.moreVertMenu)}> | ||
<div className={classnames(styles.moreMenuContent)}> | ||
<MenuDropDown | ||
onItemClick={(slug) => { | ||
if (slug === 'download_har_file') { | ||
const aElement = document.createElement('a'); | ||
const href = getExternalResourceUrl('networkLogs.har'); | ||
console.log({ href }); | ||
|
||
if (!href) { | ||
return; | ||
} | ||
|
||
aElement.href = href; | ||
aElement.download = 'networklogs.har'; | ||
aElement.click(); | ||
} else if (slug === 'download_log_file') { | ||
// not available yet | ||
} | ||
|
||
// console.log({ slug }); | ||
}} | ||
items={[ | ||
{ | ||
slug: 'download_har_file', | ||
text: 'Download HAR file', | ||
icon: HarIcon, | ||
}, | ||
// not available yet | ||
// { | ||
// slug: 'download_log_file', | ||
// text: 'Download test log', | ||
// icon: TestLogIcon, | ||
// }, | ||
]} | ||
/> | ||
</div> | ||
</div> | ||
</> | ||
)} | ||
</div> | ||
); | ||
}); | ||
|
||
function TestInfoPopupFields({ fields, totalTime }: { fields: Array<[string, string]>, totalTime: number }) { | ||
function TestInfoPopupFields({ | ||
fields, | ||
totalTime, | ||
}: { | ||
fields: Array<[string, string]>; | ||
totalTime: number; | ||
}) { | ||
return ( | ||
<div className={styles.fields}> | ||
<div className={styles.headField}>TEST FAILED - { ms(totalTime, { long: true}) }</div> | ||
<div className={styles.headField}>TEST FAILED - {ms(totalTime, { long: true })}</div> | ||
{fields.map(([fieldName, fieldValue], i) => ( | ||
<React.Fragment key={i}> | ||
<span>{fieldName}</span> | ||
|
@@ -59,16 +144,16 @@ function TestInfoPopupFields({ fields, totalTime }: { fields: Array<[string, str | |
function mapTestSystemDataToTestFields(systemData: TestSystemInfo) { | ||
const fields: Array<[string, string]> = []; | ||
|
||
fields.push(["Browser Platform", systemData.browserPlatform]); | ||
fields.push(["Browser Version", systemData.browserVersion]); | ||
fields.push(["User Agent", systemData.userAgent]); | ||
fields.push(["Machine Model Name", systemData.modelName]); | ||
fields.push(["Machine Model Version", systemData.modelVersion]); | ||
fields.push(["Viewport", `${systemData.pageViewport.width}x${systemData.pageViewport.height}`]); | ||
fields.push(["Scale Factor", `${systemData.pageViewport.deviceScaleFactor || 1}`]); | ||
fields.push(["Mobile", `${systemData.pageViewport.isMobile ? "yes": "no"}`]); | ||
fields.push(["Landscape", `${systemData.pageViewport.isLandscape ? "yes": "no"}`]); | ||
fields.push(["Touch Support", `${systemData.pageViewport.hasTouch ? "yes": "no"}`]); | ||
fields.push(['Browser Platform', systemData.browserPlatform]); | ||
fields.push(['Browser Version', systemData.browserVersion]); | ||
fields.push(['User Agent', systemData.userAgent]); | ||
fields.push(['Machine Model Name', systemData.modelName]); | ||
fields.push(['Machine Model Version', systemData.modelVersion]); | ||
fields.push(['Viewport', `${systemData.pageViewport.width}x${systemData.pageViewport.height}`]); | ||
fields.push(['Scale Factor', `${systemData.pageViewport.deviceScaleFactor || 1}`]); | ||
fields.push(['Mobile', `${systemData.pageViewport.isMobile ? 'yes' : 'no'}`]); | ||
fields.push(['Landscape', `${systemData.pageViewport.isLandscape ? 'yes' : 'no'}`]); | ||
fields.push(['Touch Support', `${systemData.pageViewport.hasTouch ? 'yes' : 'no'}`]); | ||
|
||
return fields; | ||
} |
Oops, something went wrong.