Preferences > Project - UI Improvements (#2941)

This commit is contained in:
Sudheer Salavadi 2025-01-14 06:48:11 -05:00 committed by GitHub
parent 9ee853365c
commit 016011dd23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 345 additions and 243 deletions

View file

@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { Checkbox, Loader, Toggler } from 'UI';
import { Loader } from 'UI';
import { Switch, Checkbox, Tag } from 'antd';
import GDPR from 'App/mstore/types/gdpr';
import cn from 'classnames';
import stl from './projectCodeSnippet.module.css';
@ -18,7 +19,7 @@ interface InputModeOption {
const inputModeOptions: InputModeOption[] = [
{ label: 'Record all inputs', value: 'plain' },
{ label: 'Ignore all inputs', value: 'obscured' },
{ label: 'Obscure all inputs', value: 'hidden' }
{ label: 'Obscure all inputs', value: 'hidden' },
];
const inputModeOptionsMap: Record<string, number> = {};
@ -28,7 +29,7 @@ interface Props {
project: Project;
}
const ProjectCodeSnippet: React.FC = (props: Props) => {
const ProjectCodeSnippet: React.FC<Props> = (props) => {
const { projectsStore } = useStore();
const siteId = projectsStore.siteId;
const site = props.project;
@ -58,8 +59,7 @@ const ProjectCodeSnippet: React.FC = (props: Props) => {
saveGDPR();
};
const onChangeOption = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, checked } = event.target;
const onChangeOption = (name: string, checked: boolean) => {
editGDPR({ [name]: checked });
saveGDPR();
};
@ -73,13 +73,14 @@ const ProjectCodeSnippet: React.FC = (props: Props) => {
}, [isAssistEnabled]);
return (
<div>
<div className="mb-4">
<div className="font-semibold mb-2 flex items-center">
<CircleNumber text="1" /> Choose data recording options
<div className="flex flex-col gap-8 mt-4">
<div>
<div className="font-medium mb-2 flex gap-2 items-center">
<CircleNumber text="1" />
<span>Choose data recording options</span>
</div>
<div className="ml-10 mb-4" style={{ maxWidth: '50%' }}>
<div className="ml-8 mb-4 w-fit">
<Select
name="defaultInputMode"
options={inputModeOptions}
@ -91,67 +92,70 @@ const ProjectCodeSnippet: React.FC = (props: Props) => {
/>
</div>
<div className="mx-4" />
<div className="flex items-center ml-10">
<div className="flex items-center ml-8">
<Checkbox
name="maskNumbers"
type="checkbox"
checked={gdpr.maskNumbers}
onChange={onChangeOption}
onChange={(e) => onChangeOption('maskNumbers', e.target.checked)}
className="mr-2"
label="Do not record any numeric text"
/>
>
Do not record any numeric text
</Checkbox>
<div className="mx-4" />
<Checkbox
name="maskEmails"
type="checkbox"
checked={gdpr.maskEmails}
onChange={onChangeOption}
onChange={(e) => onChangeOption('maskEmails', e.target.checked)}
className="mr-2"
label="Do not record email addresses"
/>
>
Do not record email addresses
</Checkbox>
</div>
<div className={cn(stl.info, 'rounded-lg bg-gray mb-4 ml-8 bg-amber-50 w-fit text-sm mt-2', { hidden: !changed })}>
The code snippet below changes based on the selected data recording options and should be used for implementation.
</div>
</div>
<div className={cn(stl.info, 'rounded bg-gray mt-2 mb-4 ml-10', { hidden: !changed })}>
Below code snippet changes depending on the data recording options chosen.
</div>
<div className={cn(stl.instructions, 'mt-8')}>
<div className="font-semibold flex items-center">
<div className={cn(stl.instructions, 'flex flex-col !items-start !justify-start')}>
<div className="font-medium flex gap-1 items-center">
<CircleNumber text="2" />
<span>Enable Assist (Optional)</span>
</div>
</div>
<div className="ml-10">
<p>
OpenReplay Assist allows you to support your users by seeing their live screen and
instantly hopping on call (WebRTC) with them without requiring any 3rd-party screen
sharing software.
</p>
<Toggler
label="Yes"
checked={isAssistEnabled}
name="test"
className="font-medium mr-2"
onChange={() => setAssistEnabled(!isAssistEnabled)}
/>
</div>
<div className={cn(stl.instructions, 'mt-8')}>
<div className="font-semibold flex items-center">
<CircleNumber text="3" />
<span>Install SDK</span>
<div className="ml-7">
<div className="flex gap-2 items-center">
<Switch
checked={isAssistEnabled}
className="font-normal"
onChange={() => setAssistEnabled(!isAssistEnabled)}
size="small"
/>
<span>Enable</span>
</div>
<span className="text-sm text-neutral-400">
OpenReplay Assist allows you to support your users by seeing their
live screen and instantly hopping on call (WebRTC) with them without
requiring any 3rd-party screen sharing software.
</span>
</div>
</div>
<div className="ml-10 mb-2">
Paste this snippet <span>{'before the '}</span>
<span className={stl.highLight}> {'</head>'} </span>
<span>{' tag of your page.'}</span>
</div>
<div className={cn(stl.snippetsWrapper, 'ml-10')}>
<div className={cn(stl.instructions, '')}>
<div className='flex flex-col w-full'>
<div className='flex flex-col items-start justify-start gap-2'>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="3" />
<span>Install SDK</span>
</div>
<div className="ml-8 flex gap-2 items-center">
<div>Paste this snippet <span>{'before the '}</span></div>
<Tag color="red" bordered={false} className='rounded-lg text-base mr-0'> {'</head>'} </Tag>
<span>{' tag of your page.'}</span>
</div>
</div>
<div className={cn(stl.snippetsWrapper, 'ml-8')}>
{showLoader ? (
<div style={{ height: '474px' }}>
<Loader loading={true} />
@ -168,8 +172,14 @@ const ProjectCodeSnippet: React.FC = (props: Props) => {
/>
)}
</div>
</div>
</div>
</div>
);
};
export default observer(ProjectCodeSnippet);
export default observer(ProjectCodeSnippet);

View file

@ -2,7 +2,7 @@ import React, { ChangeEvent, FormEvent, useEffect } from 'react';
import { Icon } from 'UI';
import Project from '@/mstore/types/project';
import { projectStore, useStore } from '@/mstore';
import { Modal, Segmented, Form, Input, Button } from 'antd';
import { Modal, Segmented, Form, Input, Button, Tooltip } from 'antd';
import { toast } from 'react-toastify';
import { observer } from 'mobx-react-lite';
@ -39,6 +39,9 @@ function ProjectForm(props: Props) {
// void projectsStore.fetchList();
// }
toast.success('Project updated successfully');
if (onClose) {
onClose(null);
}
} else {
toast.error(response.errors[0]);
}
@ -80,6 +83,13 @@ function ProjectForm(props: Props) {
});
};
const handleCancel = () => {
form.resetFields();
if (onClose) {
onClose(null);
}
};
console.log('ProjectForm', project);
return (
@ -94,6 +104,7 @@ function ProjectForm(props: Props) {
label="Name"
name="name"
rules={[{ required: true, message: 'Please enter a name' }]}
className='font-medium'
>
<Input
placeholder="Ex. OpenReplay"
@ -101,9 +112,10 @@ function ProjectForm(props: Props) {
maxLength={40}
value={project.name}
onChange={handleEdit}
className='font-normal rounded-lg'
/>
</Form.Item>
<Form.Item label="Project Type">
<Form.Item label="Project Type" className='font-medium'>
<div>
<Segmented
options={[
@ -125,23 +137,35 @@ function ProjectForm(props: Props) {
</div>
</Form.Item>
<div className="mt-6 flex justify-between">
<div className='flex gap-0 items-center'>
<Button
htmlType="submit"
type="primary"
className="float-left mr-2"
className="float-left mr-2 btn-add-edit-project"
loading={loading}
// disabled={!project.validate}
>
{project.exists() ? 'Update' : 'Add'}
{project.exists() ? 'Save' : 'Add'}
</Button>
<Button
type="text"
onClick={handleCancel}
className="btn-cancel-project"
>
Cancel
</Button>
</div>
{project.exists() && (
<Tooltip title='Delete project' placement='top' >
<Button
variant="text"
type="text"
onClick={handleRemove}
disabled={!canDelete}
className='btn-delete-project'
>
<Icon name="trash" size="16" />
</Button>
</Tooltip>
)}
</div>
</Form>

View file

@ -1,10 +1,10 @@
import React from 'react';
import { Avatar, Button, Input, Menu, MenuProps, Progress, Typography } from 'antd';
import { Avatar, Button, Input, Menu, MenuProps, Progress, Typography, Tooltip } from 'antd';
import { useStore } from '@/mstore';
import Project from '@/mstore/types/project';
import { observer } from 'mobx-react-lite';
import { AppWindowMac, EditIcon, Smartphone } from 'lucide-react';
import { PencilIcon } from '.store/lucide-react-virtual-3cff663764/package';
import { AppWindowMac, EditIcon, Smartphone, } from 'lucide-react';
import {PlusOutlined, SearchOutlined, EditOutlined} from '@ant-design/icons'
import ProjectForm from 'Components/Client/Projects/ProjectForm';
import { useModal } from 'Components/ModalContext';
@ -41,7 +41,7 @@ const ProjectList: React.FC = () => {
key: project.id + '',
label: <Typography.Text style={{ color: 'inherit' }} ellipsis={true}>{project.name}</Typography.Text>,
extra: <Button onClick={(e) => projectEditHandler(e, project)} className="flex opacity-0 group-hover:!opacity-100"
size="small" type="link" icon={<PencilIcon size={14} />} />,
size="small" type="link" icon={<EditOutlined size={14} />} />,
className: 'group',
icon: (
<ProjectIconWithProgress
@ -51,25 +51,36 @@ const ProjectList: React.FC = () => {
)
}));
const createProject = () => {
openModal(<ProjectForm onClose={closeModal} project={new Project()} />, {
title: 'New Project'
});
};
return (
<div className="h-full flex flex-col gap-4">
<div className="px-4 mt-4">
<Input.Search
<div className="flex flex-row gap-2 items-center p-3">
<Tooltip title='Create Project' placement='bottom'>
<Button onClick={createProject} type='primary' ghost size='middle' shape="circle" icon={<PlusOutlined size={16}/>}></Button>
</Tooltip>
<Input
placeholder="Search projects"
onSearch={handleSearch}
// onSearch={handleSearch}
prefix={<SearchOutlined />}
onChange={(e) => setSearch(e.target.value)}
allowClear
className='rounded-lg'
/>
</div>
<div
className="overflow-y-auto"
className="overflow-y-auto pref-projects-menu"
style={{ height: 'calc(100vh - 250px)' }}
>
<Menu
mode="inline"
onClick={onClick}
selectedKeys={[String(projectsStore.config.pid)]}
className="w-full !bg-white !border-0"
className="w-full !bg-white !border-0 "
inlineIndent={11}
items={menuItems}
/>
@ -84,6 +95,7 @@ const ProjectIconWithProgress: React.FC<{
platform: string;
progress: number;
}> = ({ platform, progress }) => (
<Tooltip title={`${progress}% Capture Rate`}>
<div className="relative flex items-center justify-center mr-2 leading-none">
<Progress
type="circle"
@ -107,4 +119,5 @@ const ProjectIconWithProgress: React.FC<{
/>
</div>
</div>
</Tooltip>
);

View file

@ -1,7 +1,7 @@
import React from 'react';
import Project from '@/mstore/types/project';
import { Tabs } from 'UI';
import {AppleOutlined, AndroidOutlined, CodeOutlined, JavaScriptOutlined} from '@ant-design/icons';
import usePageTitle from '@/hooks/usePageTitle';
import InstallDocs from 'Components/Onboarding/components/OnboardingTabs/InstallDocs';
import ProjectCodeSnippet from 'Components/Client/Projects/ProjectCodeSnippet';
@ -41,18 +41,32 @@ function WebSnippet({ project }: { project: Project }) {
const [isNpm, setIsNpm] = React.useState(true);
return (
<div className="flex flex-col gap-4">
<div className="">
<Segmented
options={[
{ label: 'Using NPM', value: true },
{ label: 'Using Script', value: false }
]}
value={isNpm}
onChange={setIsNpm}
block={true}
style={{ maxWidth: '200px' }}
className="!align-middle"
/>
options={[
{
label: (
<div className="flex items-center gap-2">
<CodeOutlined />
<span>NPM</span>
</div>
),
value: true,
},
{
label: (
<div className="flex items-center gap-2">
<JavaScriptOutlined />
<span>Script</span>
</div>
),
value: false,
},
]}
value={isNpm}
onChange={setIsNpm}
className="!align-middle text-center rounded-lg"
/>
{isNpm ? (
<InstallDocs site={project} />
@ -68,25 +82,39 @@ function MobileSnippet({ project }: { project: Project }) {
const ingestPoint = `https://${window.location.hostname}/ingest`;
return (
<div className="flex flex-col gap-4">
<div>
<Segmented
options={[
{ label: 'iOS', value: true },
{ label: 'Android', value: false }
{
label: (
<div className="flex items-center gap-2">
<AppleOutlined />
<span>iOS</span>
</div>
),
value: true,
},
{
label: (
<div className="flex items-center gap-2">
<AndroidOutlined />
<span>Android</span>
</div>
),
value: false,
},
]}
value={isIos}
onChange={setIsIos}
block={true}
style={{ maxWidth: '150px' }}
className="!align-middle"
className='rounded-lg'
/>
{isIos ? (
<MobileInstallDocs site={project} ingestPoint={ingestPoint} />
) : (
<AndroidInstallDocs site={project} ingestPoint={ingestPoint} />
)}
</div>
);
}

View file

@ -37,25 +37,16 @@ function Projects() {
history.push({ search: params.toString() });
}, [pid, tab]);
const createProject = () => {
openModal(<ProjectForm onClose={closeModal} project={new Project()} />, {
title: 'New Project'
});
};
return (
<Card
style={{ height: 'calc(100vh - 130px)' }}
className="rounded-lg shadow-sm"
classNames={{
header: '!border-b !px-4',
body: '!p-0 !border-t'
body: '!p-0 !border-t',
}}
title={<Typography.Title level={4} className="!m-0">Projects</Typography.Title>}
extra={[
<Button onClick={createProject} icon={<PlusIcon size={18} />}>
Create Project
</Button>
]}
>
<Layout>
<Layout.Sider width={260} trigger={null}
@ -68,7 +59,7 @@ function Projects() {
style={{ height: 46 }}>
<div className="flex items-center gap-4">
<Typography.Title level={5}
className="capitalize !m-0 whitespace-nowrap truncate">
className="capitalize !m-0 whitespace-nowrap truncate !font-medium">
{project?.name}
</Typography.Title>
<ProjectKeyButton project={project} />
@ -77,10 +68,10 @@ function Projects() {
</Layout.Header>
<Layout.Content
style={{
padding: 24,
padding:'1.5rem 1rem',
height: 'calc(100vh - 260px)'
}}
className="bg-white overflow-y-auto"
className="bg-white overflow-y-auto "
>
{project && <ProjectTabContent />}
</Layout.Content>

View file

@ -84,7 +84,6 @@
.info {
padding: 5px 10px;
background-color: #ffedd1;
}
.number {

View file

@ -1,6 +1,6 @@
.number {
width: 24px;
height: 24px;
width: 20px;
height: 20px;
background-color: black;
display: flex;
justify-content: center;
@ -8,6 +8,6 @@
border-radius: 50%;
color: white;
font-size: 12px;
margin-right: 10px;
flex-shrink: 0;
padding-top: .15rem;
}

View file

@ -69,13 +69,13 @@ function AndroidInstallDocs({ site, ingestPoint }: any) {
.replace('INGEST_POINT', ingestPoint);
return (
<div>
<div className="mb-4">
<div className="font-semibold mb-2 flex items-center">
<div className='flex flex-col gap-4 mt-4'>
<div>
<div className="font-medium flex items-center gap-2">
<CircleNumber text="1" />
Install the SDK
<span>Install the SDK</span>
</div>
<div className={cn(stl.snippetWrapper, 'ml-10')}>
<div className={cn(stl.snippetWrapper, 'ml-8')}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={installationCommand} />
</div>
@ -83,83 +83,95 @@ function AndroidInstallDocs({ site, ingestPoint }: any) {
</div>
</div>
<div className="font-semibold mb-2 flex items-center">
<CircleNumber text="2" />
Add to your app
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={_usageCode} />
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="2" />
<span>Add to your app</span>
</div>
<div className="flex ml-8 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={_usageCode} />
</div>
<CodeBlock language={'kt'} code={_usageCode} />
</div>
<CodeBlock language={'kt'} code={_usageCode} />
</div>
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="3" />
Configuration
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<CodeBlock code={configuration} language={'kt'} />
<div className={'mt-2'}>
By default, all options equals{' '}
<code className={'p-1 text-red rounded bg-gray-lightest'}>
true
</code>
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="3" />
<span>Configuration</span>
</div>
<div className="flex ml-8 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<CodeBlock code={configuration} language={'kt'} />
<div className={'mt-2'}>
By default, all options equals{' '}
<code className={'p-1 text-red rounded bg-gray-lightest'}>
true
</code>
</div>
</div>
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="4" />
Set up touch events listener
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={touches} />
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="4" />
<span> Set up touch events listener</span>
</div>
<div className="flex ml-8 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={touches} />
</div>
<CodeBlock code={touches} language={'kt'} />
</div>
<CodeBlock code={touches} language={'kt'} />
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="5" />
Hide sensitive views
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={sensitive} />
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="5" />
<span>Hide sensitive views</span>
</div>
<div className="flex ml-8 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={sensitive} />
</div>
<CodeBlock code={sensitive} language={'kt'} />
</div>
</div>
</div>
</div>
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="6" />
<span>Track inputs</span>
</div>
<div className="flex ml-8 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={inputs} />
</div>
<CodeBlock code={inputs} language={'kt'} />
</div>
<CodeBlock code={sensitive} language={'kt'} />
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="6" />
Track inputs
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={inputs} />
</div>
<CodeBlock code={inputs} language={'kt'} />
</div>
</div>
</div>
</div>
);
}

View file

@ -33,26 +33,27 @@ function InstallDocs({ site }) {
const _usageCodeSST = usageCodeSST.replace('PROJECT_KEY', site.projectKey);
const [isSpa, setIsSpa] = useState(true);
return (
<div>
<div className="mb-6">
<div className="font-semibold mb-2 flex items-center">
<div className='flex flex-col gap-4 mt-4'>
<div>
<div className="font-medium mb-2 flex gap-2 items-center">
<CircleNumber text="1" />
Install the npm package.
<span>Install the npm package.</span>
</div>
<div className={cn(stl.snippetWrapper, 'ml-10')}>
<div className={cn(stl.snippetWrapper, 'ml-8')}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={installationCommand} />
</div>
<CodeBlock code={installationCommand} language={'bash'} />
</div>
</div>
<div className={'mb-6'}>
<div className="font-semibold mb-2 flex items-center">
<div>
<div className="font-medium mb-2 flex gap-2 items-center">
<CircleNumber text="2" />
Continue with one of the following options.
<span>Continue with one of the following options.</span>
</div>
<div className="flex items-center ml-10 cursor-pointer">
<div className="flex items-center ml-8 cursor-pointer">
<div className="mr-2" onClick={() => setIsSpa(!isSpa)}>
Server-Side-Rendered (SSR)?
</div>
@ -63,8 +64,9 @@ function InstallDocs({ site }) {
// style={{ lineHeight: '23px' }}
/>
</div>
<div className="flex ml-10 mt-4">
<div className="flex ml-8">
<div className="w-full">
{isSpa && (
<div>
@ -102,14 +104,14 @@ function InstallDocs({ site }) {
</div>
<div>
<div className="font-semibold mb-2 flex items-center">
<div className="font-medium mb-2 flex gap-2 items-center">
<CircleNumber text="3" />
Enable Assist (Optional)
<span>Enable Assist (Optional)</span>
</div>
<div className="flex ml-10 mt-4">
<div className="flex ml-8 mt-4">
<div className="w-full">
<div>
<div className="mb-2">
<div className='-mb-2'>
Install the plugin via npm:
</div>
<div className={cn(stl.snippetWrapper)}>
@ -120,7 +122,7 @@ function InstallDocs({ site }) {
</div>
</div>
<div>
<div className={'mb-2'}>
<div className='-mb-2'>
Then enable it with your tracker:
</div>
<div className={cn(stl.snippetWrapper)}>

View file

@ -75,13 +75,13 @@ function MobileInstallDocs({ site, ingestPoint }: any) {
const _usageCode = usageCode.replace('INGEST_POINT', ingestPoint).replace('PROJECT_KEY', site.projectKey);
return (
<div>
<div className="mb-4">
<div className="font-semibold mb-2 flex items-center">
<div className='flex flex-col gap-4 mt-4'>
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="1" />
Install the Swift Package
<span>Install the Swift Package</span>
</div>
<div className={cn(stl.snippetWrapper, 'ml-10')}>
<div className={cn(stl.snippetWrapper, 'ml-8')}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={installationCommand} />
</div>
@ -89,78 +89,91 @@ function MobileInstallDocs({ site, ingestPoint }: any) {
</div>
</div>
<div className="font-semibold mb-2 flex items-center">
<CircleNumber text="2" />
Add to your app
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={_usageCode} />
<div>
<div className="font-medium gap-2 flex items-center">
<CircleNumber text="2" />
<span>Add to your app</span>
</div>
<div className="flex ml-8">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={_usageCode} />
</div>
<CodeBlock code={_usageCode} language={'swift'} />
</div>
<CodeBlock code={_usageCode} language={'swift'} />
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="3" />
Configuration
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<CodeBlock code={configuration} language={'swift'} />
<div className={"mt-2"}>By default, all options equals <code className={'p-1 text-red rounded bg-gray-lightest'}>true</code></div>
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="3" />
<span>Configuration</span>
</div>
<div className="flex ml-8 ">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<CodeBlock code={configuration} language={'swift'} />
<div className={"mt-2"}>By default, all options equals <code className={'p-1 text-red rounded bg-gray-lightest'}>true</code></div>
</div>
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="4" />
Set up touch events listener
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={touches} />
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="4" />
<span> Set up touch events listener</span>
</div>
<div className="flex ml-8">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={touches} />
</div>
<CodeBlock code={touches} language={'swift'} />
</div>
<CodeBlock code={touches} language={'swift'} />
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="5" />
Hide sensitive views
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={sensitive} />
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="5" />
<span>Hide sensitive views</span>
</div>
<div className="flex ml-8">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={sensitive} />
</div>
<CodeBlock code={sensitive} language={'swift'} />
</div>
<CodeBlock code={sensitive} language={'swift'} />
</div>
</div>
</div>
<div className="font-semibold mb-2 mt-4 flex items-center">
<CircleNumber text="6" />
Track inputs
</div>
<div className="flex ml-10 mt-4">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={inputs} />
<div>
<div className="font-medium flex gap-2 items-center">
<CircleNumber text="6" />
<span> Track inputs</span>
</div>
<div className="flex ml-8">
<div className="w-full">
<div className={cn(stl.snippetWrapper)}>
<div className="absolute mt-1 mr-2 right-0">
<CopyButton content={inputs} />
</div>
<CodeBlock code={inputs} language={'swift'} />
</div>
<CodeBlock code={inputs} language={'swift'} />
</div>
</div>
</div>
</div>
);
}

View file

@ -84,7 +84,6 @@
.info {
padding: 5px 10px;
background-color: #ffedd1;
}
.number {

View file

@ -84,5 +84,4 @@
.info {
padding: 5px 10px;
background-color: #ffedd1;
}

View file

@ -10,7 +10,7 @@ export default function CodeBlock({ code, language = 'javascript' }) {
}, [code, language]);
return (
<pre>
<pre className='rounded-lg'>
<code className={`language-${language}`}>
{code}
</code>

View file

@ -1,7 +1,7 @@
import React from 'react'
import { useState } from 'react';
import copy from 'copy-to-clipboard';
import { Button } from 'UI';
import { Button } from 'antd';
function CopyButton({ content, variant="text-primary", className = '', btnText = 'copy' }) {
const [copied, setCopied] = useState(false)
@ -16,9 +16,10 @@ function CopyButton({ content, variant="text-primary", className = '', btnText
return (
<Button
variant={variant}
className={ className + ' capitalize' }
type='text'
onClick={ copyHandler }
size='small'
className='capitalize mt-2 font-medium text-neutral-400'
>
{ copied ? 'copied' : btnText }
</Button>

View file

@ -414,6 +414,17 @@ p {
background-color: #E6E9FA;
}
.pref-projects-menu .ant-menu-light .ant-menu-item-selected{
background-color: #F6F7FF;
color: rgba(0,0,0,.7);
font-weight: 500;
}
.pref-projects-menu .ant-menu-light .ant-menu-item{
margin-bottom: .5rem;
border-radius: .75rem;
}
.dashboardDataPeriodSelector .dashboardMoreOptionsLabel{
display: none;
}