Skip to content

Commit

Permalink
feat(frontend): add create button (#3282)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgeepc committed Oct 19, 2023
1 parent ba8d9dd commit fece173
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 84 deletions.
6 changes: 4 additions & 2 deletions web/src/components/AllowButton/AllowButton.tsx
Expand Up @@ -3,15 +3,17 @@ import {Operation, useCustomization} from 'providers/Customization/Customization

interface IProps extends ButtonProps {
operation: Operation;
ButtonComponent?: React.ComponentType<ButtonProps>;
}

const AllowButton = ({operation, ...props}: IProps) => {
const AllowButton = ({operation, ButtonComponent, ...props}: IProps) => {
const {getIsAllowed} = useCustomization();
const isAllowed = getIsAllowed(operation);
const BtnComponent = ButtonComponent || Button;

// the tooltip unmounts and remounts the children, detaching it from the DOM
return isAllowed ? (
<Button {...props} disabled={props.disabled} />
<BtnComponent {...props} disabled={props.disabled} />
) : (
<Tooltip title="You are not allowed to perform this operation">
<Button {...props} disabled />
Expand Down
8 changes: 8 additions & 0 deletions web/src/components/CreateButton/CreateButton.tsx
@@ -0,0 +1,8 @@
import {Button, ButtonProps} from 'antd';
import {withCustomization} from 'providers/Customization';

interface IProps extends ButtonProps {}

const CreateButton = ({...props}: IProps) => <Button {...props} />;

export default withCustomization(CreateButton, 'createButton');
2 changes: 2 additions & 0 deletions web/src/components/CreateButton/index.ts
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-restricted-exports
export {default} from './CreateButton';
6 changes: 4 additions & 2 deletions web/src/components/EditTest/EditTest.tsx
@@ -1,5 +1,6 @@
import {Button, Form} from 'antd';
import AllowButton, {Operation} from 'components/AllowButton';
import CreateButton from 'components/CreateButton';
import EditTestForm from 'components/EditTestForm';
import {TriggerTypeToPlugin} from 'constants/Plugins.constants';
import useValidateTestDraft from 'hooks/useValidateTestDraft';
Expand Down Expand Up @@ -46,11 +47,12 @@ const EditTest = ({test}: IProps) => {
</Button>
<AllowButton
operation={Operation.Edit}
ButtonComponent={CreateButton}
data-cy="edit-test-submit"
loading={isEditLoading}
disabled={!isValid || !stateIsFinished}
type="primary"
loading={isEditLoading}
onClick={() => form.submit()}
type="primary"
>
Save & Run
</AllowButton>
Expand Down
6 changes: 4 additions & 2 deletions web/src/components/EditTestSuite/EditTestSuite.tsx
@@ -1,6 +1,7 @@
import {Button, Form} from 'antd';
import {useCallback, useState} from 'react';
import AllowButton, {Operation} from 'components/AllowButton';
import CreateButton from 'components/CreateButton';
import {TDraftTestSuite} from 'types/TestSuite.types';
import {useTestSuite} from 'providers/TestSuite';
import useValidateTestSuiteDraft from 'hooks/useValidateTestSuiteDraft';
Expand Down Expand Up @@ -40,11 +41,12 @@ const EditTestSuite = ({testSuite, testSuiteRun}: IProps) => {
</Button>
<AllowButton
operation={Operation.Edit}
ButtonComponent={CreateButton}
data-cy="edit-testsuite-submit"
loading={isEditLoading}
disabled={!isFormValid || !stateIsFinished}
type="primary"
loading={isEditLoading}
onClick={() => form.submit()}
type="primary"
>
Save & Run
</AllowButton>
Expand Down
6 changes: 1 addition & 5 deletions web/src/components/ResourceCard/ResourceCard.styled.ts
@@ -1,5 +1,5 @@
import {MoreOutlined} from '@ant-design/icons';
import {Button, Space, Typography} from 'antd';
import {Space, Typography} from 'antd';
import styled from 'styled-components';

import emptyStateIcon from 'assets/SpanAssertionsEmptyState.svg';
Expand Down Expand Up @@ -112,10 +112,6 @@ export const Row = styled.div<{$gap?: number; $noWrap?: boolean}>`
white-space: ${({$noWrap}) => $noWrap && 'nowrap'};
`;

export const RunButton = styled(Button)`
margin-right: 12px;
`;

export const RunsContainer = styled.div`
padding: 0 24px 15px 64px;
`;
Expand Down
11 changes: 6 additions & 5 deletions web/src/components/ResourceCard/TestCard.tsx
@@ -1,5 +1,6 @@
import {DownOutlined, RightOutlined} from '@ant-design/icons';
import {useMemo} from 'react';
import CreateButton from 'components/CreateButton';
import TestRunCard from 'components/RunCard/TestRunCard';
import TracetestAPI from 'redux/apis/Tracetest';
import {ResourceType} from 'types/Resource.type';
Expand Down Expand Up @@ -47,18 +48,18 @@ const TestCard = ({onEdit, onDelete, onRun, onViewAll, test}: IProps) => {

<ResourceCardSummary summary={test.summary} />

<S.Row>
<S.RunButton
type="primary"
ghost
<S.Row $gap={12}>
<CreateButton
data-cy={`test-run-button-${test.id}`}
ghost
onClick={event => {
event.stopPropagation();
onRun(test, ResourceType.Test);
}}
type="primary"
>
Run
</S.RunButton>
</CreateButton>
<ResourceCardActions
id={test.id}
shouldEdit={shouldEdit}
Expand Down
11 changes: 6 additions & 5 deletions web/src/components/ResourceCard/TestSuiteCard.tsx
@@ -1,6 +1,7 @@
import {DownOutlined, RightOutlined} from '@ant-design/icons';
import {useMemo} from 'react';

import CreateButton from 'components/CreateButton';
import TestSuiteRunCard from 'components/RunCard/TestSuiteRunCard';
import TracetestAPI from 'redux/apis/Tracetest';
import {ResourceType} from 'types/Resource.type';
Expand Down Expand Up @@ -53,18 +54,18 @@ const TestSuiteCard = ({

<ResourceCardSummary summary={summary} />

<S.Row>
<S.RunButton
type="primary"
ghost
<S.Row $gap={12}>
<CreateButton
data-cy={`testsuite-run-button-${testSuiteId}`}
ghost
onClick={event => {
event.stopPropagation();
onRun(testSuite, ResourceType.TestSuite);
}}
type="primary"
>
Run
</S.RunButton>
</CreateButton>
<ResourceCardActions
id={testSuiteId}
shouldEdit={shouldEdit}
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/RunDetailLayout/HeaderRight.tsx
@@ -1,5 +1,6 @@
import {CloseCircleOutlined} from '@ant-design/icons';
import {Button, Tooltip} from 'antd';
import CreateButton from 'components/CreateButton';
import RunActionsMenu from 'components/RunActionsMenu';
import TestActions from 'components/TestActions';
import TestState from 'components/TestState';
Expand Down Expand Up @@ -58,9 +59,9 @@ const HeaderRight = ({testId}: IProps) => {
)}
<VariableSetSelector />
{!isDraftMode && state && isRunStateFinished(state) && (
<Button data-cy="run-test-button" ghost onClick={() => onRun()} type="primary">
<CreateButton data-cy="run-test-button" ghost onClick={() => onRun()} type="primary">
Run Test
</Button>
</CreateButton>
)}
<EventLogPopover runEvents={runEvents} />
<RunActionsMenu
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/TestSuiteHeader/TestSuiteHeader.tsx
@@ -1,5 +1,5 @@
import {Button} from 'antd';
import {useLocation} from 'react-router-dom';
import CreateButton from 'components/CreateButton';
import {TestSuiteRunStatusIcon} from 'components/RunStatusIcon';
import TestState from 'components/TestState';
import TestSuiteRunActionsMenu from 'components/TestSuiteRunActionsMenu';
Expand Down Expand Up @@ -76,9 +76,9 @@ const TestSuiteHeader = () => {
)}
<VariableSetSelector />
{state && state === TestStateEnum.FINISHED && (
<Button ghost onClick={() => onRun(runId)} type="primary" data-cy="testsuite-run-button">
<CreateButton data-cy="testsuite-run-button" ghost onClick={() => onRun(runId)} type="primary">
Run Test Suite
</Button>
</CreateButton>
)}
<TestSuiteRunActionsMenu testSuiteId={testSuiteId} runId={runId} isRunView />
</S.SectionRight>
Expand Down
18 changes: 0 additions & 18 deletions web/src/pages/Home/CreateButton.tsx

This file was deleted.

36 changes: 36 additions & 0 deletions web/src/pages/Home/EmptyTestList.tsx
@@ -0,0 +1,36 @@
import {Button} from 'antd';
import Empty from 'components/Empty';
import {ADD_TEST_URL, OPENING_TRACETEST_URL} from 'constants/Common.constants';
import {withCustomization} from 'providers/Customization';
import * as S from './Home.styled';

interface IProps {
onClick(): void;
}

const EmptyTestList = ({onClick}: IProps) => (
<Empty
title="Haven't Created a Test Yet"
message={
<>
Hit the &apos;Create&apos; button below to kickstart your testing adventure. Want to learn more about tests?
Just click{' '}
<S.Link href={ADD_TEST_URL} target="_blank">
here
</S.Link>
. If you don’t have an app that’s generating OpenTelemetry traces we have a demo for you. Follow these{' '}
<S.Link href={OPENING_TRACETEST_URL} target="_blank">
instructions
</S.Link>
!
</>
}
action={
<Button onClick={onClick} type="primary">
Create Your First Test
</Button>
}
/>
);

export default withCustomization(EmptyTestList, 'emptyTestList');
37 changes: 13 additions & 24 deletions web/src/pages/Home/TestsList.tsx
@@ -1,22 +1,22 @@
import AllowButton, {Operation} from 'components/AllowButton';
import CreateButton from 'components/CreateButton';
import CreateTestModal from 'components/CreateTestModal/CreateTestModal';
import Empty from 'components/Empty';
import Pagination from 'components/Pagination';
import TestCard from 'components/ResourceCard/TestCard';
import {SortBy, SortDirection, sortOptions} from 'constants/Test.constants';
import usePagination from 'hooks/usePagination';
import useTestCrud from 'providers/Test/hooks/useTestCrud';
import {useCallback, useState} from 'react';
import TracetestAPI from 'redux/apis/Tracetest';
import {ADD_TEST_URL, OPENING_TRACETEST_URL} from 'constants/Common.constants';
import HomeAnalyticsService from 'services/Analytics/HomeAnalytics.service';
import useDeleteResource from 'hooks/useDeleteResource';
import {useDashboard} from 'providers/Dashboard/Dashboard.provider';
import VariableSetSelector from 'components/VariableSetSelector/VariableSetSelector';
import Test from 'models/Test.model';
import * as S from './Home.styled';
import CreateButton from './CreateButton';
import HomeFilters from './HomeFilters';
import Loading from './Loading';
import EmptyTestList from './EmptyTestList';

const {useGetTestListQuery} = TracetestAPI.instance;

Expand Down Expand Up @@ -67,30 +67,19 @@ const Tests = () => {
onSortBy={(sortBy, sortDirection) => setParameters({sortBy, sortDirection})}
isEmpty={pagination.list?.length === 0}
/>
<CreateButton onCreate={() => setIsCreateTestOpen(true)} dataCy="create-button" />
<AllowButton
operation={Operation.Edit}
ButtonComponent={CreateButton}
data-cy="create-button"
onClick={() => setIsCreateTestOpen(true)}
type="primary"
>
Create
</AllowButton>
</S.ActionsContainer>

<Pagination<Test>
emptyComponent={
<Empty
title="Haven't Created a Test Yet"
message={
<>
Hit the &apos;Create&apos; button below to kickstart your testing adventure. Want to learn more about
tests? Just click{' '}
<S.Link href={ADD_TEST_URL} target="_blank">
here
</S.Link>
. If you don’t have an app that’s generating OpenTelemetry traces we have a demo for you. Follow these{' '}
<S.Link href={OPENING_TRACETEST_URL} target="_blank">
instructions
</S.Link>
!
</>
}
action={<CreateButton onCreate={() => setIsCreateTestOpen(true)} title="Create Your First Test" />}
/>
}
emptyComponent={<EmptyTestList onClick={() => setIsCreateTestOpen(true)} />}
loadingComponent={<Loading />}
{...pagination}
>
Expand Down
3 changes: 1 addition & 2 deletions web/src/pages/Settings/Content.tsx
Expand Up @@ -7,7 +7,7 @@ import Linter from 'components/Settings/Linter';
import Polling from 'components/Settings/Polling';
import TestRunner from 'components/Settings/TestRunner';
import BetaBadge from 'components/BetaBadge/BetaBadge';
import {useCustomization, withCustomization} from 'providers/Customization';
import {withCustomization} from 'providers/Customization';
import * as S from './Settings.styled';

const TabsKeys = {
Expand All @@ -20,7 +20,6 @@ const TabsKeys = {
};

const Content = () => {
const {getFlag} = useCustomization();
const [query, setQuery] = useSearchParams();

return (
Expand Down
6 changes: 3 additions & 3 deletions web/src/pages/Test/Content.tsx
@@ -1,5 +1,5 @@
import {useMemo} from 'react';
import {Button} from 'antd';
import CreateButton from 'components/CreateButton';
import PaginatedList from 'components/PaginatedList';
import TestRunCard from 'components/RunCard/TestRunCard';
import TestHeader from 'components/TestHeader';
Expand Down Expand Up @@ -39,15 +39,15 @@ const Content = () => {
shouldEdit={shouldEdit}
title={`${test.name} (v${test.version})`}
runButton={
<Button
<CreateButton
data-cy="test-details-run-test-button"
ghost
loading={isLoadingRunTest}
onClick={() => runTest({test})}
type="primary"
>
Run Test
</Button>
</CreateButton>
}
/>

Expand Down
6 changes: 3 additions & 3 deletions web/src/pages/TestSuite/Content.tsx
@@ -1,5 +1,5 @@
import {Button} from 'antd';
import {useCallback, useMemo} from 'react';
import CreateButton from 'components/CreateButton';
import PaginatedList from 'components/PaginatedList';
import TestSuiteRunCard from 'components/RunCard/TestSuiteRunCard';
import TestHeader from 'components/TestHeader';
Expand Down Expand Up @@ -39,9 +39,9 @@ const Content = () => {
shouldEdit={shouldEdit}
title={`${testSuite.name} (v${testSuite.version})`}
runButton={
<Button onClick={handleRunTest} loading={isEditLoading} type="primary" ghost>
<CreateButton ghost loading={isEditLoading} onClick={handleRunTest} type="primary">
Run Test Suite
</Button>
</CreateButton>
}
/>

Expand Down
5 changes: 0 additions & 5 deletions web/src/pages/TestSuites/TestSuites.styled.tsx
@@ -1,5 +1,4 @@
import {Button as AntdButton, Dropdown, Row, Space, Typography} from 'antd';
import AllowButton from 'components/AllowButton';
import styled from 'styled-components';

export const Button = styled(AntdButton)`
Expand All @@ -11,10 +10,6 @@ export const Link = styled.a`
font-weight: 600;
`;

export const CreateTestButton = styled(AllowButton)`
font-weight: 600;
`;

export const CreateDropdownButton = styled(Dropdown)``;

export const ActionsContainer = styled.div`
Expand Down

0 comments on commit fece173

Please sign in to comment.