ui: migrating old components -> ant (#3060)

* ui: migrating old components -> ant

* ui: moving input, tooltip, toggler, checkbox... -> Toggler\s*(.)? from 'UI

* ui: more components moved

* ui: move popover to ant
This commit is contained in:
Delirium 2025-02-24 16:11:44 +01:00 committed by GitHub
parent 1122ced4c3
commit 968a3eefde
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
142 changed files with 525 additions and 2352 deletions

View file

@ -18,11 +18,6 @@ const components: any = {
AssistPure: lazy(() => import('Components/Assist/AssistRouter')),
SessionsOverviewPure: lazy(() => import('Components/Overview')),
DashboardPure: lazy(() => import('Components/Dashboard/NewDashboard')),
FunnelDetailsPure: lazy(() => import('Components/Funnels/FunnelDetails')),
FunnelIssueDetails: lazy(
() => import('Components/Funnels/FunnelIssueDetails')
),
FunnelPagePure: lazy(() => import('Components/Funnels/FunnelPage')),
MultiviewPure: lazy(() => import('Components/Session_/Multiview/Multiview')),
UsabilityTestingPure: lazy(
() => import('Components/UsabilityTesting/UsabilityTesting')
@ -47,9 +42,6 @@ const enhancedComponents: any = {
Assist: withSiteIdUpdater(components.AssistPure),
Client: withSiteIdUpdater(components.ClientPure),
Onboarding: withSiteIdUpdater(components.OnboardingPure),
FunnelPage: withSiteIdUpdater(components.FunnelPagePure),
FunnelsDetails: withSiteIdUpdater(components.FunnelDetailsPure),
FunnelIssue: withSiteIdUpdater(components.FunnelIssueDetails),
Multiview: withSiteIdUpdater(components.MultiviewPure),
UsabilityTesting: withSiteIdUpdater(components.UsabilityTestingPure),
UsabilityTestEdit: withSiteIdUpdater(components.UsabilityTestEditPure),
@ -85,9 +77,6 @@ const FFLAG_READ_PATH = routes.fflagRead();
const NOTES_PATH = routes.notes();
const BOOKMARKS_PATH = routes.bookmarks();
const RECORDINGS_PATH = routes.recordings();
const FUNNEL_PATH = routes.funnels();
const FUNNEL_CREATE_PATH = routes.funnelsCreate();
const FUNNEL_ISSUE_PATH = routes.funnelIssue();
const SESSION_PATH = routes.session();
const CLIENT_PATH = routes.client();
const ONBOARDING_PATH = routes.onboarding();
@ -246,24 +235,6 @@ function PrivateRoutes() {
path={withSiteId(HIGHLIGHTS_PATH, siteIdList)}
component={enhancedComponents.Highlights}
/>
<Route
exact
strict
path={withSiteId(FUNNEL_PATH, siteIdList)}
component={enhancedComponents.FunnelPage}
/>
<Route
exact
strict
path={withSiteId(FUNNEL_CREATE_PATH, siteIdList)}
component={enhancedComponents.FunnelsDetails}
/>
<Route
exact
strict
path={withSiteId(FUNNEL_ISSUE_PATH, siteIdList)}
component={enhancedComponents.FunnelIssue}
/>
<Route
exact
strict

View file

@ -1,11 +1,10 @@
import React, { useEffect } from 'react';
import stl from './notifications.module.css';
import { Icon, Tooltip } from 'UI';
import { Icon } from 'UI';
import { useModal } from 'App/components/Modal';
import AlertTriggersModal from 'Shared/AlertTriggersModal';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { Badge, Button } from 'antd';
import { Badge, Button, Tooltip } from 'antd';
import { BellOutlined } from '@ant-design/icons';

View file

@ -1,10 +1,10 @@
import React, { useState } from 'react'
import stl from './ChatControls.module.css'
import cn from 'classnames'
import { Button, Icon } from 'UI'
import { Icon } from 'UI'
import { Button } from 'antd'
import type { LocalStream } from 'Player';
interface Props {
stream: LocalStream | null,
endCall: () => void,
@ -35,17 +35,15 @@ function ChatControls({ stream, endCall, videoEnabled, setVideoEnabled, isPresta
return (
<div className={cn(stl.controls, "flex items-center w-full justify-start bottom-0 px-2")}>
<div className="flex items-center">
<div className="flex items-center gap-2">
<div className={cn(stl.btnWrapper, { [stl.disabled]: audioEnabled})}>
<Button variant="text" onClick={toggleAudio} hover>
<Icon name={audioEnabled ? 'mic' : 'mic-mute'} size="16" />
<Button size={'small'} variant="text" onClick={toggleAudio} icon={<Icon name={audioEnabled ? 'mic' : 'mic-mute'} size="16" />}>
<span className={cn("ml-1 color-gray-medium text-sm", { 'color-red' : audioEnabled })}>{audioEnabled ? 'Mute' : 'Unmute'}</span>
</Button>
</div>
<div className={cn(stl.btnWrapper, { [stl.disabled]: videoEnabled})}>
<Button variant="text" onClick={toggleVideo} hover>
<Icon name={ videoEnabled ? 'camera-video' : 'camera-video-off' } size="16" />
<Button size={'small'} variant="text" onClick={toggleVideo} icon={<Icon name={ videoEnabled ? 'camera-video' : 'camera-video-off' } size="16" />}>
<span className={cn("ml-1 color-gray-medium text-sm", { 'color-red' : videoEnabled })}>{videoEnabled ? 'Stop Video' : 'Start Video'}</span>
</Button>
</div>

View file

@ -1,6 +1,7 @@
import { useObserver } from 'mobx-react-lite';
import React from 'react';
import { Button, Modal, Form, Icon, Input } from 'UI';
import { Modal, Form, Icon, Input } from 'UI';
import { Button } from 'antd'
interface Props {
show: boolean;
@ -57,7 +58,7 @@ function EditRecordingModal(props: Props) {
<Modal.Footer>
<div className="-mx-2 px-2">
<Button
variant="primary"
type="primary"
onClick={ save }
className="float-left mr-2"
>

View file

@ -1,6 +1,7 @@
import React from 'react';
import { INDEXES } from 'App/constants/zindex';
import { Button, Loader, Icon } from 'UI';
import { Loader, Icon } from 'UI';
import { Button } from 'antd'
import { PlayerContext } from 'App/components/Session/playerContext';
import { useStore } from "App/mstore";
import { observer } from 'mobx-react-lite';
@ -76,7 +77,7 @@ function RequestingWindow({ getWindowType }: Props) {
</div>
<span>{WIN_VARIANTS[windowType].text}</span>
<Loader size={30} style={{ minHeight: 60 }} />
<Button variant="text-primary" onClick={actions[WIN_VARIANTS[windowType].action]}>
<Button variant="text" onClick={actions[WIN_VARIANTS[windowType].action]}>
Cancel
</Button>
</div>

View file

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
import { Button, Tooltip } from 'UI';
import { Button } from 'antd';
import cn from 'classnames';
import ChatWindow from '../../ChatWindow';
import { CallingState, ConnectionStatus, RemoteControlStatus, RequestLocalStream } from 'Player';
@ -7,7 +7,7 @@ import type { LocalStream } from 'Player';
import { PlayerContext, ILivePlayerContext } from 'App/components/Session/playerContext';
import { observer } from 'mobx-react-lite';
import { toast } from 'react-toastify';
import { confirm } from 'UI';
import { confirm, Icon, Tooltip } from 'UI';
import stl from './AassistActions.module.css';
import ScreenRecorder from 'App/components/Session_/ScreenRecorder/ScreenRecorder';
import { audioContextManager } from 'App/utils/screenRecorder';
@ -213,9 +213,10 @@ function AssistActions({
role="button"
>
<Button
icon={annotating ? 'pencil-stop' : 'pencil'}
variant={annotating ? 'text-red' : 'text-primary'}
icon={<Icon name={annotating ? 'pencil-stop' : 'pencil'} size={16} />}
type={'text'}
style={{ height: '28px' }}
className={annotating ? 'text-red' : 'text-main'}
>
Annotate
</Button>
@ -238,8 +239,9 @@ function AssistActions({
role="button"
>
<Button
icon={remoteActive ? 'window-x' : 'remote-control'}
variant={remoteActive ? 'text-red' : 'text-primary'}
icon={<Icon name={remoteActive ? 'window-x' : 'remote-control'} size={16} />}
type={'text'}
className={remoteActive ? 'text-red' : 'text-main'}
style={{ height: '28px' }}
>
Remote Control
@ -264,8 +266,9 @@ function AssistActions({
role="button"
>
<Button
icon="headset"
variant={onCall ? 'text-red' : isPrestart ? 'green' : 'primary'}
icon={<Icon name={'headset'} size={16} />}
type={'text'}
className={onCall ? 'text-red' : isPrestart ? 'text-green' : 'text-main'}
style={{ height: '28px' }}
>
{onCall ? 'End' : isPrestart ? 'Join Call' : 'Call'}

View file

@ -1,5 +1,6 @@
import React, { useEffect } from 'react';
import { PageTitle, Icon, Button } from 'UI';
import { PageTitle, Icon } from 'UI';
import { Button } from 'antd'
import AuditList from '../AuditList';
import AuditSearchField from '../AuditSearchField';
import { useStore } from 'App/mstore';
@ -61,8 +62,7 @@ function AuditView() {
auditStore.updateKey('page', 1)
} }/>
<div>
<Button variant="text-primary" className="ml-3" onClick={exportToCsv}>
<Icon name="grid-3x3" color="teal" />
<Button type="text" icon={<Icon name="grid-3x3" color="teal" />} className="ml-3" onClick={exportToCsv}>
<span className="ml-2">Export to CSV</span>
</Button>
</div>

View file

@ -1,6 +1,7 @@
import React from 'react';
import cn from 'classnames';
import { Button } from 'UI';
import { Icon } from 'UI';
import { Button } from 'antd';
import styles from './listItem.module.css';
const ListItem = ({ field, onEdit, disabled }) => {
@ -17,7 +18,7 @@ const ListItem = ({ field, onEdit, disabled }) => {
>
<span>{field.key}</span>
<div className="invisible group-hover:visible" data-hidden={field.index === 0}>
<Button variant="text-primary" icon="pencil" />
<Button type="text" icon={<Icon name={"pencil"} size={16} />} />
</div>
</div>
);

View file

@ -3,7 +3,8 @@ import React from 'react';
import { useStore } from 'App/mstore';
import { namedStore } from 'App/mstore/integrationsStore';
import { Button, Checkbox, Form, Input, Loader } from 'UI';
import { Checkbox, Form, Input, Loader } from 'UI';
import { Button } from 'antd'
import { toast } from 'react-toastify';
function IntegrationForm(props: any) {
@ -97,7 +98,7 @@ function IntegrationForm(props: any) {
onClick={save}
disabled={!config?.validate()}
loading={loading}
variant="primary"
type="primary"
className="float-left mr-2"
>
{config?.exists() ? 'Update' : 'Add'}

View file

@ -1,6 +1,6 @@
import React from 'react';
import { Form, Input, Button, Message } from 'UI';
import { confirm } from 'UI';
import { Form, Input, Message, confirm } from 'UI';
import { Button } from 'antd'
import { observer } from 'mobx-react-lite'
import { useStore } from 'App/mstore'
@ -73,7 +73,7 @@ function SlackAddForm(props) {
onClick={save}
disabled={!instance.validate()}
loading={saving}
variant="primary"
type="primary"
className="float-left mr-2"
>
{instance.exists() ? 'Update' : 'Add'}

View file

@ -1,7 +1,8 @@
import React, { useEffect } from 'react';
import SlackChannelList from './SlackChannelList/SlackChannelList';
import SlackAddForm from './SlackAddForm';
import { Button } from 'UI';
import { Icon } from 'UI';
import { Button } from 'antd';
import { observer } from 'mobx-react-lite'
import { useStore } from 'App/mstore'
@ -34,7 +35,7 @@ const SlackForm = () => {
<div className="shrink-0" style={{ width: '350px' }}>
<div className="flex items-center p-5">
<h3 className="text-2xl mr-3">Slack</h3>
<Button rounded={true} icon="plus" iconSize={24} variant="outline" onClick={onNew}/>
<Button shape={'circle'} type={'text'} icon={<Icon name={"plus"} size={24} />} onClick={onNew}/>
</div>
<SlackChannelList onEdit={onEdit} />
</div>

View file

@ -2,8 +2,8 @@ import { observer } from 'mobx-react-lite';
import React from 'react';
import { useStore } from 'App/mstore';
import { Button, Form, Input, Message } from 'UI';
import { confirm } from 'UI';
import { confirm, Form, Input, Message } from 'UI';
import { Button } from 'antd'
interface Props {
onClose: () => void;
@ -83,7 +83,7 @@ function TeamsAddForm({ onClose }: Props) {
onClick={save}
disabled={!instance?.validate()}
loading={saving}
variant="primary"
type="primary"
className="float-left mr-2"
>
{instance?.exists() ? 'Update' : 'Add'}

View file

@ -1,10 +1,11 @@
import React, { useEffect } from 'react';
import TeamsChannelList from './TeamsChannelList';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { Icon } from 'UI';
import { Button } from 'antd'
import TeamsChannelList from './TeamsChannelList';
import TeamsAddForm from './TeamsAddForm';
import { Button } from 'UI';
const MSTeams = () => {
const { integrationsStore } = useStore();
@ -35,7 +36,7 @@ const MSTeams = () => {
<div className="shrink-0" style={{ width: '350px' }}>
<div className="flex items-center p-5">
<h3 className="text-2xl mr-3">Microsoft Teams</h3>
<Button rounded={true} icon="plus" iconSize={24} variant="outline" onClick={onNew}/>
<Button shape={'circle'} icon={<Icon name={'plus'} size={24} />} type="text" onClick={onNew}/>
</div>
<TeamsChannelList onEdit={onEdit} />
</div>

View file

@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import cn from 'classnames';
import stl from './notifications.module.css';
import { Toggler } from 'UI';
import { Switch } from 'antd'
import { useStore } from "App/mstore";
import { observer } from 'mobx-react-lite'
import withPageTitle from 'HOCs/withPageTitle';
@ -25,12 +25,13 @@ function Notifications() {
<div className="">
<div className="text-lg font-medium">Weekly project summary</div>
<div className="mb-4">Receive weekly report for each project on email.</div>
<Toggler
<div className={'flex items-center gap-2'}>
<Switch
checked={weeklyReportStore.weeklyReport}
name="test"
onChange={onChange}
label={weeklyReportStore.weeklyReport ? 'Yes' : 'No'}
/>
<span>{weeklyReportStore.weeklyReport ? 'Yes' : 'No'}</span>
</div>
</div>
</div>
);

View file

@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react';
import { Button, Message, Form, Input } from 'UI';
import { Message, Form, Input } from 'UI';
import { Button } from 'antd'
import styles from './profileSettings.module.css';
import { validatePassword } from 'App/validate';
import { PASSWORD_POLICY } from 'App/constants';
@ -121,7 +122,7 @@ const ChangePassword = () => {
{PASSWORD_POLICY}
</Message>
<div className="flex items-center pt-3">
<Button type="submit" variant="outline" disabled={isSubmitDisabled()} loading={loading}>
<Button htmlType="submit" type="default" disabled={isSubmitDisabled()} loading={loading}>
Change Password
</Button>
<Button
@ -139,7 +140,7 @@ const ChangePassword = () => {
</Form>
) : (
<div onClick={() => setShow(true)}>
<Button variant="text-primary">Change Password</Button>
<Button type="text">Change Password</Button>
</div>
);
};

View file

@ -1,5 +1,6 @@
import React from 'react';
import { Button, Input, Form } from 'UI';
import { Input, Form } from 'UI';
import { Button } from 'antd'
import styles from './profileSettings.module.css';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
@ -61,7 +62,7 @@ function Settings() {
/>
</Form.Field>
<Button variant="outline" loading={loading} disabled={!changed} type="submit">
<Button type="default" loading={loading} disabled={!changed} htmlType="submit">
{'Update'}
</Button>
</Form>

View file

@ -1,6 +1,7 @@
import React from 'react';
import copy from 'copy-to-clipboard';
import { Form, Input, Button } from "UI";
import { Form, Input } from "UI";
import { Button } from 'antd';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
@ -29,8 +30,7 @@ function TenantKey() {
value={ tenantKey }
leadingButton={
<Button
variant="text-primary"
role="button"
type="text"
onClick={ copyHandler }
>
{ copied ? 'Copied' : 'Copy' }

View file

@ -5,8 +5,8 @@ import React, { useEffect } from 'react';
import { useModal } from 'App/components/Modal';
import { useStore } from 'App/mstore';
import { Button, Loader, NoContent, Tooltip } from 'UI';
import { confirm } from 'UI';
import { Loader, NoContent, Tooltip, confirm } from 'UI';
import { Button } from 'antd'
import RoleForm from './components/RoleForm';
import RoleItem from './components/RoleItem';
@ -68,7 +68,7 @@ function Roles() {
title="You dont have the permissions to perform this action."
disabled={isAdmin}
>
<Button variant="primary" onClick={() => editHandler({})}>
<Button type="primary" onClick={() => editHandler({})}>
Add
</Button>
</Tooltip>

View file

@ -2,10 +2,10 @@ import { observer } from 'mobx-react-lite';
import React, { useEffect, useRef } from 'react';
import { useStore } from 'App/mstore';
import { Button, Checkbox, Form, Icon, Input } from 'UI';
import { Checkbox, Form, Icon, Input } from 'UI';
import stl from './roleForm.module.css';
import { Select } from 'antd';
import { Select, Button } from 'antd';
import { SelectProps } from 'antd/es/select';
interface Props {
@ -220,7 +220,7 @@ const RoleForm = (props: Props) => {
onClick={_save}
disabled={!role.validate}
loading={saving}
variant="primary"
type="primary"
className="float-left mr-2"
>
{role.exists() ? 'Update' : 'Add'}
@ -228,7 +228,7 @@ const RoleForm = (props: Props) => {
{role.exists() && <Button onClick={closeModal}>{'Cancel'}</Button>}
</div>
{role.exists() && (
<Button variant="text" onClick={() => props.deleteHandler(role)}>
<Button type="text" onClick={() => props.deleteHandler(role)}>
<Icon name="trash" size="18" />
</Button>
)}

View file

@ -1,5 +1,6 @@
import React from 'react';
import { Icon, Link, Button } from 'UI';
import { Icon, Link } from 'UI';
import { Button } from 'antd'
import stl from './roleItem.module.css';
import cn from 'classnames';
import { CLIENT_TABS, client as clientRoute } from 'App/routes';
@ -46,7 +47,7 @@ function RoleItem({ role, editHandler, isAdmin, permissions, projects }: Props)
<div className={cn(stl.actions, 'absolute right-0 top-0 bottom-0 mr-8 invisible group-hover:visible')}>
{isAdmin && !!editHandler && (
<Button variant="text-primary" icon="pencil" disabled={role.protected} onClick={() => editHandler(role)} />
<Button type="text" icon={<Icon name={"pencil"} />} disabled={role.protected} onClick={() => editHandler(role)} />
)}
</div>
</div>

View file

@ -1,5 +1,6 @@
import React from 'react';
import { Tooltip, Button } from 'UI';
import { Tooltip } from 'UI';
import { Button } from 'antd'
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { useModal } from 'App/components/Modal';
@ -24,7 +25,7 @@ function AddProjectButton({ isAdmin = false }: any) {
title={`${!isAdmin ? PERMISSION_WARNING : !canAddProject ? LIMIT_WARNING : 'Add a Project'}`}
disabled={isAdmin || canAddProject}
>
<Button variant="primary" onClick={onClick} disabled={!canAddProject || !isAdmin}>
<Button type="primary" onClick={onClick} disabled={!canAddProject || !isAdmin}>
Add Project
</Button>
</Tooltip>

View file

@ -1,31 +0,0 @@
import React from 'react';
import { Input, Button, Icon } from 'UI';
import styles from './blockedIps.module.css';
class BlockedIps extends React.PureComponent {
render() {
return (
<div className={ styles.wrapper }>
<h4>{ 'Block IP' }</h4>
<div className={ styles.content }>
<label>{ 'List of IPs or Subnets to be blocked.' }</label>
<div className={ styles.inputWrapper }>
<Input type="text" />
<Button primary outline >{ 'Block' }</Button>
</div>
<div className={ styles.list }>
<div className={ styles.item }>
<div>{ '192.128.2.1' }</div>
<div className={ styles.actions }>
<Icon name="trash" size="14" color="gray-medium" />
</div>
</div>
</div>
</div>
</div>
);
}
}
export default BlockedIps;

View file

@ -1,7 +1,8 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from "App/mstore";
import { Form, Button, Input, Icon } from 'UI';
import { Form, Input, Icon } from 'UI';
import { Button } from 'antd'
import { validateNumber } from 'App/validate';
import styles from './siteForm.module.css';
import Select from 'Shared/Select';
@ -115,12 +116,13 @@ function GDPRForm(props) {
<div className={ styles.footer }>
<Button
variant="outline"
type="primary"
className="float-left mr-2"
loading={ saving }
content="Update"
/>
<Button onClick={ onClose } content="Cancel" />
>
Update
</Button>
<Button onClick={ onClose }>Close</Button>
</div>
</Form>
)

View file

@ -1,7 +1,7 @@
import { useModal } from 'App/components/Modal';
import React from 'react';
import TrackingCodeModal from 'Shared/TrackingCodeModal';
import { Button } from 'UI';
import { Button } from 'antd';
interface Props {
site: any;
@ -16,7 +16,7 @@ function InstallButton(props: Props) {
);
};
return (
<Button size="small" variant="text-primary" onClick={onClick}>
<Button size="small" type="text" onClick={onClick}>
{'Installation Steps'}
</Button>
);

View file

@ -3,8 +3,8 @@ import React, { ChangeEvent, FormEvent, useEffect, useState } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { toast } from 'react-toastify';
import { useStore } from 'App/mstore';
import { Button, Form, Icon, Input } from 'UI';
import { confirm } from 'UI';
import { confirm, Form, Icon, Input } from 'UI';
import { Button } from 'antd'
import { observer } from 'mobx-react-lite';
import styles from './siteForm.module.css';
@ -141,8 +141,8 @@ const NewSiteForm = ({ location: { pathname }, onClose }: Props) => {
</Form.Field>
<div className="mt-6 flex justify-between">
<Button
variant="primary"
type="submit"
type="primary"
htmlType="submit"
className="float-left mr-2"
loading={loading}
disabled={!site.validate}
@ -151,8 +151,7 @@ const NewSiteForm = ({ location: { pathname }, onClose }: Props) => {
</Button>
{site.exists() && (
<Button
variant="text"
type="button"
type="text"
onClick={handleRemove}
disabled={!canDelete}
>

View file

@ -1,7 +1,8 @@
import React, { useState } from 'react';
import { Tag } from 'antd';
import cn from 'classnames';
import { Loader, Button, TextLink, NoContent, Pagination, PageTitle, Divider, Icon } from 'UI';
import { Loader, TextLink, NoContent, Pagination, PageTitle, Divider, Icon } from 'UI';
import { Button } from 'antd';
import withPageTitle from 'HOCs/withPageTitle';
import stl from './sites.module.css';
import NewSiteForm from './NewSiteForm';
@ -52,7 +53,7 @@ const Sites = () => {
showModal(<NewSiteForm onClose={hideModal} />, { right: true });
};
return <Button icon="edit" variant="text-primary" disabled={!isAdmin} onClick={_onClick} />;
return <Button icon={<Icon name={"edit"} />} type="text" disabled={!isAdmin} onClick={_onClick} />;
};
const captureRateClickHandler = (project: Project) => {
@ -88,12 +89,12 @@ const Sites = () => {
<ProjectKey value={project.projectKey} tooltip="Project key copied to clipboard" />
</div>
<div className="col-span-3 flex items-center">
<Button variant="text-primary" onClick={() => captureRateClickHandler(project)}>
<Button type="text" onClick={() => captureRateClickHandler(project)}>
{project.sampleRate}%
</Button>
{project.conditionsCount > 0 ? (
<Button
variant="text-primary"
variant="text"
onClick={() => captureRateClickHandler(project)}
className="ml-2"
>

View file

@ -1,37 +0,0 @@
.wrapper {
width: 300px;
padding: 20px;
& label {
color: $gray-medium;
font-size: 12px;
}
}
.inputWrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.list {
margin-top: 20px;
display: none; /* TODO enable this once the API is Ready */
& .item {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: solid thin $gray-light;
padding: 8px 5px;
&:hover {
background-color: $active-blue;
& .actions {
opacity: 1;
}
}
& .actions {
opacity: 0;
}
}
}

View file

@ -1,5 +1,6 @@
import React from 'react';
import { Tooltip, Button } from 'UI';
import { Tooltip } from 'UI';
import { Button } from 'antd'
import { useStore } from 'App/mstore';
import { useObserver } from 'mobx-react-lite';
@ -17,7 +18,7 @@ function AddUserButton({ isAdmin = false, onClick, btnVariant = 'primary' }: any
title={`${!isAdmin ? PERMISSION_WARNING : !cannAddUser ? LIMIT_WARNING : 'Add team member'}`}
disabled={isAdmin || cannAddUser}
>
<Button disabled={!cannAddUser || !isAdmin} variant={btnVariant} onClick={onClick}>
<Button disabled={!cannAddUser || !isAdmin} type={btnVariant} onClick={onClick}>
Add Team Member
</Button>
</Tooltip>

View file

@ -5,8 +5,8 @@ import React from 'react';
import { useModal } from 'App/components/Modal';
import { useStore } from 'App/mstore';
import { Button, CopyButton, Form, Icon, Input } from 'UI';
import { confirm } from 'UI';
import { confirm, CopyButton, Form, Icon, Input } from 'UI';
import { Button } from 'antd'
import Select from 'Shared/Select';
@ -139,22 +139,20 @@ function UserForm() {
onClick={onSave}
disabled={!user.valid(isEnterprise) || isSaving}
loading={isSaving}
variant="primary"
type="primary"
className="float-left mr-2"
>
{user.exists() ? 'Update' : 'Invite'}
</Button>
{user.exists() && <Button onClick={hideModal}>{'Cancel'}</Button>}
</div>
<div>
<Button
disabled={user.isSuperAdmin}
data-hidden={!user.exists()}
onClick={deleteHandler}
>
<Icon name="trash" size="16" />
</Button>
</div>
{!user.exists() ? null :
<div>
<Button disabled={user.isSuperAdmin} onClick={deleteHandler}>
<Icon name="trash" size="16" />
</Button>
</div>
}
</div>
{!user.isJoined && user.invitationLink && (

View file

@ -1,6 +1,7 @@
//@ts-nocheck
import React from 'react';
import { Button, Tooltip } from 'UI';
import { Tooltip, Icon } from 'UI';
import { Button } from 'antd'
import { checkForRecent } from 'App/date';
import cn from 'classnames';
@ -79,9 +80,8 @@ function UserListItem(props: Props) {
{!user.isJoined && user.invitationLink && !user.isExpiredInvite && (
<Tooltip title="Copy Invite Code" hideOnClick={true}>
<Button
variant="text-primary"
icon="link-45deg"
className=""
type="text"
icon={<Icon name={"link-45deg"} />}
onClick={copyInviteCode}
/>
</Tooltip>
@ -90,15 +90,14 @@ function UserListItem(props: Props) {
{!user.isJoined && user.isExpiredInvite && (
<Tooltip title="Generate Invite" hideOnClick={true}>
<Button
icon="link-45deg"
variant="text-primary"
className=""
icon={<Icon name={"link-45deg"} />}
variant="text"
onClick={generateInvite}
/>
</Tooltip>
)}
</div>
<Button variant="text-primary" icon="pencil" />
<Button variant="text" icon={<Icon name={"pencil"} />} />
</div>
</div>
</div>

View file

@ -1,6 +1,6 @@
import React from 'react';
import cn from 'classnames';
import { Button } from 'UI';
import { Button } from 'antd';
import stl from './table.module.css';
export default class Table extends React.PureComponent {
@ -56,7 +56,7 @@ export default class Table extends React.PureComponent {
<div className="w-full flex justify-center mt-2">
<Button
onClick={ this.onLoadMoreClick }
variant="text-primary"
type="text"
>
{ rows.size + ' More' }
</Button>

View file

@ -1,5 +1,6 @@
import React from 'react'
import { Button, Icon } from 'UI'
import { Icon } from 'UI'
import { Button } from 'antd'
interface IBottomButtons {
loading: boolean
@ -14,8 +15,7 @@ function BottomButtons({ loading, instance, deleting, onDelete }: IBottomButtons
<div className="flex items-center">
<Button
loading={loading}
variant="primary"
type="submit"
type="primary"
disabled={loading || !instance.validate()}
id="submit-button"
>
@ -25,10 +25,8 @@ function BottomButtons({ loading, instance, deleting, onDelete }: IBottomButtons
<div>
{instance.exists() && (
<Button
hover
variant="text"
type="text"
loading={deleting}
type="button"
onClick={() => onDelete(instance)}
id="trash-button"
className="!text-teal !fill-teal"

View file

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useStore } from 'App/mstore';
import { observer, useObserver } from 'mobx-react-lite';
import { Button, Loader, NoContent, Pagination } from 'UI';
import { Loader, NoContent, Pagination } from 'UI';
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
import { InfoCircleOutlined } from '@ant-design/icons';
import { debounce } from 'App/utils';
@ -10,7 +10,7 @@ import CardIssueItem from './CardIssueItem';
import SessionsModal from '../SessionsModal';
import { useModal } from 'App/components/Modal';
import Issue from 'App/mstore/types/issue';
import { List } from 'antd';
import { List, Button } from 'antd';
function CardIssues() {
const { metricStore, dashboardStore } = useStore();
@ -104,8 +104,8 @@ function CardIssues() {
)}
</div>
<div className="flex items-center gap-4">
{hasFilters && <Button variant="text-primary" onClick={clearFilters}>Clear Filters</Button>}
<Button variant="text-primary" onClick={() => handleClick()}>All Sessions</Button>
{hasFilters && <Button type="text" onClick={clearFilters}>Clear Filters</Button>}
<Button type="text" onClick={() => handleClick()}>All Sessions</Button>
</div>
</div>

View file

@ -2,7 +2,8 @@ import { useModal } from 'App/components/Modal';
import { observer } from 'mobx-react-lite';
import React, { useEffect, useState } from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
import { Loader, Pagination, Button } from 'UI';
import { Loader, Pagination } from 'UI';
import { Button } from 'antd'
import SessionsModal from './SessionsModal';
import CardUserItem from './CardUserItem';
import { useStore } from 'App/mstore';
@ -45,7 +46,7 @@ function CardUserList(props: RouteComponentProps<Props>) {
<div className="flex justify-between">
<h1 className="font-medium text-2xl">Returning users between</h1>
<div>
<Button variant="text-primary">All Sessions</Button>
<Button type="text">All Sessions</Button>
</div>
</div>

View file

@ -2,7 +2,7 @@ import React from 'react';
import { useObserver } from 'mobx-react-lite';
import DashboardMetricSelection from '../DashboardMetricSelection';
import DashboardForm from '../DashboardForm';
import { Button } from 'UI';
import { Button } from 'antd';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { useStore } from 'App/mstore';
import { useModal } from 'App/components/Modal';
@ -67,7 +67,7 @@ function DashboardModal(props: Props) {
<div className="flex items-center absolute bottom-0 left-0 right-0 bg-white border-t p-3">
<Button
variant="primary"
type="primary"
disabled={!dashboard.isValid || loading}
onClick={onSave}
className="flaot-left mr-2"

View file

@ -1,83 +0,0 @@
import {useObserver} from 'mobx-react-lite';
import React from 'react';
import {Button, Modal, Form, Icon} from 'UI';
import {useStore} from 'App/mstore'
import Select from 'Shared/Select';
interface Props {
metricId: string,
show: boolean;
closeHandler?: () => void;
}
function DashboardSelectionModal(props: Props) {
const {show, metricId, closeHandler} = props;
const {dashboardStore} = useStore();
const dashboardOptions = dashboardStore.dashboards.map((i: any) => ({
key: i.id,
label: i.name,
value: i.dashboardId,
}));
const [selectedId, setSelectedId] = React.useState(dashboardOptions[0].value);
const onSave = () => {
const dashboard = dashboardStore.getDashboard(selectedId)
if (dashboard) {
dashboardStore.addWidgetToDashboard(dashboard, [metricId]).then(closeHandler)
}
}
React.useEffect(() => {
const handleEsc = (e: KeyboardEvent) => {
if (e.key === 'Escape' || e.key === 'Esc') {
closeHandler();
}
}
document.addEventListener('keydown', handleEsc, false);
return () => {
document.removeEventListener('keydown', handleEsc, false);
}
}, [])
return useObserver(() => (
<Modal size="small" open={show} onClose={closeHandler}>
<Modal.Header className="flex items-center justify-between">
<div className='text-xl font-medium'>{'Add to selected dashboard'}</div>
<Icon
role="button"
tabIndex="-1"
color="gray-dark"
size="14"
name="close"
onClick={closeHandler}
/>
</Modal.Header>
<Modal.Content>
<Form.Field>
<label className="mb-2">{'Dashbaord:'}</label>
<Select
options={dashboardOptions}
defaultValue={dashboardOptions[0].value}
onChange={({value}: any) => setSelectedId(value.value)}
/>
</Form.Field>
</Modal.Content>
<Modal.Footer>
<Button
variant="primary"
onClick={onSave}
className="float-left mr-2 "
>
Add
</Button>
<Button className="mr-2" onClick={closeHandler}>{'Cancel'}</Button>
</Modal.Footer>
</Modal>
));
}
export default DashboardSelectionModal;

View file

@ -1,6 +1,7 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { Button, Loader } from 'UI';
import { Loader } from 'UI';
import { Button } from 'antd'
import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper';
import { useStore } from 'App/mstore';
import { useModal } from 'App/components/Modal';
@ -63,7 +64,7 @@ function AddMetric({ history, siteId, title, description }: IProps) {
<div className="text-disabled-text">{description}</div>
</div>
<Button variant="text-primary" className="font-medium ml-2" onClick={onCreateNew}>
<Button variant="text" className="text-main font-medium ml-2" onClick={onCreateNew}>
+ Create New
</Button>
</div>
@ -100,7 +101,7 @@ function AddMetric({ history, siteId, title, description }: IProps) {
{' out of '}
<span className="font-medium">{metrics ? metrics.length : 0}</span>
</div>
<Button variant="primary" disabled={selectedWidgetIds.length === 0} onClick={onSave}>
<Button type="primary" disabled={selectedWidgetIds.length === 0} onClick={onSave}>
Add Selected
</Button>
</div>

View file

@ -1,6 +1,7 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { Button, Loader } from 'UI';
import { Loader } from 'UI';
import { Button } from 'antd'
import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper';
import { useStore } from 'App/mstore';
import { useModal } from 'App/components/Modal';
@ -79,7 +80,7 @@ function AddPredefinedMetric({ history, siteId, title, description }: IProps) {
</div>
<div className="flex flex-col items-end">
<Button variant="text-primary" className="font-medium ml-2" onClick={onCreateNew}>
<Button type="text" className="text-main font-medium ml-2" onClick={onCreateNew}>
+ Create Custom Metric
</Button>
<div className="text-disabled-text">Past 7 Days</div>
@ -145,7 +146,7 @@ function AddPredefinedMetric({ history, siteId, title, description }: IProps) {
{' out of '}
<span className="font-medium">{totalMetricCount}</span>
</div>
<Button variant="primary" disabled={selectedWidgetIds.length === 0} onClick={onSave}>
<Button type="primary" disabled={selectedWidgetIds.length === 0} onClick={onSave}>
Add Selected
</Button>
</div>

View file

@ -2,7 +2,7 @@ import { useModal } from 'App/components/Modal';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import React, { useMemo } from 'react';
import { Button } from 'UI';
import { Button } from 'antd';
function FooterContent({ dashboardId, selected }: any) {
const { hideModal } = useModal();
@ -27,10 +27,10 @@ function FooterContent({ dashboardId, selected }: any) {
<span className="font-medium">{total}</span>
</div>
<div className="flex items-center">
<Button variant="text-primary" className="mr-2" onClick={hideModal}>
<Button type="text" className="mr-2" onClick={hideModal}>
Cancel
</Button>
<Button disabled={selected.length === 0} variant="primary" onClick={addSelectedToDashboard}>
<Button disabled={selected.length === 0} type="primary" onClick={addSelectedToDashboard}>
Add Selected to Dashboard
</Button>
</div>

View file

@ -1,15 +1,13 @@
import React, {useEffect, useState} from 'react';
import {metricOf, issueOptions, issueCategories} from 'App/constants/filterOptions';
import { metricOf } from 'App/constants/filterOptions';
import {FilterKey} from 'Types/filter/filterType';
import {useStore} from 'App/mstore';
import {observer} from 'mobx-react-lite';
import {Button, Icon, confirm, Tooltip} from 'UI';
import {Input, Alert} from 'antd'
import { Icon, confirm, Tooltip } from 'UI';
import { Input, Alert, Button } from 'antd'
import FilterSeries from '../FilterSeries';
import Select from 'Shared/Select';
import {withSiteId, dashboardMetricDetails, metricDetails} from 'App/routes';
import MetricTypeDropdown from './components/MetricTypeDropdown';
import MetricSubtypeDropdown from './components/MetricSubtypeDropdown';
import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes';
import {
TIMESERIES,
TABLE,
@ -285,8 +283,8 @@ function WidgetForm(props: Props) {
{`${isTable || isFunnel || isClickmap || isInsights || isPathAnalysis || isRetention ? 'Filter by' : 'Chart Series'}`}
{!isTable && !isFunnel && !isClickmap && !isInsights && !isPathAnalysis && !isRetention && (
<Button
className='ml-2'
variant='text-primary'
className='ml-2 text-main'
type='text'
onClick={() => metric.addSeries()}
disabled={!canAddSeries}
>
@ -327,7 +325,7 @@ function WidgetForm(props: Props) {
disabled={!cannotSaveFunnel}
>
<div className='flex items-center'>
<Button variant='primary' onClick={onSave} disabled={isSaving || cannotSaveFunnel}>
<Button type='primary' onClick={onSave} disabled={isSaving || cannotSaveFunnel}>
{metric.exists()
? 'Update'
: parseInt(dashboardId) > 0
@ -335,7 +333,7 @@ function WidgetForm(props: Props) {
: 'Create'}
</Button>
{metric.exists() && metric.hasChanged && (
<Button onClick={undoChanges} variant='text' icon='arrow-counterclockwise' className='ml-2'>
<Button onClick={undoChanges} type='text' icon={<Icon name={'arrow-counterclockwise'} />} className='ml-2'>
Undo
</Button>
)}
@ -343,8 +341,7 @@ function WidgetForm(props: Props) {
</Tooltip>
<div className='flex items-center'>
{metric.exists() && (
<Button variant='text-primary' onClick={onDelete}>
<Icon name='trash' size='14' className='mr-2' color='teal'/>
<Button type='text' className={'text-main'} icon={<Icon name='trash' size='14' className='mr-2' color='teal'/>} onClick={onDelete}>
Delete
</Button>
)}

View file

@ -11,7 +11,8 @@ import { sessions as sessionsRoute } from 'App/routes';
import Divider from 'Components/Errors/ui/Divider';
import ErrorName from 'Components/Errors/ui/ErrorName';
import Label from 'Components/Errors/ui/Label';
import { Button, ErrorDetails, Icon, Loader } from 'UI';
import { ErrorDetails, Icon, Loader } from 'UI';
import { Button } from 'antd'
import SessionBar from './SessionBar';
@ -81,11 +82,12 @@ function MainSection(props) {
</span>
<Button
className="ml-auto"
variant="text-primary"
variant="text"
onClick={findSessions}
icon={<Icon className="ml-1" name="next1" color="teal" />}
iconPosition={'end'}
>
Find all sessions with this error
<Icon className="ml-1" name="next1" color="teal" />
</Button>
</div>
<SessionBar className="my-4" session={error.lastHydratedSession} />

View file

@ -1,11 +1,12 @@
import React from 'react';
import FeatureFlag from 'App/mstore/types/FeatureFlag';
import { Icon, Toggler, Link, TextEllipsis, Tooltip } from 'UI';
import { Icon, Link, TextEllipsis, Tooltip } from 'UI';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { resentOrDate } from 'App/date';
import { toast } from 'react-toastify';
import { fflagRead } from "App/routes";
import { Switch } from 'antd';
function FFlagItem({ flag }: { flag: FeatureFlag }) {
const { featureFlagsStore, userStore } = useStore();
@ -35,7 +36,10 @@ function FFlagItem({ flag }: { flag: FeatureFlag }) {
<div className={'flex items-center'}>
<Link style={{ flex: 1 }} to={fflagRead(flag.featureFlagId.toString())}>
<div className={'flex items-center gap-2'}>
<Tooltip delay={150} title={flag.isSingleOption ? 'Single variant' : 'Multivariant'}>
<Tooltip
delay={150}
title={flag.isSingleOption ? 'Single variant' : 'Multivariant'}
>
<Icon name={flagIcon} size={32} />
</Tooltip>
<div className="flex flex-col gap-1" style={{ width: 300 }}>
@ -50,18 +54,27 @@ function FFlagItem({ flag }: { flag: FeatureFlag }) {
</div>
</div>
</Link>
<div style={{ flex: 1 }}>{resentOrDate(flag.updatedAt || flag.createdAt)}</div>
<div style={{ flex: 1 }} className={'flex items-center gap-2 capitalize'}>
<div style={{ flex: 1 }}>
{resentOrDate(flag.updatedAt || flag.createdAt)}
</div>
<div
style={{ flex: 1 }}
className={'flex items-center gap-2 capitalize'}
>
<Icon name={'person-fill'} />
{user}
</div>
<div style={{ marginLeft: 'auto', width: 115 }}>
<Toggler
checked={flag.isActive}
name={'persist-flag'}
label={flag.isActive ? 'Enabled' : 'Disabled'}
onChange={toggleActivity}
/>
<div
style={{
marginLeft: 'auto',
width: 115,
display: 'flex',
alignItems: 'center',
gap: '0.25rem',
}}
>
<Switch checked={flag.isActive} onChange={toggleActivity} />
<div>{flag.isActive ? 'Enabled' : 'Disabled'}</div>
</div>
</div>
</div>

View file

@ -1,5 +1,6 @@
import React from 'react'
import { Button, PageTitle } from 'UI'
import { PageTitle } from 'UI'
import { Button } from 'antd'
import FFlagsSearch from "Components/FFlags/FFlagsSearch";
import { useHistory } from "react-router";
import { newFFlag, withSiteId } from 'App/routes';
@ -13,7 +14,7 @@ function FFlagsListHeader({ siteId }: { siteId: string }) {
<PageTitle title="Feature Flags" />
</div>
<div className="ml-auto flex items-center">
<Button variant="primary" onClick={() => history.push(withSiteId(newFFlag(), siteId))}>
<Button type="primary" onClick={() => history.push(withSiteId(newFFlag(), siteId))}>
Create Feature Flag
</Button>
<div className="mx-2"></div>

View file

@ -1,7 +1,8 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import { Toggler, Loader, Button, NoContent, ItemMenu } from 'UI';
import { Loader, NoContent, ItemMenu } from 'UI';
import { Button, Switch } from 'antd'
import Breadcrumb from 'Shared/Breadcrumb';
import { useHistory } from 'react-router';
import { withSiteId, fflag, fflags } from 'App/routes';
@ -59,11 +60,16 @@ function FlagView({ siteId, fflagId }: { siteId: string; fflagId: string }) {
<div className={'flex items-center gap-2'}>
<div className={'text-2xl'}>{current.flagKey}</div>
<Button
className={'ml-auto'}
variant={'text-primary'}
className={'ml-auto text-main'}
type={'text'}
onClick={() =>
history.push(
withSiteId(fflag(featureFlagsStore.currentFflag?.featureFlagId.toString()), siteId)
withSiteId(
fflag(
featureFlagsStore.currentFflag?.featureFlagId.toString()
),
siteId
)
)
}
>
@ -72,17 +78,16 @@ function FlagView({ siteId, fflagId }: { siteId: string; fflagId: string }) {
<ItemMenu bold items={menuItems} />
</div>
<div className={'border-b'} style={{ color: 'rgba(0,0,0, 0.6)' }}>
{current.description || 'There is no description for this feature flag.'}
{current.description ||
'There is no description for this feature flag.'}
</div>
<div className={'mt-4'}>
<label className={'font-semibold'}>Status</label>
<Toggler
checked={current.isActive}
name={'persist-flag'}
onChange={toggleActivity}
label={current.isActive ? 'Enabled' : 'Disabled'}
/>
<div className={'flex items-center gap-2'}>
<Switch checked={current.isActive} onChange={toggleActivity} />
<div>{current.isActive ? 'Enabled' : 'Disabled'}</div>
</div>
</div>
<div className={'mt-4'}>
<label className={'font-semibold'}>Persistence</label>
@ -92,28 +97,25 @@ function FlagView({ siteId, fflagId }: { siteId: string; fflagId: string }) {
: 'This flag is not persistent across authentication events.'}
</div>
</div>
{!current.isSingleOption ? (
<Multivariant readonly />
{!current.isSingleOption ? <Multivariant readonly /> : null}
{current.conditions.length > 0 ? (
<div className="mt-6 p-4 rounded bg-gray-lightest">
<label className={'font-semibold'}>Rollout Conditions</label>
{current.conditions.map((condition, index) => (
<React.Fragment key={index}>
<RolloutCondition
set={index + 1}
readonly
index={index}
conditions={condition}
removeCondition={current.removeCondition}
/>
<div className={'mt-2'} />
</React.Fragment>
))}
</div>
) : null}
{current.conditions.length > 0 ? (
<div className="mt-6 p-4 rounded bg-gray-lightest">
<label className={'font-semibold'}>Rollout Conditions</label>
{current.conditions.map((condition, index) => (
<React.Fragment key={index}>
<RolloutCondition
set={index + 1}
readonly
index={index}
conditions={condition}
removeCondition={current.removeCondition}
/>
<div className={'mt-2'} />
</React.Fragment>
))}
</div>
) : null}
</div>
</div>
);
}

View file

@ -1,6 +1,7 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { Button } from 'UI';
import { Icon } from 'UI';
import { Button } from 'antd';
import cn from 'classnames';
import FeatureFlag from 'App/mstore/types/FeatureFlag';
@ -46,8 +47,8 @@ function Description({
</div>
) : (
<Button
variant={'text-primary'}
icon={'edit'}
type={'text'}
icon={<Icon name={'edit'} size={16} />}
onClick={() => setEditing({ isDescrEditing: true })}
>
Add

View file

@ -1,5 +1,4 @@
import React from 'react';
import { Button } from 'UI';
import { observer } from 'mobx-react-lite';
import cn from 'classnames';
import { ItemMenu } from 'UI';
@ -7,6 +6,7 @@ import { useStore } from 'App/mstore';
import { useHistory } from 'react-router';
import { toast } from 'react-toastify';
import { fflags, withSiteId } from "App/routes";
import { Button } from 'antd';
function Header({ current, onCancel, onSave, isNew, siteId }: any) {
const { featureFlagsStore } = useStore();
@ -29,10 +29,10 @@ function Header({ current, onCancel, onSave, isNew, siteId }: any) {
</div>
<div className={'flex items-center gap-2'}>
<Button variant="text-primary" onClick={onCancel}>
<Button type="text" onClick={onCancel}>
Cancel
</Button>
<Button variant="primary" onClick={onSave}>
<Button type="primary" onClick={onSave}>
Save
</Button>
{!isNew ? <ItemMenu bold items={menuItems} /> : null}

View file

@ -1,6 +1,7 @@
import React from 'react';
import { Rollout, Payload } from './Helpers';
import { Input, Button, Icon } from 'UI';
import { Input, Icon } from 'UI';
import { Button } from 'antd'
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import cn from 'classnames';
@ -164,7 +165,7 @@ function Multivariant({ readonly }: { readonly?: boolean }) {
{readonly ? null : (
<div className={'mt-2 flex justify-between w-full'}>
{featureFlagsStore.currentFflag!.variants.length < 10 ? (
<Button variant={'text-primary'} onClick={featureFlagsStore.currentFflag!.addVariant}>
<Button type={'text'} onClick={featureFlagsStore.currentFflag!.addVariant}>
+ Add Variant
</Button>
) : null}

View file

@ -1,8 +1,9 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import { Input, SegmentSelection, Toggler, Loader, Button, NoContent } from 'UI';
import { Input, SegmentSelection, Loader, NoContent } from 'UI';
import Breadcrumb from 'Shared/Breadcrumb';
import { Button, Switch } from 'antd'
import { useModal } from 'App/components/Modal';
import HowTo from 'Components/FFlags/NewFFlag/HowTo';
import {Prompt, useHistory} from 'react-router';
@ -92,7 +93,13 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
/>
<div className={'w-full bg-white rounded p-4 widget-wrapper'}>
<div className="flex justify-between items-center">
<Header siteId={siteId} current={current} onCancel={onCancel} onSave={onSave} isNew={!fflagId} />
<Header
siteId={siteId}
current={current}
onCancel={onCancel}
onSave={onSave}
isNew={!fflagId}
/>
</div>
<div className={'w-full border-b border-light-gray my-2'} />
@ -106,7 +113,9 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
current.setFlagKey(e.target.value.replace(/\s/g, '-'));
}}
/>
<div className={'text-sm text-disabled-text mt-1 flex items-center gap-1'}>
<div
className={'text-sm text-disabled-text mt-1 flex items-center gap-1'}
>
Feature flag keys must be unique.
<div className={'link'} onClick={onImplementClick}>
Learn how to implement feature flags
@ -142,10 +151,16 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
</div>
{current.isSingleOption ? (
<>
<div className={'text-sm text-disabled-text mt-1 flex items-center gap-1'}>
<div
className={
'text-sm text-disabled-text mt-1 flex items-center gap-1'
}
>
Users will be served
<code className={'p-1 text-red rounded bg-gray-lightest'}>true</code> if they match
one or more rollout conditions.
<code className={'p-1 text-red rounded bg-gray-lightest'}>
true
</code>{' '}
if they match one or more rollout conditions.
</div>
<div className={'mt-6'}>
<Payload />
@ -156,7 +171,6 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
}}
placeholder={"E.g. red button, {'buttonColor': 'red'}"}
className={'mt-2'}
/>
</div>
</>
@ -166,50 +180,65 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
</div>
<div className={'mt-6'}>
<label className={'font-semibold'}>Persist flag across authentication</label>
<Toggler
checked={current.isPersist}
name={'persist-flag'}
onChange={() => {
current.setIsPersist(!current.isPersist);
}}
label={current.isPersist ? 'Yes' : 'No'}
/>
<label className={'font-semibold'}>
Persist flag across authentication
</label>
<div className="flex items-center gap-2">
<Switch
checked={current.isPersist}
onChange={() => {
current.setIsPersist(!current.isPersist);
}}
/>
<div>{current.isPersist ? 'Yes' : 'No'}</div>
</div>
<div className={'text-sm text-disabled-text flex items-center gap-1'}>
Persist flag to not reset this feature flag status after a user is identified.
Persist flag to not reset this feature flag status after a user is
identified.
</div>
</div>
<div className={'mt-6'}>
<label className={'font-semibold'}>Enable this feature flag (Status)?</label>
<Toggler
checked={current.isActive}
name={'persist-flag'}
onChange={() => {
!fflagId && !current.isActive ? toast.success("Feature flag will be enabled upon saving it.") : ""
current.setIsEnabled(!current.isActive);
}}
label={current.isActive ? 'Enabled' : 'Disabled'}
/>
<label className={'font-semibold'}>
Enable this feature flag (Status)?
</label>
<div className="flex items-center gap-2">
<Switch
checked={current.isActive}
onChange={() => {
!fflagId && !current.isActive
? toast.success(
'Feature flag will be enabled upon saving it.'
)
: '';
current.setIsEnabled(!current.isActive);
}}
/>
<div>{current.isActive ? 'Enabled' : 'Disabled'}</div>
</div>
</div>
<div className={'mt-6 p-4 rounded bg-gray-lightest'}>
<label className={'font-semibold'}>Rollout Conditions</label>
{current.conditions.length === 0 ? null : (
<div className={'text-sm text-disabled-text mb-2'}>
Indicate the users for whom you intend to make this flag available. Keep in mind that
each set of conditions will be deployed separately from one another.
Indicate the users for whom you intend to make this flag
available. Keep in mind that each set of conditions will be
deployed separately from one another.
</div>
)}
<NoContent
show={current.conditions.length === 0}
title={'The flag will be available for 100% of the user sessions.'}
subtext={
<div className={'flex flex-col items-center'} style={{ fontSize: 14 }}>
<div
className={'flex flex-col items-center'}
style={{ fontSize: 14 }}
>
<div className={'text-sm mb-1'}>
Set up condition sets to restrict the rollout.
</div>
<Button onClick={() => current!.addCondition()} variant={'text-primary'}>
<Button onClick={() => current!.addCondition()} type={'text'}>
+ Create Condition Set
</Button>
</div>
@ -237,7 +266,7 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
'flex items-center justify-center w-full bg-white rounded border mt-2 p-2'
}
>
<Button variant={'text-primary'}>+ Create Condition Set</Button>
<Button type={'text'}>+ Create Condition Set</Button>
</div>
) : null}
</>

View file

@ -2,7 +2,8 @@ import React, { useEffect } from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import ReCAPTCHA from 'react-google-recaptcha';
import { Form, Input, Loader, Button, Icon, Message } from 'UI';
import { Form, Input, Loader, Icon, Message } from 'UI';
import { Button } from 'antd'
import stl from './forgotPassword.module.css';
import { validatePassword } from 'App/validate';
import { PASSWORD_POLICY } from 'App/constants';
@ -112,7 +113,10 @@ function CreatePassword(props: Props) {
</div>
</Loader>
<div className="mt-4">
<div data-hidden={!updated} className="flex items-center flex-col text-center">
<div
data-hidden={!updated}
className="flex items-center flex-col text-center"
>
<div className="w-10 h-10 bg-tealx-lightest rounded-full flex items-center justify-center mb-3">
<Icon name="check" size="30" color="tealx" />
</div>
@ -122,9 +126,16 @@ function CreatePassword(props: Props) {
{validationError && <Message error>{validationError}</Message>}
<Button type="submit" data-hidden={updated} variant="primary" loading={loading} className="w-full mt-4">
Create
</Button>
{updated ? null :
<Button
htmlType="submit"
type="primary"
loading={loading}
className="w-full mt-4"
>
Create
</Button>
}
</>
)}

View file

@ -1,15 +0,0 @@
import React from 'react';
import { withRouter } from 'react-router-dom';
interface Props {
}
function FunnelDetails(props: Props) {
return (
<div>
Create View/Detail View
</div>
);
}
export default withRouter(FunnelDetails);

View file

@ -1 +0,0 @@
export { default } from './FunnelDetails'

View file

@ -1 +0,0 @@
//export { default } from './FunnelIssueDetails'

View file

@ -1,61 +0,0 @@
import { PageTitle, Button, Pagination, Icon, Loader } from 'UI';
import { useStore } from 'App/mstore';
import { useObserver } from 'mobx-react-lite';
import React, { useEffect } from 'react';
import { sliceListPerPage } from 'App/utils';
import FunnelItem from '../FunnelItem/FunnelItem';
import FunnelSearch from '../FunnelSearch';
function FunnelList(props) {
const { funnelStore } = useStore()
const list = useObserver(() => funnelStore.list)
const loading = useObserver(() => funnelStore.isLoading)
useEffect(() => {
if (list.length === 0) {
funnelStore.fetchFunnels()
}
}, [])
return (
<Loader loading={loading}>
<div className="flex items-center">
<div className="flex items-center">
<PageTitle title='Funnels' className="mr-3" />
<Button primary size="small" onClick={() => {}}>New Funnel</Button>
</div>
<div className="ml-auto w-1/4">
<FunnelSearch />
</div>
</div>
<div className="color-gray-medium mt-2 mb-4">Funnels make it easy to uncover the most significant issues that impacted conversions.</div>
<div className="mt-3 border rounded bg-white">
<div className="grid grid-cols-12 p-3 font-medium">
<div className="col-span-4 flex items-center">
<Icon name="funnel-fill"/> <span className="ml-2">Title</span>
</div>
<div className="col-span-3">Owner</div>
<div className="col-span-3">Last Modified</div>
</div>
{sliceListPerPage(list, funnelStore.page - 1, funnelStore.pageSize).map((funnel: any) => (
<FunnelItem funnel={funnel} />
))}
</div>
<div className="w-full flex items-center justify-center py-8">
<Pagination
page={funnelStore.page}
total={list.length}
onPageChange={(page) => funnelStore.updateKey('page', page)}
limit={funnelStore.pageSize}
debounceRequest={100}
/>
</div>
</Loader>
);
}
export default FunnelList;

View file

@ -1 +0,0 @@
export { default } from './FunnelList';

View file

@ -1,26 +0,0 @@
import React from 'react';
import { Switch, Route } from 'react-router';
import FunnelDetails from '../FunnelDetails/FunnelDetails';
import FunnelList from '../FunnelList';
function FunnelPage(props) {
return (
<div className="page-margin container-70">
<Switch>
<Route path="/">
<FunnelList />
</Route>
<Route path="/funnel/create">
<FunnelDetails />
</Route>
{/* <Route path="/funnel/:id">
<FunnelDetail />
</Route> */}
</Switch>
</div>
);
}
export default FunnelPage;

View file

@ -1 +0,0 @@
export { default } from './FunnelPage';

View file

@ -1,7 +1,8 @@
import React from 'react';
// @ts-ignore
import slide from 'App/svg/cheers.svg';
import { Button, Loader } from 'UI';
import { Loader } from 'UI';
import { Button } from 'antd'
import Footer from './Footer';
import { getHighest } from 'App/constants/zindex';
import Category from 'Components/Header/HealthStatus/ServiceCategory';
@ -81,7 +82,8 @@ function HealthModal({
disabled={isLoading}
onClick={getHealth}
icon={'arrow-repeat'}
variant={'text-primary'}
type={'text'}
className={'text-main'}
>
Recheck
</Button>
@ -132,7 +134,7 @@ function HealthModal({
<Button
disabled={!healthResponse?.overallHealth}
loading={isLoading}
variant={'primary'}
type={'primary'}
className={'ml-auto'}
onClick={() => setPassed?.()}
>

View file

@ -2,12 +2,12 @@ import { Segmented } from 'antd';
import React from 'react';
import CircleNumber from '../CircleNumber';
import MetadataList from '../MetadataList/MetadataList';
import { HighlightCode, Icon, Button } from 'UI';
import { HighlightCode, Icon } from 'UI';
import DocCard from 'Shared/DocCard/DocCard';
import withOnboarding, { WithOnboardingProps } from '../withOnboarding';
import { OB_TABS } from 'App/routes';
import withPageTitle from 'App/components/hocs/withPageTitle';
import { Button as AntButton } from 'antd'
import { Button } from 'antd'
interface Props extends WithOnboardingProps {
platforms: Array<{
@ -42,10 +42,10 @@ function IdentifyUsersTab(props: Props) {
href={`https://docs.openreplay.com/en/installation/identify-user${platform.value === "web" ? "/#with-npm" : "/#with-ios-app"}`}
target="_blank"
>
<AntButton size={'small'} type={'text'} className="ml-2 flex items-center gap-2">
<Button size={'small'} type={'text'} className="ml-2 flex items-center gap-2">
<Icon name={'question-circle'} />
<div className={'text-main'}>See Documentation</div>
</AntButton>
</Button>
</a>
</h1>
<div className="p-4 flex gap-2 items-center">
@ -142,11 +142,11 @@ function IdentifyUsersTab(props: Props) {
</div>
<div className="border-t px-4 py-3 flex justify-end gap-4">
<Button variant="text-primary" onClick={() => (props.skip ? props.skip() : null)}>
<Button type="text" onClick={() => (props.skip ? props.skip() : null)}>
Skip
</Button>
<Button
variant="primary"
type="primary"
className=""
onClick={() => (props.navTo ? props.navTo(OB_TABS.MANAGE_USERS) : null)}
>

View file

@ -2,13 +2,13 @@ import React from 'react';
import OnboardingTabs from '../OnboardingTabs';
import MobileOnboardingTabs from '../OnboardingTabs/OnboardingMobileTabs';
import ProjectFormButton from '../ProjectFormButton';
import { Button, Icon } from 'UI';
import { Icon } from 'UI';
import withOnboarding from '../withOnboarding';
import { WithOnboardingProps } from '../withOnboarding';
import { OB_TABS } from 'App/routes';
import withPageTitle from 'App/components/hocs/withPageTitle';
import { Segmented } from 'antd';
import { Button as AntButton } from 'antd'
import { Button } from 'antd'
interface Props extends WithOnboardingProps {
platforms: Array<{
@ -41,10 +41,10 @@ function InstallOpenReplayTab(props: Props) {
</div>
</div>
<a href={"https://docs.openreplay.com/en/using-or/"} target="_blank">
<AntButton size={"small"} type={"text"} className="ml-2 flex items-center gap-2">
<Button size={"small"} type={"text"} className="ml-2 flex items-center gap-2">
<Icon name={"question-circle"} />
<div className={"text-main"}>See Documentation</div>
</AntButton>
</Button>
</a>
</h1>
<div className="p-4 flex gap-2 items-center">
@ -62,7 +62,7 @@ function InstallOpenReplayTab(props: Props) {
</div>
<div className="border-t px-4 py-3 flex justify-end">
<Button
variant="primary"
type="primary"
className=""
onClick={() => (props.navTo ? props.navTo(OB_TABS.IDENTIFY_USERS) : null)}
>

View file

@ -1,9 +1,8 @@
import { Button as AntButton } from 'antd';
import React from 'react';
import { Icon } from 'UI';
import { Button } from 'antd';
import Integrations from 'App/components/Client/Integrations/Integrations';
import withPageTitle from 'App/components/hocs/withPageTitle';
import { Button, Icon } from 'UI';
import withOnboarding, { WithOnboardingProps } from '../withOnboarding';
@ -21,21 +20,20 @@ function IntegrationsTab(props: Props) {
href="https://docs.openreplay.com/en/integrations/"
target="_blank"
>
<AntButton
<Button
size={'small'}
type={'text'}
className="ml-2 flex items-center gap-2"
icon={<Icon name={'question-circle'} />}
>
<Icon name={'question-circle'} />
<div className={'text-main'}>See Documentation</div>
</AntButton>
</Button>
</a>
</h1>
<Integrations hideHeader={true} />
<div className="border-t px-4 py-3 flex justify-end">
<Button
variant="primary"
className=""
type="primary"
onClick={() => (props.skip ? props.skip() : null)}
>
Complete Setup

View file

@ -1,11 +1,11 @@
import UsersView from 'App/components/Client/Users/UsersView';
import DocCard from 'Shared/DocCard/DocCard';
import React from 'react';
import { Button, Icon } from 'UI';
import { Icon } from 'UI';
import withOnboarding, { WithOnboardingProps } from '../withOnboarding';
import { OB_TABS } from 'App/routes';
import withPageTitle from 'App/components/hocs/withPageTitle';
import { Button as AntButton } from 'antd'
import { Button } from 'antd'
interface Props extends WithOnboardingProps {}
@ -22,10 +22,10 @@ function ManageUsersTab(props: Props) {
href="https://docs.openreplay.com/en/tutorials/adding-users/"
target="_blank"
>
<AntButton size={'small'} type={'text'} className="ml-2 flex items-center gap-2">
<Button size={'small'} type={'text'} className="ml-2 flex items-center gap-2">
<Icon name={'question-circle'} />
<div className={'text-main'}>See Documentation</div>
</AntButton>
</Button>
</a>
</h1>
<div className="grid grid-cols-6 gap-4 p-4">
@ -48,16 +48,16 @@ function ManageUsersTab(props: Props) {
</div>
</div>
<div className="border-t px-4 py-3 flex justify-end">
<Button variant="text-primary" onClick={() => (props.skip ? props.skip() : null)}>
<Button type="text" onClick={() => (props.skip ? props.skip() : null)}>
Skip
</Button>
<Button
variant="primary"
className=""
type="primary"
onClick={() => (props.navTo ? props.navTo(OB_TABS.INTEGRATIONS) : null)}
icon={<Icon name="arrow-right-short" color="white" size={20} />}
iconPosition={'end'}
>
Configure Integrations
<Icon name="arrow-right-short" color="white" size={20} />
</Button>
</div>
</>

View file

@ -1,11 +1,11 @@
import React, { useEffect } from 'react';
import { Button, TagBadge } from 'UI';
import { TagBadge, confirm } from 'UI';
import CustomFieldForm from '../../../Client/CustomFields/CustomFieldForm';
import { confirm } from 'UI';
import { useModal } from 'App/components/Modal';
import { toast } from 'react-toastify';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { Button } from 'antd'
const MetadataList = () => {
const { customFieldStore, projectsStore } = useStore();
@ -47,7 +47,7 @@ const MetadataList = () => {
return (
<div className="py-2 flex">
<Button variant="outline" onClick={() => openModal()}>
<Button type="default" onClick={() => openModal()}>
Add Metadata
</Button>
<div className="flex ml-2">

View file

@ -1,6 +1,6 @@
import React from 'react'
import { withRouter } from 'react-router'
import { Button } from 'UI'
import { Button } from 'antd'
import { OB_TABS, onboarding as onboardingRoute, withSiteId } from 'App/routes'
import { sessions } from 'App/routes';
import { useStore } from 'App/mstore'
@ -36,7 +36,7 @@ const OnboardingNavButton = ({ match: { params: { activeTab, siteId } }, history
<div className="flex items-center">
<Button
size="small"
variant="outline"
type="outline"
onClick={onDone}
className="float-left mr-2"
>
@ -44,7 +44,7 @@ const OnboardingNavButton = ({ match: { params: { activeTab, siteId } }, history
</Button>
<Button
variant="primary"
type="primary"
onClick={setTab}
>
{BTN_MSGS[activeIndex]}

View file

@ -3,7 +3,7 @@ import stl from './installDocs.module.css';
import cn from 'classnames';
import CircleNumber from '../../CircleNumber';
import { CopyButton, CodeBlock } from 'UI';
import { Toggler } from 'UI';
import { Switch } from 'antd'
const installationCommand = 'npm i @openreplay/tracker';
const usageCode = `import Tracker from '@openreplay/tracker';
@ -57,11 +57,10 @@ function InstallDocs({ site }) {
<div className="mr-2" onClick={() => setIsSpa(!isSpa)}>
Server-Side-Rendered (SSR)?
</div>
<Toggler
<Switch
checked={!isSpa}
name="sessionsLive"
onChange={() => setIsSpa(!isSpa)}
// style={{ lineHeight: '23px' }}
/>
</div>

View file

@ -1,8 +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 GDPR from 'App/mstore/types/gdpr';
import { Checkbox, Loader } from 'UI';
import { Switch } from 'antd'
import cn from 'classnames';
import stl from './projectCodeSnippet.module.css';
import CircleNumber from '../../CircleNumber';
@ -119,13 +119,14 @@ const ProjectCodeSnippet = () => {
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 className={'flex items-center gap-2'}>
<Switch
checked={isAssistEnabled}
className="font-medium mr-2"
onChange={() => setAssistEnabled(!isAssistEnabled)}
/>
<span>Yes</span>
</div>
</div>
<div className={cn(stl.instructions, 'mt-8')}>

View file

@ -1,7 +1,7 @@
import React, {useEffect, useState} from 'react';
import cn from 'classnames';
import {observer} from 'mobx-react-lite';
import {Button} from 'UI';
import { Button } from 'antd'
import stl from './AutoplayTimer.module.css';
import clsOv from './overlay.module.css';
import AutoplayToggle from 'Shared/AutoplayToggle';
@ -11,7 +11,7 @@ function AutoplayTimer({history}: any) {
let timer: NodeJS.Timer;
const [cancelled, setCancelled] = useState(false);
const [counter, setCounter] = useState(5);
const {clipStore} = useStore();
const { clipStore } = useStore();
useEffect(() => {
if (counter > 0) {
@ -46,11 +46,11 @@ function AutoplayTimer({history}: any) {
<AutoplayToggle/>
</div>
<div className="flex items-center">
<Button variant="text-primary" onClick={cancel}>
<Button type="text" onClick={cancel}>
Cancel
</Button>
<div className="px-2"/>
<Button variant="outline" onClick={() => clipStore.next()}>Play Now</Button>
<Button type="default" onClick={() => clipStore.next()}>Play Now</Button>
</div>
</div>
</div>

View file

@ -1,5 +1,6 @@
import React, { ErrorInfo } from 'react'
import { Button } from 'UI'
import React, { ErrorInfo } from 'react';
import { Button } from 'antd';
import { Icon } from 'UI';
class PlayerErrorBoundary extends React.Component<any> {
state = { hasError: false, error: '' };
@ -10,21 +11,20 @@ class PlayerErrorBoundary extends React.Component<any> {
componentDidCatch(error: Error, info: ErrorInfo) {
this.setState({
hasError: true,
error: error + info.componentStack
})
error: error + info.componentStack,
});
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return (
<div className={"flex flex-col p-4 gap-4"}>
<div className={'flex flex-col p-4 gap-4'}>
<h4>Something went wrong during player rendering.</h4>
<p>{this.state.error}</p>
<Button
onClick={() => window.location.reload()}
icon={"spinner"}
variant={"primary"}
icon={<Icon name={'spinner'} size={16} />}
type={'primary'}
style={{ width: 'fit-content' }}
>
Reload
@ -37,4 +37,4 @@ class PlayerErrorBoundary extends React.Component<any> {
}
}
export default PlayerErrorBoundary
export default PlayerErrorBoundary;

View file

@ -2,7 +2,8 @@ import React from 'react';
import { List } from 'immutable';
import cn from 'classnames';
import { withRequest, withToggle } from 'HOCs';
import { Button, Icon, SlideModal, TextEllipsis } from 'UI';
import { Icon, SlideModal, TextEllipsis } from 'UI';
import { Button } from 'antd'
import stl from './metadataItem.module.css';
import SessionList from './SessionList';
@ -62,7 +63,7 @@ export default class extends React.PureComponent {
</div>
<Button
onClick={ this.switchOpen }
variant="text"
type="text"
className={ stl.searchButton }
id="metadata-item"
>

View file

@ -2,7 +2,8 @@ import React from 'react';
import { List } from 'immutable';
import cn from 'classnames';
import { withRequest, withToggle } from 'HOCs';
import { Button, Icon, SlideModal, TextEllipsis } from 'UI';
import { Icon, SlideModal, TextEllipsis } from 'UI';
import { Button } from 'antd'
import stl from './metadataItem.module.css';
import SessionList from './SessionList';
@ -62,7 +63,7 @@ export default class extends React.PureComponent {
</div>
<Button
onClick={ this.switchOpen }
variant="text"
type="text"
className={ stl.searchButton }
id="metadata-item"
>

View file

@ -1,12 +1,10 @@
import React from 'react';
import { List } from 'immutable';
import { countries } from 'App/constants';
import { useStore } from 'App/mstore';
import { browserIcon, osIcon, deviceTypeIcon } from 'App/iconNames';
import { formatTimeOrDate } from 'App/date';
import { Avatar, TextEllipsis, CountryFlag, Icon, Tooltip, Popover } from 'UI';
import cn from 'classnames';
import { withRequest } from 'HOCs';
import SessionInfoItem from '../../SessionInfoItem';
import { useModal } from 'App/components/Modal';
import UserSessionsModal from 'Shared/UserSessionsModal';

View file

@ -1,5 +1,6 @@
import React from 'react';
import { JSONTree, NoContent, Button, Tabs } from 'UI'
import { JSONTree, NoContent, Tabs } from 'UI'
import { Button } from 'antd'
import cn from 'classnames';
import stl from './fetchDetails.module.css';
import Headers from './components/Headers'
@ -158,10 +159,10 @@ export default class FetchDetails extends React.PureComponent {
</div>
<div className="flex justify-between absolute bottom-0 left-0 right-0 p-3 border-t bg-white">
<Button variant="outline" onClick={prevClick} disabled={first}>
<Button type="outline" onClick={prevClick} disabled={first}>
Prev
</Button>
<Button variant="outline" onClick={nextClick} disabled={last}>
<Button type="outline" onClick={nextClick} disabled={last}>
Next
</Button>
</div>

View file

@ -1,5 +1,5 @@
import React from 'react';
import { Loader, Pagination, Tooltip, Button } from 'UI';
import { Loader, Pagination, Tooltip, Icon } from 'UI';
import SessionItem from 'Shared/SessionItem';
import Select from 'Shared/Select';
import SortOrderButton from 'Shared/SortOrderButton';
@ -11,7 +11,7 @@ import AssistSearchActions from 'App/components/Assist/AssistSearchActions';
import LiveSessionSearch from 'Shared/LiveSessionSearch';
import cn from 'classnames';
import Session from 'App/mstore/types/session';
import { Button } from 'antd'
const PER_PAGE = 10;
interface ConnectProps {
@ -65,9 +65,9 @@ function AssistSessionsModal(props: ConnectProps) {
<Button
loading={loading}
className="mr-2"
variant="text"
type="text"
onClick={reloadSessions}
icon="arrow-repeat"
icon={<Icon name={"arrow-repeat"} />}
/>
</Tooltip>
<AssistSearchActions />

View file

@ -67,9 +67,10 @@ export function IntervalSelector({
distance={20}
render={({ close }: any) => (
<div
style={{ margin: -12 }}
className={cn(
'flex flex-col bg-white border',
'border-borderColor-gray-light-shade text-figmaColors-text-primary rounded'
'flex flex-col bg-white',
'text-figmaColors-text-primary rounded'
)}
>
<div className="font-semibold py-2 px-4 w-full text-left">
@ -84,8 +85,7 @@ export function IntervalSelector({
}}
className={cn(
'py-2 px-4 cursor-pointer w-full text-left font-semibold',
'hover:text-main hover:shadow-border-main border-t',
'border-borderColor-gray-light-shade'
'hover:bg-active-blue border-t border-borderColor-gray-light-shade'
)}
>
{interval}
@ -149,10 +149,11 @@ export function SpeedOptions({
theme="nopadding"
animation="none"
duration={0}
placement={'top'}
className="cursor-pointer select-none"
distance={20}
render={({ close }: any) => (
<div className="flex flex-col bg-white border border-borderColor-gray-light-shade text-figmaColors-text-primary rounded">
<div style={{ margin: -12 }} className="flex flex-col bg-white text-figmaColors-text-primary rounded">
<div className="font-semibold py-2 px-4 w-full text-left">Playback speed</div>
{Object.keys(SPEED_OPTIONS).map((index: any) => (
<div

View file

@ -1,332 +0,0 @@
import { Tag, Input } from 'antd';
import { Duration } from 'luxon';
import React from 'react';
import { toast } from 'react-toastify';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import {
Note,
TAGS,
WriteNote,
iTag,
tagProps,
} from 'App/services/NotesService';
import { Button, Checkbox, Icon } from 'UI';
import { shortDurationFromMs } from 'App/date';
import Select from 'Shared/Select';
interface Props {
time: number;
isEdit?: boolean;
editNote?: WriteNote;
hideModal: () => void;
}
function CreateNote({
time,
isEdit,
editNote,
hideModal,
}: Props) {
const { notesStore, integrationsStore, sessionStore } = useStore();
const sessionId = sessionStore.current.sessionId;
const updateNote = sessionStore.updateNote;
const slackChannels = integrationsStore.slack.list;
const fetchSlack = integrationsStore.slack.fetchIntegrations;
const teamsChannels = integrationsStore.msteams.list;
const fetchTeams = integrationsStore.msteams.fetchIntegrations;
const [text, setText] = React.useState('');
const [slackChannel, setSlackChannel] = React.useState('');
const [teamsChannel, setTeamsChannel] = React.useState('');
const [isPublic, setPublic] = React.useState(false);
const [tag, setTag] = React.useState<iTag>(TAGS[0]);
const [useTimestamp, setUseTs] = React.useState(true);
const [useSlack, setSlack] = React.useState(false);
const [useTeams, setTeams] = React.useState(false);
const inputRef = React.createRef<HTMLTextAreaElement>();
React.useEffect(() => {
if (isEdit && editNote) {
setTag(editNote.tag);
setText(editNote.message);
setPublic(editNote.isPublic);
if (editNote.timestamp > 0) {
setUseTs(true);
}
}
}, [isEdit]);
React.useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
fetchSlack();
fetchTeams();
}
}, []);
const duration = Duration.fromMillis(time || 0).toFormat('mm:ss');
const cleanUp = () => {
setText('');
setTag(TAGS[0]);
hideModal();
};
const onSubmit = () => {
if (text === '') return;
const note: WriteNote = {
message: text,
tag,
timestamp: useTimestamp
? Math.floor(isEdit && editNote ? editNote.timestamp : time)
: -1,
isPublic,
};
const onSuccess = (noteId: string) => {
if (slackChannel) {
notesStore.sendSlackNotification(noteId, slackChannel);
}
if (teamsChannel) {
notesStore.sendMsTeamsNotification(noteId, teamsChannel);
}
};
if (isEdit && editNote) {
return notesStore
.updateNote(editNote.noteId!, note)
.then((r) => {
toast.success('Note updated');
notesStore.fetchSessionNotes(sessionId).then(() => {
onSuccess(editNote.noteId!);
updateNote(r as Note);
});
})
.catch((e) => {
toast.error('Error updating note');
console.error(e);
})
.finally(() => {
cleanUp();
});
} else {
return notesStore
.addNote(sessionId, note)
.then((r) => {
onSuccess(r!.noteId as unknown as string);
toast.success('Note added');
})
.catch((e) => {
toast.error('Error adding note');
console.error(e);
})
.finally(() => {
cleanUp();
});
}
};
const closeTooltip = () => {
hideModal();
};
const tagActive = (noteTag: iTag) => tag === noteTag;
const addTag = (tag: iTag) => {
setTag(tag);
};
const slackChannelsOptions = slackChannels
.map(({ webhookId, name }) => ({
value: webhookId,
label: name,
})) as unknown as { value: string; label: string }[];
const teamsChannelsOptions = teamsChannels
.map(({ webhookId, name }) => ({
value: webhookId,
label: name,
})) as unknown as { value: string; label: string }[];
slackChannelsOptions.unshift({
// @ts-ignore
value: null,
// @ts-ignore
label: <div className={'text-disabled-text'}>Pick a channel</div>,
disabled: true,
});
teamsChannelsOptions.unshift({
// @ts-ignore
value: null,
// @ts-ignore
label: <div className={'text-disabled-text'}>Pick a channel</div>,
disabled: true,
});
const changeSlackChannel = ({
value,
}: {
value: Record<string, string>;
name: string;
}) => {
if (value) {
setSlackChannel(value.value);
}
};
const changeTeamsChannel = ({
value,
}: {
value: Record<string, string>;
name: string;
}) => {
if (value) {
setTeamsChannel(value.value);
}
};
return (
<div
className={'bg-white h-screen w-full p-4 flex flex-col gap-4'}
onClick={(e) => e.stopPropagation()}
>
<div className="flex items-center">
<Icon name="quotes" size={20} />
<h3 className="text-xl ml-2 mr-4 font-semibold">
{isEdit ? 'Edit Note' : 'Add Note'}
</h3>
<div className="ml-auto cursor-pointer" onClick={closeTooltip}>
<Icon name="close" size={20} />
</div>
</div>
<div
className="flex items-center cursor-pointer gap-2"
onClick={() => setUseTs(!useTimestamp)}
>
<Checkbox checked={useTimestamp} />
<span>Add note at current time frame</span>
<div className={'border px-1 bg-gray-lightest rounded'}>{duration}</div>
</div>
<div className="">
<div className={'font-semibold'}>Note</div>
<Input.TextArea
ref={inputRef}
name="message"
id="message"
placeholder="Enter your note here..."
rows={3}
value={text}
autoFocus
onChange={(e) => {
setText(e.target.value);
}}
className="text-area"
/>
<div className={'flex w-full items-center gap-1 my-2'}>
{editNote && editNote?.startAt ? (
<>
<span>From: </span>
<Input disabled readOnly value={shortDurationFromMs(editNote?.startAt)} />
<span>To: </span>
<Input disabled readOnly value={shortDurationFromMs(editNote?.endAt)} />
</>
) : null}
</div>
<div className="flex items-center gap-1" style={{ lineHeight: '15px' }}>
{TAGS.map((tag) => (
<Tag
onClick={() => addTag(tag)}
key={tag}
className='cursor-pointer rounded-lg hover:bg-indigo-50'
color={tagActive(tag) ? tagProps[tag] : undefined}
bordered={false}
>
<div className={'flex items-center gap-2'}>
{tagActive(tag) ? (
<Icon name="check-circle-fill" color="inherit" size={13} />
) : null}
{tag}
</div>
</Tag>
))}
</div>
</div>
<div
className={'flex items-center gap-2 cursor-pointer'}
onClick={() => setPublic(!isPublic)}
>
<Checkbox checked={isPublic} />
<div>Visible to team members</div>
</div>
{slackChannelsOptions.length > 1 ? (
<div className="flex flex-col">
<div
className="flex items-center cursor-pointer"
onClick={() => setSlack(!useSlack)}
>
<Checkbox checked={useSlack} />
<span className="ml-1 mr-3"> Share via Slack </span>
</div>
{useSlack && (
<div>
<Select
options={slackChannelsOptions}
// @ts-ignore
defaultValue
// @ts-ignore
onChange={changeSlackChannel}
value={slackChannel}
/>
</div>
)}
</div>
) : null}
{teamsChannelsOptions.length > 1 ? (
<div className="flex flex-col">
<div
className="flex items-center cursor-pointer"
onClick={() => setTeams(!useTeams)}
>
<Checkbox checked={useTeams} />
<span className="ml-1 mr-3"> Share via MS Teams </span>
</div>
{useTeams && (
<div>
<Select
options={teamsChannelsOptions}
// @ts-ignore
defaultValue
// @ts-ignore
onChange={changeTeamsChannel}
value={teamsChannel}
/>
</div>
)}
</div>
) : null}
<div className="flex">
<Button
variant="primary"
className="mr-4"
disabled={text === ''}
onClick={onSubmit}
>
{isEdit
? 'Save Note'
: `Add Note ${useTeams || useSlack ? '& Share' : ''}`}
</Button>
<Button variant={'text'} onClick={closeTooltip}>
Cancel
</Button>
</div>
</div>
);
}
export default observer(CreateNote);

View file

@ -31,6 +31,7 @@ function PlayingTime({ timeMode, setTimeMode, startedAt, sessionTz }: Props) {
distance={20}
render={({ close }) => (
<div
style={{ margin: -12 }}
className={
'flex flex-col gap-2 bg-white py-2 rounded color-gray-darkest text-left'
}

View file

@ -17,7 +17,6 @@ import {
import { Icon } from 'UI';
import { useModal } from '../../Modal';
import CreateNote from './Controls/components/CreateNote';
import AutoplayTimer from './Overlay/AutoplayTimer';
import ElementsMarker from './Overlay/ElementsMarker';
import Loader from './Overlay/Loader';
@ -68,11 +67,11 @@ const menuItems: MenuProps['items'] = [
icon: <Icon name={'redux'} size={14} />,
},
{ type: 'divider' },
{
key: ItemKey.AddNote,
label: 'Add Note',
icon: <Icon name={'quotes'} size={14} />,
},
// {
// key: ItemKey.AddNote,
// label: 'Add Note',
// icon: <Icon name={'quotes'} size={14} />,
// },
{
key: ItemKey.CopySessionUrl,
label: 'Copy Session URL',
@ -131,16 +130,16 @@ function Overlay({ nextId, isClickmap }: Props) {
case ItemKey.State:
toggleBottomBlock(STORAGE);
break;
case ItemKey.AddNote:
showModal(
<CreateNote
hideModal={hideModal}
isEdit={false}
time={Math.round(store.get().time)}
/>,
{ right: true, width: 380 }
);
break;
// case ItemKey.AddNote:
// showModal(
// <CreateNote
// hideModal={hideModal}
// isEdit={false}
// time={Math.round(store.get().time)}
// />,
// { right: true, width: 380 }
// );
// break;
case ItemKey.CopySessionUrl:
copy(window.location.origin + window.location.pathname);
toast.success('Session URL copied to clipboard');

View file

@ -2,7 +2,8 @@ import React, { useEffect, useState } from 'react';
import cn from 'classnames';
import { observer } from 'mobx-react-lite';
import { withRouter } from 'react-router-dom';
import { Button, Link } from 'UI';
import { Link } from 'UI';
import { Button } from 'antd'
import { session as sessionRoute, withSiteId } from 'App/routes';
import stl from './AutoplayTimer.module.css';
import clsOv from './overlay.module.css';
@ -50,12 +51,12 @@ function AutoplayTimer({ history }: any) {
<AutoplayToggle />
</div>
<div className="flex items-center">
<Button variant="text-primary" onClick={cancel}>
<Button variant="text" onClick={cancel}>
Cancel
</Button>
<div className="px-2" />
<Link to={sessionRoute(nextId)} disabled={!nextId}>
<Button variant="outline">Play Now</Button>
<Button type="default">Play Now</Button>
</Link>
</div>
</div>

View file

@ -1,7 +1,7 @@
import React from 'react';
import { screenRecorder } from 'App/utils/screenRecorder';
import { Tooltip } from 'antd'
import { Button } from 'UI';
import { Tooltip, Button } from 'antd'
import { Icon } from 'UI';
import { SessionRecordingStatus } from 'Player';
let stopRecorderCb: () => void;
import { recordingsService } from 'App/services';
@ -116,7 +116,7 @@ function ScreenRecorder() {
<Tooltip
title={isEnterprise ? supportedMessage : ENTERPRISE_REQUEIRED}
>
<Button icon="record-circle" disabled variant="text-primary">
<Button icon={<Icon name={"record-circle"} size={16} />} disabled type="text">
Record Activity
</Button>
</Tooltip>
@ -127,8 +127,9 @@ function ScreenRecorder() {
return (
<div onClick={!isRecording ? recordingRequest : stopRecordingHandler} className="p-2">
<Button
icon={!isRecording ? 'stop-record-circle' : 'record-circle'}
variant={isRecording ? 'text-red' : 'text-primary'}
icon={<Icon name={!isRecording ? 'stop-record-circle' : 'record-circle'} size={16} />}
type={'text'}
className={isRecording ? 'text-red' : 'text-main'}
>
{isRecording ? 'Stop Recording' : 'Record Activity'}
</Button>

View file

@ -1,78 +0,0 @@
import React from 'react';
import { Button, Icon } from 'UI';
import styles from './menu.module.css';
import cn from 'classnames';
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
interface MenuItem {
key: number;
autoclose?: boolean;
component?: React.ReactElement;
}
interface Props {
items: MenuItem[];
useSc?: boolean;
}
export default class ItemMenu extends React.PureComponent<Props> {
state = {
displayed: false,
};
handleEsc = (e: KeyboardEvent) => e.key === 'Escape' && this.state.displayed && this.toggleMenu();
handleSc = (e: KeyboardEvent) => e.key === 'M' && e.shiftKey ? this.toggleMenu() : null;
componentDidMount() {
document.addEventListener('keydown', this.handleEsc, false);
if (this.props.useSc) {
document.addEventListener('keydown', this.handleSc, false)
}
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleEsc, false);
if (this.props.useSc) {
document.removeEventListener('keydown', this.handleSc, false)
}
}
toggleMenu = () => {
this.setState({ displayed: !this.state.displayed });
};
closeMenu = () => {
this.setState({ displayed: false });
};
render() {
const { items } = this.props;
const { displayed } = this.state;
return (
<div className={styles.wrapper}>
<OutsideClickDetectingDiv onClickOutside={this.closeMenu}>
<Button variant="text" onClick={this.toggleMenu}>
<div className="flex items-center">
<Icon name="ellipsis-v" size={18} className="mr-1" />
<span>More</span>
</div>
</Button>
<div className={cn(styles.menu, styles.menuDim)} data-displayed={displayed}>
{items.map((item) =>
item.component ? (
<div
key={item.key}
onClick={item.autoclose ? this.closeMenu : undefined}
role="menuitem"
className="hover:bg-gray-light-shade cursor-pointer flex items-center w-full"
>
{item.component}
</div>
) : null
)}
</div>
</OutsideClickDetectingDiv>
</div>
);
}
}

View file

@ -1,41 +0,0 @@
import CreateNote from 'Components/Session_/Player/Controls/components/CreateNote';
import React from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import { PlayerContext } from 'App/components/Session/playerContext';
import { Button, Tooltip } from 'antd';
import { MessageOutlined } from '@ant-design/icons';
import { useModal } from 'App/components/Modal';
function NotePopup() {
const { sessionStore } = useStore();
const tooltipActive = sessionStore.createNoteTooltip.isVisible;
const { player, store } = React.useContext(PlayerContext);
const { showModal, hideModal } = useModal();
const toggleNotePopup = () => {
if (tooltipActive) return;
player.pause();
showModal(
<CreateNote hideModal={hideModal} isEdit={false} time={Math.round(store.get().time)} />,
{
right: true,
width: 380,
}
);
};
return (
<Tooltip title={'Add Note'} placement='bottom'>
<Button
size={'small'}
className={'flex items-center justify-center'}
onClick={toggleNotePopup}
disabled={tooltipActive}
>
<MessageOutlined />
</Button>
</Tooltip>
);
}
export default observer(NotePopup)

View file

@ -15,7 +15,8 @@ import { SITE_ID_STORAGE_KEY } from 'App/constants/storageKeys';
import { useStore } from 'App/mstore';
import { login } from 'App/routes';
import { validatePassword } from 'App/validate';
import { Button, Form, Input, Link } from 'UI';
import { Form, Input, Link } from 'UI';
import { Button } from 'antd'
import Select from 'Shared/Select';
@ -221,8 +222,8 @@ const SignupForm = () => {
) : null}
<Button
type="submit"
variant="primary"
htmlType="submit"
type="primary"
loading={loading}
className="w-full rounded-lg"
>

View file

@ -1,120 +0,0 @@
import withPageTitle from 'HOCs/withPageTitle';
import { observer } from 'mobx-react-lite';
import React from 'react';
import { useStore } from 'App/mstore';
import { Button, Loader, Message } from 'UI';
import styles from './updatePassword.module.css';
const ERROR_DOESNT_MATCH = "Passwords doesn't match";
const MIN_LENGTH = 8;
const PASSWORD_POLICY = `Password should contain at least ${MIN_LENGTH} symbols`;
const checkDoesntMatch = (newPassword, newPasswordRepeat) =>
newPasswordRepeat.length > 0 && newPasswordRepeat !== newPassword;
function UpdatePassword() {
const { userStore } = useStore();
const updatePassword = userStore.updatePassword;
const errors = userStore.updatePasswordRequest.errors;
const loading = userStore.updatePasswordRequest.loading;
const [oldPassword, setOldPassword] = React.useState('');
const [newPassword, setNewPassword] = React.useState('');
const [newPasswordRepeat, setNewPasswordRepeat] = React.useState('');
const handleSubmit = (event) => {
event.preventDefault();
if (isSubmitDisabled()) return;
void updatePassword({ oldPassword, newPassword });
};
const writeOldPass = ({ target: { value } }) => setOldPassword(value);
const writeNewPass = ({ target: { value } }) => setNewPassword(value);
const writeNewPassRepeat = ({ target: { value } }) =>
setNewPasswordRepeat(value);
const isSubmitDisabled = () => {
if (
newPassword !== newPasswordRepeat ||
newPassword.length < MIN_LENGTH ||
oldPassword.length < MIN_LENGTH
)
return true;
return false;
};
const doesntMatch = checkDoesntMatch(newPassword, newPasswordRepeat);
return (
<div className={styles.form}>
<div className={styles.logo} />
<form onSubmit={handleSubmit}>
<h2>{'Password Change'}</h2>
<Loader loading={loading}>
<div>
<div className={styles.inputWithIcon}>
<i className={styles.inputIconPassword} />
<input
type="password"
placeholder="Old Password"
name="oldPassword"
onChange={writeOldPass}
className={styles.password}
/>
</div>
<div className={styles.inputWithIcon}>
<i className={styles.inputIconPassword} />
<input
type="password"
placeholder="New Password"
name="newPassword"
onChange={writeNewPass}
className={styles.password}
/>
</div>
<div
className={styles.passwordPolicy}
data-hidden={newPassword.length > 7}
>
{PASSWORD_POLICY}
</div>
<div className={styles.inputWithIcon}>
<i className={styles.inputIconPassword} />
<input
type="password"
placeholder="Repeat New Password"
name="newPasswordRepeat"
onChange={writeNewPassRepeat}
className={styles.password}
/>
</div>
<Message error hidden={!doesntMatch}>
{ERROR_DOESNT_MATCH}
</Message>
</div>
</Loader>
{errors && (
<div className={styles.errors}>
{errors.map((error) => (
<span>
{error}
<br />
</span>
))}
</div>
)}
<div className={styles.formFooter}>
<Button type="submit" variant="primary">
{'Update'}
</Button>
</div>
</form>
</div>
);
}
export default withPageTitle('Password Change - OpenReplay')(
observer(UpdatePassword)
);

View file

@ -1,127 +0,0 @@
@import 'icons.css';
.form {
position: absolute;
top: 50%;
margin-top: -300px;
width: 520px;
left: 50%;
margin-left: -260px;
& .passwordPolicy {
color: $gray-medium;
padding: 5px 0 10px;
font-size: 13px;
}
& form {
padding: 10px 70px;
border: solid 2px $gray-light;
border-radius: 2px;
background-color: white;
}
& h2 {
text-align: center;
font-size: 20px;
color: #555555;
margin: 35px 0;
font-weight: 300;
}
}
.formFooter {
text-align: center;
padding: 15px 0;
}
.links {
display: flex;
align-items: center;
justify-content: center;
padding: 10px 0;
margin-top: 20px;
& .divider {
width: 1px;
height: 12px;
background-color: $gray-medium;
margin: 0 5px;
}
}
.logo {
background-image: svg-load('logo.svg');
background-repeat: no-repeat;
background-size: contain;
background-position: center center;
height: 50px;
margin-bottom: 20px;
}
.email, .password {
display: block;
margin-top: 15px;
width: 100%;
height: 45px;
line-height: 45px;
border: $gray-light solid 1px;
border-radius: 3px;
font-size: 14px;
padding: 0 10px;
transition: all 0.2s;
&::placeholder {
color: #AAA;
}
&:focus {
border-color: $teal;
transition: all 0.2s;
}
}
.errors {
border-radius: 5px;
width: 400px;
margin: auto;
border: 2px solid $red;
padding: 15px;
background-color: $white;
}
.submit {
display: block;
border-radius: 5px;
background: $teal;
width: 135px;
height: 45px;
margin: 20px auto;
color: $white;
font-size: 16px;
cursor: pointer;
}
.inputWithIcon {
position: relative;
& input {
padding-left: 45px;
}
}
@define-mixin inputIcon $name {
position: absolute;
left: 15px;
top: calc(50% - 8px);
@mixin icon $name, $gray-medium, 15px;
}
.inputIconUser {
@mixin inputIcon user-alt;
}
.inputIconPassword {
@mixin inputIcon lock-alt;
}

View file

@ -1,5 +1,6 @@
import React, { useEffect } from 'react';
import { Button, NoContent, Loader } from 'UI';
import { NoContent, Loader } from 'UI';
import { Button } from 'antd'
import cn from 'classnames';
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
import ListItem from './ListItem'
@ -37,7 +38,6 @@ function AlertTriggersModal(props: Props) {
{ count > 0 && (
<div className="">
<Button
// loading={loading} // TODO should use the different loading state for this
variant="text"
onClick={onClearAll}
disabled={count === 0}

View file

@ -1,5 +1,5 @@
import React from 'react';
import { Button } from 'UI';
import { Button } from 'antd';
import stl from './listItem.module.css';
import cn from 'classnames';
import AlertTypeLabel from '../AlertTypeLabel';
@ -10,7 +10,7 @@ const ListItem = ({ alert, onClear, loading }: any) => {
<div className="flex justify-between items-center">
<div className="text-sm">{alert.createdAt && alert.createdAt.toFormat('LLL dd, yyyy, hh:mm a')}</div>
<div className={ cn("invisible", { 'group-hover:visible' : !alert.viewed})} >
<Button variant="text" loading={loading}>
<Button type="text" loading={loading}>
<span className={ cn("text-sm color-gray-medium", { 'invisible' : loading })} onClick={onClear}>{'IGNORE'}</span>
</Button>
</div>

View file

@ -2,7 +2,8 @@ import React from 'react';
import { VList, VListHandle } from 'virtua';
import cn from 'classnames';
import { Duration } from 'luxon';
import { NoContent, Button } from 'UI';
import { NoContent, Icon } from 'UI';
import { Button } from 'antd'
import { percentOf } from 'App/utils';
import BarRow from './BarRow';
@ -214,21 +215,13 @@ function TimeTable(props: Props) {
{navigation && (
<div className={cn(autoscrollStl.navButtons, 'flex items-center')}>
<Button
variant="text-primary"
icon="chevron-up"
tooltip={{
title: 'Previous Error',
delay: 0,
}}
type="text"
icon={<Icon name={'chevron-up'} />}
onClick={onPrevClick}
/>
<Button
variant="text-primary"
icon="chevron-down"
tooltip={{
title: 'Next Error',
delay: 0,
}}
type="text"
icon={<Icon name={'chevron-down'} />}
onClick={onNextClick}
/>
</div>

View file

@ -1,5 +1,6 @@
import React from 'react'
import { Button, Icon } from 'UI'
import { Icon } from 'UI'
import { Button } from 'antd'
export default function DocLink({ className = '', url, label }) {
const openLink = () => {
@ -8,7 +9,7 @@ export default function DocLink({ className = '', url, label }) {
return (
<div className={className}>
<Button variant="text-primary" onClick={openLink}>
<Button type="text" onClick={openLink} className={'flex items-center gap-2'}>
<span className="mr-2">{ label }</span>
<Icon name="external-link-alt" color="teal" />
</Button>

View file

@ -1,30 +0,0 @@
import React, { useState } from 'react'
import { Button } from 'UI';
export default function ImageViewer(
{ source, activeIndex, onClose }
) {
const [currentIndex, setCurrentIndex] = useState(activeIndex)
const onPrevClick = () => {
setCurrentIndex(currentIndex - 1);
}
const onNextClick = () => {
setCurrentIndex(currentIndex + 1);
}
return (
<div className="absolute bg-gray-light inset-0 z-50">
<div className="flex justify-between absolute bottom-0 left-0 right-0 p-3 border-t bg-white">
<Button variant="outline" onClick={onPrevClick} disabled={currentIndex === 0}>
Prev
</Button>
<Button variant="outline" onClick={onClose}>
CLOSE
</Button>
<Button variant="outline" onClick={onNextClick} disabled={currentIndex === source.length - 1}>
Next
</Button>
</div>
<img src={source[currentIndex]} className="border p-3"/>
</div>
)
}

View file

@ -1 +0,0 @@
export { default } from './ImageViewer';

View file

@ -1,5 +1,6 @@
import React from 'react'
import { Button, Icon } from 'UI'
import { Icon } from 'UI'
import { Button } from 'antd'
import { CLIENT_TABS, client as clientRoute } from 'App/routes';
import { withRouter } from 'react-router-dom';
@ -14,7 +15,7 @@ function IntegrateSlackTeamsButton({ history }) {
<Button
className="my-auto mt-2 mb-2 flex items-center gap-2"
onClick={gotoPreferencesIntegrations}
variant="text-primary"
type="text"
>
<Icon name="integrations/slack" size={16} />
<Icon name="integrations/teams" size={24} className="mr-2 ml-1" />

View file

@ -1,6 +1,7 @@
import React from 'react';
import LiveSessionSearchField from 'Shared/LiveSessionSearchField';
import { Button, Tooltip } from 'UI';
import { Tooltip } from 'UI';
import { Button } from 'antd'
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
@ -20,9 +21,9 @@ const LiveSearchBar = (props: Props) => {
<div className="flex items-center" style={{ width: '40%' }}>
<Tooltip title={'Clear Steps'}>
<Button
variant="text-primary"
type="text"
disabled={!hasFilters}
className="ml-auto font-medium"
className="text-main ml-auto font-medium"
onClick={() => searchStoreLive.clearSearch()}
>
Clear

View file

@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import { NoContent, Loader, Pagination, Button } from 'UI';
import { NoContent, Loader, Pagination, Icon } from 'UI';
import SessionItem from 'Shared/SessionItem';
import withPermissions from 'HOCs/withPermissions';
import { KEYS } from 'Types/filter/customFilter';
@ -13,6 +13,7 @@ import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
import { numberWithCommas } from 'App/utils';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { Button } from 'antd'
const AUTOREFRESH_INTERVAL = 2 * 60 * 1000;
const PER_PAGE = 10;
@ -144,10 +145,9 @@ function LiveSessionList() {
</span>
<Button
variant="text-primary"
variant="text"
className="mt-4"
icon="arrow-repeat"
iconSize={20}
icon={<Icon name="arrow-repeat" size={20} />}
onClick={refetch}
>
Refresh

View file

@ -1,6 +1,6 @@
import React from 'react';
import { Button, Modal, Form, Icon, Checkbox, Input } from 'UI';
import { confirm } from 'UI';
import { confirm, Modal, Form, Icon, Checkbox, Input } from 'UI';
import { Button } from 'antd'
import stl from './SaveSearchModal.module.css';
import cn from 'classnames';
import { toast } from 'react-toastify';
@ -96,14 +96,14 @@ function SaveSearchModal({ show, closeHandler, rename = false }: Props) {
</Modal.Content>
<Modal.Footer className="flex items-center px-6">
<div className="mr-auto flex items-center">
<Button variant="primary" onClick={onSave} loading={loading} disabled={!savedSearch.validate()}
<Button type="primary" onClick={onSave} loading={loading} disabled={!savedSearch.validate()}
className="mr-2">
{savedSearch.exists() ? 'Update' : 'Save'}
</Button>
<Button onClick={closeHandler}>{'Cancel'}</Button>
</div>
{savedSearch.exists() && (
<Button variant="text" onClick={onDelete}>
<Button type="text" onClick={onDelete}>
<Icon name="trash" size="18" />
</Button>
)}

View file

@ -1,5 +1,6 @@
import React from 'react';
import { Popover, Button } from 'UI';
import { Popover } from 'UI';
import { Button } from 'antd'
import MetaItem from '../MetaItem';
interface Props {
@ -23,7 +24,7 @@ export default function MetaMoreButton(props: Props) {
placement="bottom"
>
<div className="flex items-center">
<Button variant="text-primary">+{list.length - maxLength} More</Button>
<Button variant="text">+{list.length - maxLength} More</Button>
</div>
</Popover>
);

View file

@ -1,7 +1,8 @@
import { Conditions } from 'App/mstore/types/FeatureFlag';
import React from 'react';
import ConditionSet from 'Shared/ConditionSet';
import { Button } from 'UI';
import { Icon } from 'UI';
import { Button } from 'antd';
import { nonConditionalFlagFilters } from 'Types/filter/newFilter';
function ConditionalRecordingSettings({
@ -43,7 +44,7 @@ function ConditionalRecordingSettings({
/>
<div className={'flex gap-1 items-center'}>
<span className={'font-semibold'}>matching</span>
<Button variant={'text-primary'} icon={'plus'} onClick={addConditionSet}>
<Button type={'text'} icon={<Icon name={'plus'} size={16} />} onClick={addConditionSet}>
Condition Set
</Button>
</div>

View file

@ -5,8 +5,8 @@ import { toast } from 'react-toastify';
import { useStore } from 'App/mstore';
import { Timezone } from 'App/mstore/types/sessionSettings';
import { Button, Icon } from 'UI';
import { Icon } from 'UI';
import { Button } from 'antd'
import Select from 'Shared/Select';
type TimezonesDropdown = Timezone[];
@ -104,8 +104,7 @@ function DefaultTimezone() {
<div className="col-span-3 ml-3">
<Button
disabled={!changed}
variant="outline"
size="medium"
type="default"
onClick={onTimezoneSave}
>
Update

View file

@ -1,6 +1,7 @@
import React from 'react';
import Select from 'Shared/Select';
import { Button, Input } from 'UI';
import { Input } from 'UI';
import { Button } from 'antd';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { toast } from 'react-toastify';
@ -66,7 +67,7 @@ function ListingVisibility() {
/>
</div>
<div className="col-span-3">
<Button variant="outline" size="medium" disabled={!changed} onClick={saveSettings}>Update</Button>
<Button type="default" disabled={!changed} onClick={saveSettings}>Update</Button>
</div>
</div>
</>

View file

@ -1,7 +1,8 @@
import React, { useEffect } from 'react';
import { FilterKey } from 'Types/filter/filterType';
import SessionItem from 'Shared/SessionItem';
import { NoContent, Loader, Pagination, Button } from 'UI';
import { NoContent, Loader, Pagination, Icon } from 'UI';
import { Button } from 'antd'
import { useLocation, withRouter } from 'react-router-dom';
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
import { numberWithCommas } from 'App/utils';
@ -188,10 +189,9 @@ function SessionList() {
</div>
)}
<Button
variant="text-primary"
variant="text"
className="mt-4"
icon="arrow-repeat"
iconSize={20}
icon={<Icon name={"arrow-repeat"} size={20} />}
onClick={() => {
void searchStore.fetchSessions(true, isBookmark);
}}

View file

@ -1,7 +1,8 @@
import { useModal } from 'App/components/Modal';
import React from 'react';
import SessionSettings from 'Shared/SessionSettings';
import { Button, Tooltip } from 'UI';
import { Icon, Tooltip } from 'UI';
import { Button } from 'antd'
function SessionSettingButton(props: any) {
const { showModal } = useModal();
@ -13,7 +14,7 @@ function SessionSettingButton(props: any) {
return (
<div className="cursor-pointer ml-4" onClick={handleClick}>
<Tooltip title="Session Settings">
<Button icon="sliders" variant="text" id="btn-session-settings" />
<Button icon={<Icon name={'sliders'} />} type="text" id="btn-session-settings" />
</Tooltip>
</div>
);

Some files were not shown because too many files have changed in this diff Show more