Skip to content

Commit

Permalink
Merge branch 'main' into chore/deleted-project-api-tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
Tymek authored Jul 4, 2024
2 parents 9f0b2dd + 96a1996 commit 415cadb
Show file tree
Hide file tree
Showing 85 changed files with 2,401 additions and 624 deletions.
1 change: 0 additions & 1 deletion USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
| Amedia | https://www.amedia.no/ |
| Deutsche Telekom | https://www.telekom.com/ |
| Docker | https://www.docker.com/ |
| Federal Reserve Bank of Kansas City | https://www.kansascityfed.org/ |
| FINN.no | https://www.finn.no/ |
| H-E-B | https://www.heb.com/ |
| Interflora | https://www.interflora.co.uk/ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@ import { ProjectsList } from 'component/admin/apiToken/ProjectsList/ProjectsList

describe('ProjectsList', () => {
it('should prioritize new "projects" array over deprecated "project"', async () => {
render(
const { container } = render(
<ProjectsList
project='project'
projects={['project1', 'project2']}
/>,
);

const links = await screen.findAllByRole('link');
expect(links).toHaveLength(2);
expect(links[0]).toHaveTextContent('project1');
expect(links[1]).toHaveTextContent('project2');
expect(links[0]).toHaveAttribute('href', '/projects/project1');
expect(links[1]).toHaveAttribute('href', '/projects/project2');
expect(container.textContent).toContain('2 projects');
});

it('should render correctly with single "project"', async () => {
Expand All @@ -27,12 +22,6 @@ describe('ProjectsList', () => {
expect(links[0]).toHaveTextContent('project');
});

it('should have comma between project links', async () => {
const { container } = render(<ProjectsList projects={['a', 'b']} />);

expect(container.textContent).toContain(', ');
});

it('should render asterisk if no projects are passed', async () => {
const { container } = render(<ProjectsList />);

Expand All @@ -44,4 +33,14 @@ describe('ProjectsList', () => {

expect(container.textContent).toEqual('*');
});

it('should show the number of projects', async () => {
const { container } = render(
<ProjectsList
projects={['project1', 'project2', 'project3', 'project4']}
/>,
);

expect(container.textContent).toContain('4 projects');
});
});
87 changes: 58 additions & 29 deletions frontend/src/component/admin/apiToken/ProjectsList/ProjectsList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { styled } from '@mui/material';
import { Highlighter } from 'component/common/Highlighter/Highlighter';
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
import { Fragment, type VFC } from 'react';
import { Fragment, type FC } from 'react';
import { Link } from 'react-router-dom';

const StyledLink = styled(Link)(({ theme }) => ({
Expand All @@ -18,42 +20,69 @@ interface IProjectsListProps {
projects?: string | string[];
}

export const ProjectsList: VFC<IProjectsListProps> = ({
projects,
project,
}) => {
export const ProjectsList: FC<IProjectsListProps> = ({ projects, project }) => {
const { searchQuery } = useSearchHighlightContext();
const fields: string[] =
projects && Array.isArray(projects)

const projectsList =
projects && Array.isArray(projects) && projects.length > 1
? projects
: project
? [project]
: [];
: [];

if (fields.length === 0) {
if (projectsList.length > 0) {
return (
<TextCell>
<Highlighter search={searchQuery}>*</Highlighter>
<HtmlTooltip
title={projectsList.map((item, index) => (
<Fragment key={item}>
{index > 0 && ', '}
{!item || item === '*' ? (
<Highlighter search={searchQuery}>
*
</Highlighter>
) : (
<StyledLink to={`/projects/${item}`}>
<Highlighter search={searchQuery}>
{item}
</Highlighter>
</StyledLink>
)}
</Fragment>
))}
placement='bottom-start'
arrow
tabIndex={0}
>
<span>{`${projectsList.length}`} projects</span>
</HtmlTooltip>
</TextCell>
);
}

return (
<TextCell>
{fields.map((item, index) => (
<Fragment key={item}>
{index > 0 && ', '}
{!item || item === '*' ? (
if (
(projectsList.length === 1 && projectsList[0] === '*') ||
project === '*' ||
(!project && (!projectsList || projectsList.length === 0))
) {
return (
<TextCell>
<HtmlTooltip
title='ALL current and future projects'
placement='bottom'
arrow
>
<span>
<Highlighter search={searchQuery}>*</Highlighter>
) : (
<StyledLink to={`/projects/${item}`}>
<Highlighter search={searchQuery}>
{item}
</Highlighter>
</StyledLink>
)}
</Fragment>
))}
</TextCell>
);
</span>
</HtmlTooltip>
</TextCell>
);
}

if (projectsList.length === 1 || project) {
const item = project || projectsList[0];

return <LinkCell to={`/projects/${item}`} title={item} />;
}

return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const BillingInformation: FC<IBillingInformationProps> = ({
</StyledInfoLabel>
<StyledDivider />
<StyledInfoLabel>
<a href='mailto:customersuccess@getunleash.io?subject=PRO plan clarifications'>
<a href='mailto:support@getunleash.io?subject=PRO plan clarifications'>
Get in touch with us
</a>{' '}
for any clarification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export const BillingPlan: FC<IBillingPlanProps> = ({ instanceStatus }) => {
After you have sent your billing information, your
instance will be upgraded - you don't have to do
anything.{' '}
<a href='mailto:customersuccess@getunleash.io?subject=PRO plan clarifications'>
<a href='mailto:support@getunleash.io?subject=PRO plan clarifications'>
Get in touch with us
</a>{' '}
for any clarification
Expand Down
90 changes: 70 additions & 20 deletions frontend/src/component/commandBar/CommandBar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import {
Box,
IconButton,
Expand All @@ -13,7 +13,6 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import { useKeyboardShortcut } from 'hooks/useKeyboardShortcut';
import { SEARCH_INPUT } from 'utils/testIds';
import { useOnClickOutside } from 'hooks/useOnClickOutside';
import { useOnBlur } from 'hooks/useOnBlur';
import {
CommandResultGroup,
type CommandResultGroupItem,
Expand All @@ -22,10 +21,11 @@ import { CommandPageSuggestions } from './CommandPageSuggestions';
import { useRoutes } from 'component/layout/MainLayout/NavigationSidebar/useRoutes';
import { useAsyncDebounce } from 'react-table';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { CommandFeatures } from './CommandFeatures';
import { CommandSearchFeatures } from './CommandSearchFeatures';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { CommandRecent } from './CommandRecent';
import { CommandPages } from './CommandPages';
import { CommandQuickSuggestions } from './CommandQuickSuggestions';
import { CommandSearchPages } from './CommandSearchPages';
import { CommandBarFeedback } from './CommandBarFeedback';
import { RecentlyVisitedRecorder } from './RecentlyVisitedRecorder';

export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
Expand All @@ -35,7 +35,7 @@ export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
top: '39px',
zIndex: 4,
borderTop: theme.spacing(0),
padding: theme.spacing(4, 0, 1.5),
padding: theme.spacing(1.5, 0, 1.5),
borderRadius: 0,
borderBottomLeftRadius: theme.spacing(1),
borderBottomRightRadius: theme.spacing(1),
Expand Down Expand Up @@ -72,11 +72,6 @@ const StyledSearch = styled('div')(({ theme }) => ({
padding: '3px 5px 3px 12px',
width: '100%',
zIndex: 3,
'&:focus-within': {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
borderBottom: '0px',
},
}));

const StyledInputBase = styled(InputBase)(({ theme }) => ({
Expand Down Expand Up @@ -109,6 +104,7 @@ export const CommandBar = () => {
CommandResultGroupItem[]
>([]);
const [searchedFlagCount, setSearchedFlagCount] = useState(0);
const [hasNoResults, setHasNoResults] = useState(false);
const [value, setValue] = useState<string>('');
const { routes } = useRoutes();
const allRoutes: Record<string, IPageRouteInfo> = {};
Expand Down Expand Up @@ -166,13 +162,23 @@ export const CommandBar = () => {
},
});
}
setHasNoResults(noResultsFound);
}, 200);

useEffect(() => {
debouncedSetSearchState(value);
}, [searchedFlagCount]);

const onSearchChange = (value: string) => {
debouncedSetSearchState(value);
setValue(value);
};

const clearSearchValue = () => {
onSearchChange('');
setShowSuggestions(false);
};

const hotkey = useKeyboardShortcut(
{
modifiers: ['ctrl'],
Expand All @@ -188,19 +194,44 @@ export const CommandBar = () => {
},
);
useKeyboardShortcut({ key: 'Escape' }, () => {
setShowSuggestions(false);
if (searchContainerRef.current?.contains(document.activeElement)) {
searchInputRef.current?.blur();
}
});
const placeholder = `Command bar (${hotkey})`;

useOnClickOutside([searchContainerRef], hideSuggestions);
useOnBlur(searchContainerRef, hideSuggestions);

const onKeyDown = (event: React.KeyboardEvent) => {
if (event.key === 'Escape') {
setShowSuggestions(false);
} else if (
event.keyCode >= 48 &&
event.keyCode <= 110 &&
!hasNoResults
) {
searchInputRef.current?.focus();
}
};
return (
<StyledContainer ref={searchContainerRef} active={showSuggestions}>
<RecentlyVisitedRecorder />
<StyledSearch>
<StyledSearch
sx={{
borderBottomLeftRadius: (theme) =>
showSuggestions
? 0
: theme.shape.borderRadiusExtraLarge,
borderBottomRightRadius: (theme) =>
showSuggestions
? 0
: theme.shape.borderRadiusExtraLarge,
borderBottom: (theme) =>
showSuggestions
? '0px'
: `1px solid ${theme.palette.neutral.border}`,
}}
>
<SearchIcon
sx={{
mr: 1,
Expand Down Expand Up @@ -248,26 +279,45 @@ export const CommandBar = () => {
<ConditionallyRender
condition={Boolean(value) && showSuggestions}
show={
<CommandResultsPaper>
<CommandResultsPaper onKeyDownCapture={onKeyDown}>
{searchString !== undefined && (
<CommandFeatures
<CommandSearchFeatures
searchString={searchString}
setSearchedFlagCount={setSearchedFlagCount}
onClick={clearSearchValue}
/>
)}
<CommandResultGroup
groupName={'Projects'}
icon={'flag'}
onClick={clearSearchValue}
items={searchedProjects}
/>
<CommandPages items={searchedPages} />
<CommandSearchPages
items={searchedPages}
onClick={clearSearchValue}
/>
<ConditionallyRender
condition={hasNoResults}
show={
<CommandBarFeedback
onSubmit={hideSuggestions}
/>
}
/>
</CommandResultsPaper>
}
elseShow={
showSuggestions && (
<CommandResultsPaper>
<CommandRecent routes={allRoutes} />
<CommandPageSuggestions routes={allRoutes} />
<CommandResultsPaper onKeyDownCapture={onKeyDown}>
<CommandQuickSuggestions
routes={allRoutes}
onClick={clearSearchValue}
/>
<CommandPageSuggestions
routes={allRoutes}
onClick={clearSearchValue}
/>
</CommandResultsPaper>
)
}
Expand Down
Loading

0 comments on commit 415cadb

Please sign in to comment.