Skip to content

Commit

Permalink
Merge pull request #199 from atlassian/ARC-2599-part-1-connection-pan…
Browse files Browse the repository at this point in the history
…el-top

Arc-2599 part 1 connection panel top
  • Loading branch information
rachellerathbone authored Nov 16, 2023
2 parents 8678de1 + acea2d5 commit 03d7e24
Show file tree
Hide file tree
Showing 12 changed files with 342 additions and 4 deletions.
3 changes: 2 additions & 1 deletion app/jenkins-for-jira-ui/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@
":": "before"
}
}
]
],
"import/no-extraneous-dependencies": ["error", {"devDependencies": true}]
},
"settings": {
"import/parsers": {
Expand Down
3 changes: 2 additions & 1 deletion app/jenkins-for-jira-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
"@atlaskit/spinner": "15.5.3",
"@atlaskit/textfield": "5.6.4",
"@atlaskit/theme": "12.5.5",
"@atlaskit/tokens": "^1.28.1",
"@atlaskit/tooltip": "17.8.4",
"@atlassiansox/analytics-web-client": "^4.14.3",
"@atlassiansox/analytics-web-client": "^4.14.3",
"@emotion/css": "11.7.1",
"@emotion/react": "11.7.1",
"@emotion/styled": "11.6.0",
Expand Down
9 changes: 9 additions & 0 deletions app/jenkins-for-jira-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import styled from '@emotion/styled';
import { view } from '@forge/bridge';
import { withLDProvider } from 'launchdarkly-react-client-sdk';
import { setGlobalTheme } from '@atlaskit/tokens';
import { InstallJenkins } from './components/ConnectJenkins/InstallJenkins/InstallJenkins';
import { JenkinsServerList } from './components/JenkinsServerList/JenkinsServerList';
import { ConnectJenkins } from './components/ConnectJenkins/ConnectJenkins/ConnectJenkins';
Expand Down Expand Up @@ -77,6 +78,14 @@ const App: React.FC = () => {
return <JenkinsSpinner secondaryClassName={spinnerHeight} />;
}

setGlobalTheme({
light: 'light',
dark: 'dark',
colorMode: 'auto',
spacing: 'spacing',
typography: 'typography'
});

return (
<AppContainer>
<Router history={history}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { css } from '@emotion/css';
import { token } from '@atlaskit/tokens';

export const connectionPanelContainer = css`
border-radius: 8px;
box-shadow: 0px 2px 4px 0px #091E4240;
display: flex;
flex-direction: column;
max-height: 164px;
padding: ${token('space.300')};
margin: ${token('space.400')} auto ${token('space.400')} ${token('space.025')};
`;

export const connectionPanelTopContainer = css`
border-bottom: 1px solid #f4f3f6;
display: flex;
justify-content: space-between;
padding-bottom: ${token('space.300')};
`;

export const connectionPanelHeaderContainer = css`
align-items: center;
flex-direction: column;
margin-bottom: ${token('space.075')};
`;

export const connectionPanelHeaderContentContainer = css`
align-items: center;
display: flex;
margin-bottom: ${token('space.075')};
`;

export const serverName = css`
font-size: 20px;
margin-right: ${token('space.075')};
`;

export const ipAddressStyle = css`
color: #626F86;
font-size: 14px;
`;

export const connectionPanelMainContainer = css`
margin-top: ${token('space.200', '16px')};
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { ConnectionPanelTop } from './ConnectionPanelTop';
import { ConnectedState } from '../StatusLabel/StatusLabel';

describe('ConnectionPanelTop', () => {
test('renders with the correct content and styles for CONNECTED state', () => {
const ipAddress = '10.0.0.1';
render(<ConnectionPanelTop connectedState={ConnectedState.CONNECTED} ipAddress={ipAddress} />);

const nameLabel = screen.getByText(/Insert name/i);
const ipAddressLabel = screen.getByText(`IP address: ${ipAddress}`);
const statusLabel = screen.getByTestId('status-label');

expect(nameLabel).toBeInTheDocument();
expect(ipAddressLabel).toBeInTheDocument();
expect(statusLabel).toHaveStyle({ color: '#206e4e', backgroundColor: '#dcfff1' });
expect(statusLabel).toHaveTextContent('CONNECTED');
});

test('renders with the correct content and styles for DUPLICATE state', () => {
const ipAddress = '10.0.0.1';
render(<ConnectionPanelTop connectedState={ConnectedState.DUPLICATE} ipAddress={ipAddress} />);

const nameLabel = screen.getByText(/Insert name/i);
const ipAddressLabel = screen.getByText(`IP address: ${ipAddress}`);
const statusLabel = screen.getByTestId('status-label');

expect(nameLabel).toBeInTheDocument();
expect(ipAddressLabel).toBeInTheDocument();
expect(statusLabel).toHaveStyle({ color: '#ae2e24', backgroundColor: '#ffecea' });
expect(statusLabel).toHaveTextContent('DUPLICATE');
});

test('renders with the correct content and styles for PENDING state', () => {
const ipAddress = '10.0.0.1';
render(<ConnectionPanelTop connectedState={ConnectedState.PENDING} ipAddress={ipAddress} />);

const nameLabel = screen.getByText(/Insert name/i);
const ipAddressLabel = screen.getByText(`IP address: ${ipAddress}`);
const statusLabel = screen.getByTestId('status-label');

expect(nameLabel).toBeInTheDocument();
expect(ipAddressLabel).toBeInTheDocument();
expect(statusLabel).toHaveStyle({ color: '#a54900', backgroundColor: '#fff7d6' });
expect(statusLabel).toHaveTextContent('PENDING');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useEffect, useState } from 'react';
import { cx } from '@emotion/css';
import { ConnectionPanelMain } from './ConnectionPanelMain';
import { ConnectionPanelTop } from './ConnectionPanelTop';
import { ConnectedState } from '../StatusLabel/StatusLabel';
import { connectionPanelContainer } from './ConnectionPanel.styles';

const ConnectionPanel = (): JSX.Element => {
// TODO - remove temp state and define pending/duplicate/connected state from data
const [connectedState, setConnectState] = useState<ConnectedState>(ConnectedState.PENDING);

useEffect(() => {
// TODO - update this based on data
setConnectState(ConnectedState.DUPLICATE);
}, []);

return (
<div className={cx(connectionPanelContainer)}>
<ConnectionPanelTop connectedState={connectedState} ipAddress="10.10.0.10"/>
<ConnectionPanelMain />
</div>
);
};

export { ConnectionPanel };
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { cx } from '@emotion/css';
import { connectionPanelMainContainer } from './ConnectionPanel.styles';

const ConnectionPanelMain = (): JSX.Element => {
return (
<div className={cx(connectionPanelMainContainer)}>Connection panel main coming soon...</div>
);
};

export { ConnectionPanelMain };
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { cx } from '@emotion/css';
import Button from '@atlaskit/button/standard-button';
import MoreIcon from '@atlaskit/icon/glyph/more';
import DropdownMenu, { DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
import {
connectionPanelHeaderContainer,
connectionPanelHeaderContentContainer,
connectionPanelTopContainer,
ipAddressStyle,
serverName
} from './ConnectionPanel.styles';
import { ConnectedState, StatusLabel } from '../StatusLabel/StatusLabel';

type ConnectionPanelTopProps = {
connectedState: ConnectedState,
ipAddress: string
};

const connectedStateColors: Record<ConnectedState, { textColor: string; backgroundColor: string }> = {
[ConnectedState.CONNECTED]: { textColor: '#206e4e', backgroundColor: '#dcfff1' },
[ConnectedState.DUPLICATE]: { textColor: '#ae2e24', backgroundColor: '#ffecea' },
[ConnectedState.PENDING]: { textColor: '#a54900', backgroundColor: '#fff7d6' }
};

const ConnectionPanelTop = ({ connectedState, ipAddress }: ConnectionPanelTopProps): JSX.Element => {
const { textColor, backgroundColor } = connectedStateColors[connectedState];

return (
<div className={cx(connectionPanelTopContainer)}>
<div className={cx(connectionPanelHeaderContainer)}>
<div className={cx(connectionPanelHeaderContentContainer)}>
<h2 className={cx(serverName)}>Insert name</h2>
<StatusLabel text={connectedState} color={textColor} backgroundColor={backgroundColor} />
</div>
<div>
<p className={cx(ipAddressStyle)}>IP address: {ipAddress}</p>
</div>
</div>
<DropdownMenu
trigger={({ triggerRef, ...props }) => (
<Button
{...props}
iconBefore={<MoreIcon label="more" />}
ref={triggerRef}
/>
)}
>
<DropdownItemGroup>
{/* TODO: add onClick for all dropdown items */}
<DropdownItem>Rename</DropdownItem>
<DropdownItem>Connection settings</DropdownItem>
<DropdownItem>Disconnect</DropdownItem>
</DropdownItemGroup>
</DropdownMenu>
</div>
);
};

export { ConnectionPanelTop };
5 changes: 4 additions & 1 deletion app/jenkins-for-jira-ui/src/components/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import PageHeader from '@atlaskit/page-header';
import { ButtonGroup } from '@atlaskit/button';
import Button from '@atlaskit/button/standard-button';
import { headerContainer } from '../JenkinsServerList/JenkinsServerList.styles';
import { TopPanel } from './TopPanel/TopPanel';
import { mainPageContainer } from './MainPage.styles';
import { ConnectionPanel } from '../ConnectionPanel/ConnectionPanel';
import { TopPanel } from './TopPanel/TopPanel';

const MainPage = (): JSX.Element => {
const pageHeaderActions = (
Expand All @@ -25,6 +26,8 @@ const MainPage = (): JSX.Element => {
</div>

<TopPanel />

<ConnectionPanel />
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { css } from '@emotion/css';

export const statusLabel = css`
border-radius: 3px;
font-size: 11px;
font-weight: 700;
margin: 0;
padding: 0.1em 0.3em;
`;
30 changes: 30 additions & 0 deletions app/jenkins-for-jira-ui/src/components/StatusLabel/StatusLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { cx } from '@emotion/css';
import { statusLabel } from './StatusLabel.styles';

export enum ConnectedState {
CONNECTED = 'CONNECTED',
DUPLICATE = 'DUPLICATE',
PENDING = 'PENDING'
}

type StatusLabelProps = {
text: string,
backgroundColor: string,
color: string
};

const StatusLabel = ({ text, backgroundColor, color }: StatusLabelProps): JSX.Element => {
const dynamicStyles = {
backgroundColor,
color
};

return (
<p className={cx(statusLabel)} style={dynamicStyles}>
{text}
</p>
);
};

export { StatusLabel };
Loading

0 comments on commit 03d7e24

Please sign in to comment.