Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/final redesign touches #147

Merged
merged 12 commits into from
Jul 12, 2024
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
env:
# Playwright headless browsers running in CI get low confidence scores, causing flaky e2e tests. Lower the confidence score threshold for CI testing.
MIN_CONFIDENCE_SCORE: 0
Expand Down
80 changes: 62 additions & 18 deletions src/app/playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
MyCollapsibleContent,
} from '../../client/components/common/Collapsible/Collapsible';
import { ChevronSvg } from '../../client/img/chevronSvg';
import { pluralize } from '../../shared/utils';

const PLAYGROUND_COPY = {
androidOnly: 'Applicable only to Android devices',
Expand Down Expand Up @@ -125,6 +126,10 @@ function Playground() {
];

const suspectScore = usedIdentificationEvent?.products?.suspectScore?.data?.result;
// @ts-expect-error Not supported in Node SDK yet
const remoteControl: boolean | undefined = usedIdentificationEvent?.products?.remoteControl?.data?.result;
// @ts-expect-error Not supported in Node SDK yet
const ipVelocity: number | undefined = usedIdentificationEvent?.products?.velocity?.data?.distinctIp.intervals['1h'];

const smartSignals: TableCellData[][] = [
[
Expand Down Expand Up @@ -246,6 +251,27 @@ function Playground() {
: tableStyles.green,
},
],
[
{
content: [
<DocsLink
href='https://dev.fingerprint.com/docs/smart-signals-overview#remote-control-tools-detection'
key='remote-control-tools'
>
Remote Control Tools
</DocsLink>,
],
},
{
content: remoteControl === undefined ? 'Not available' : remoteControl === true ? 'Yes 🕹️' : 'Not detected',
className:
remoteControl === undefined
? tableStyles.neutral
: remoteControl === true
? tableStyles.red
: tableStyles.green,
},
],
[
{
content: [
Expand Down Expand Up @@ -284,6 +310,20 @@ function Playground() {
usedIdentificationEvent?.products?.highActivity?.data?.result === true ? tableStyles.red : tableStyles.green,
},
],
[
{
content: [
<DocsLink href='https://dev.fingerprint.com/docs/smart-signals-overview#velocity-signals' key='velocity '>
Velocity signals
</DocsLink>,
],
},
{
content: ipVelocity === undefined ? 'Not available' : `${pluralize(ipVelocity, 'IP')} in the past hour`,
className:
ipVelocity === undefined ? tableStyles.neutral : ipVelocity > 1 ? tableStyles.red : tableStyles.green,
},
],
[
{
content: [
Expand All @@ -294,11 +334,12 @@ function Playground() {
},
{
content: usedIdentificationEvent?.products?.suspectScore?.data?.result ?? 'Not available',
className: !suspectScore
? tableStyles.neutral
: suspectScore > SUSPECT_SCORE_RED_THRESHOLD
? tableStyles.red
: tableStyles.green,
className:
suspectScore === undefined
? tableStyles.neutral
: suspectScore > SUSPECT_SCORE_RED_THRESHOLD
? tableStyles.red
: tableStyles.green,
},
],
[
Expand Down Expand Up @@ -407,7 +448,6 @@ function Playground() {
</h1>
<p>Analyze your browser with Fingerprint Pro and see all the available signals.</p>
</Container>

{agentResponse && (
<Container size='large'>
<div className={styles.visitorIdBox}>
Expand All @@ -419,13 +459,21 @@ function Playground() {
{!cachedEvent ? (
<Container size='large'>
<div className={styles.runningIntelligence}>
<Spinner size='40px' thickness={3} />
<h2>Running device intelligence...</h2>
<Spinner size={64} />
<h2>
Running Device Intelligence<span className={styles.blink}>_</span>
</h2>
</div>
</Container>
) : (
<>
<Container size='large'>
<RefreshButton
loading={isLoadingAgentResponse || isLoadingServerResponse}
getAgentData={getAgentData}
className={styles.reloadButton}
/>

<div className={styles.tablesContainer}>
<MyCollapsible defaultOpen>
<h3 className={styles.tableTitle}>
Expand Down Expand Up @@ -464,29 +512,25 @@ function Playground() {
</div>
</Container>

<Container size='large'>
<RefreshButton
loading={isLoadingAgentResponse || isLoadingServerResponse}
getAgentData={getAgentData}
className={styles.reloadButton}
/>
</Container>

<Container size='large' className={styles.isSection}>
<h2 className={styles.sectionTitle}>How to use this demo</h2>
<HowToUseThisPlayground />
</Container>
<Container size='large' className={classnames(styles.isSection, styles.jsonSection)}>
<div className={styles.jsonContainer}>
<div>
<h4 className={styles.jsonTitle}>JavaScript Agent Response {isLoadingAgentResponse && <Spinner />}</h4>
<h4 className={styles.jsonTitle}>
JavaScript Agent Response {isLoadingAgentResponse && <Spinner size={16} />}
</h4>
<CollapsibleJsonViewer
dataTestId={TEST_IDS.playground.agentResponseJSON}
json={displayedAgentResponse ?? {}}
/>
</div>
<div>
<h4 className={styles.jsonTitle}>Server API Response {isLoadingServerResponse && <Spinner />}</h4>
<h4 className={styles.jsonTitle}>
Server API Response {isLoadingServerResponse && <Spinner size={16} />}
</h4>
<CollapsibleJsonViewer
dataTestId={TEST_IDS.playground.serverResponseJSON}
json={usedIdentificationEvent ?? {}}
Expand Down
14 changes: 10 additions & 4 deletions src/app/playground/components/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MapContainer, Marker, TileLayer } from 'react-leaflet';
import React from 'react';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { env } from '../../../env';

// This is a workaround for the marker icon not showing up out of the box
const DefaultIcon = L.divIcon({
Expand All @@ -27,7 +28,9 @@ type MapProps = {
zoom?: number;
};

const Map: FunctionComponent<MapProps> = (props) => {
const MAPBOX_ACCESS_TOKEN = env.NEXT_PUBLIC_MAPBOX_API_TOKEN;

export const Map: FunctionComponent<MapProps> = (props) => {
const defaultZoom = 9; // Shows you rougly inside a specific city
return (
<MapContainer
Expand All @@ -45,9 +48,12 @@ const Map: FunctionComponent<MapProps> = (props) => {
doubleClickZoom={false}
attributionControl={false}
>
{/* More options here https://github.com/leaflet-extras/leaflet-providers
but make sure to test them live, some of them only work on Localhost */}
<TileLayer url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' />
<TileLayer
url={`https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=${MAPBOX_ACCESS_TOKEN}`}
id='mapbox/outdoors-v11'
tileSize={512}
zoomOffset={-1}
/>
<Marker position={props.position} icon={DefaultIcon} interactive={false} />
</MapContainer>
);
Expand Down
2 changes: 1 addition & 1 deletion src/app/playground/components/RefreshButton.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

img {
transition: scale 0.2s ease;
margin-left: rem(8px);
margin-left: rem(4px);
}

&:hover {
Expand Down
77 changes: 55 additions & 22 deletions src/app/playground/playground.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
@include media('<=tabletWide') {
font-size: rem(30px);
}

@include media('<=phoneLandscape') {
text-align: left;
}
}

p {
Expand All @@ -41,6 +45,10 @@
@include media('<=tabletWide') {
font-size: rem(16px);
}

@include media('<=phoneLandscape') {
text-align: left;
}
}
}

Expand All @@ -53,7 +61,6 @@
display: flex;
flex-direction: column;
gap: rem(8px);
margin-bottom: rem(32px);

@include media('<=tabletWide') {
padding: rem(20px);
Expand Down Expand Up @@ -139,13 +146,18 @@ h2.sectionTitle {

&:hover {
color: v('orange-gradient');

.externalLinkArrow {
translate: 2px 0px;
}
}

img {
margin-left: rem(2px);
.externalLinkArrow {
margin-left: 4px;
vertical-align: baseline;
height: rem(10px);
color: v('dark-black');
width: 10px;
height: 10px;
transition: translate 0.2s ease-in-out;
}
}

Expand All @@ -172,16 +184,38 @@ h2.sectionTitle {
}

h2 {
color: v('dark-black');
font-family: Inter;
font-size: rem(24px);
font-weight: 400;
color: v('orange-gradient');
text-align: center;
letter-spacing: -0.25px;
font-family: JetBrains Mono;
font-size: 16px;
font-weight: 400;
line-height: 160%;

@include media('<=tabletWide') {
font-size: rem(18px);
}
animation: reveal 0.5s cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
display: inline-block;
}

.blink {
animation: blink 0.3s infinite;
}
}

@keyframes reveal {
from {
clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
}
to {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
}

@keyframes blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}

Expand All @@ -195,24 +229,22 @@ h2.sectionTitle {
}

.locationText {
color: v('dark-gray');
color: v('dark-black');
font-family: Inter;
font-size: rem(13px);
font-weight: 400;
line-height: 160%;
letter-spacing: 0.13px;
}

.externalLinkArrow {
margin-left: 4px;
vertical-align: baseline;
}

.reloadButton {
margin: rem(48px) auto rem(48px) auto;
margin: rem(16px) auto rem(32px) auto;

@include media('<=tabletWide') {
margin: rem(24px) auto rem(24px) auto;
@include media('<=phoneLandscape') {
&.reloadButton {
margin: rem(16px) 0 rem(32px) 0;
padding: 0px;
}
}
}

Expand All @@ -225,6 +257,7 @@ h2.sectionTitle {
@include media('<=1200px') {
grid-template-columns: minmax(0, 500px);
}
margin-bottom: rem(48px);
}

.tableTitle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
padding: rem(20px) rem(24px);
gap: 6px;
flex-wrap: wrap;
color: v('dark-black');

> div:first-child {
text-align: left;
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/common/Spinner/Spinner.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
& {
color: v('orange-gradient');
}

animation: spin 1s linear infinite;
}
12 changes: 6 additions & 6 deletions src/client/components/common/Spinner/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import CircularProgress, { CircularProgressProps } from '@mui/material/CircularProgress';
import { FunctionComponent } from 'react';
import styles from './Spinner.module.scss';
import { SpinnerSvg } from '../../../img/SpinnerSvg';
import classNames from 'classnames';

export const Spinner: FunctionComponent<{
size?: CircularProgressProps['size'];
thickness?: CircularProgressProps['thickness'];
sx?: React.CSSProperties;
}> = ({ sx, size, thickness }) => (
<CircularProgress size={size ?? '18px'} thickness={thickness ?? 5} className={styles.spinner} sx={{ ...sx }} />
size: number;
className?: string;
}> = ({ size, className }) => (
<SpinnerSvg className={classNames(styles.spinner, className)} width={size} height={size} />
);
Loading
Loading