Skip to content

Commit

Permalink
Merge branch 'main' into feat/command-bar-pages-and-name-resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
daveleek committed Jun 14, 2024
2 parents 09f105e + 25947c3 commit 5d31ad1
Show file tree
Hide file tree
Showing 31 changed files with 459 additions and 77 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file.

## [6.0.3] - 2024-06-14

### Bug Fixes

- Backport lifecycle and playground fixes ([#7396](https://github.com/Unleash/unleash/issues/7396))


## [6.0.2] - 2024-06-12

### Bug Fixes
Expand Down
24 changes: 12 additions & 12 deletions docker/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -577,11 +577,11 @@ brace-expansion@^2.0.1:
balanced-match "^1.0.0"

braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.0.1"
fill-range "^7.1.1"

buffer-from@^1.0.0:
version "1.1.2"
Expand Down Expand Up @@ -1399,10 +1399,10 @@ fast-safe-stringify@^2.0.7:
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==

fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"

Expand Down Expand Up @@ -2682,10 +2682,10 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==

path-scurry@1.10.2, path-scurry@^1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7"
integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==
path-scurry@1.11.1, path-scurry@^1.10.2:
version "1.11.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
dependencies:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
Expand Down
32 changes: 29 additions & 3 deletions frontend/src/component/commandBar/CommandBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
} from './RecentlyVisited/CommandResultGroup';
import { PageSuggestions } from './PageSuggestions';
import { useRoutes } from 'component/layout/MainLayout/NavigationSidebar/useRoutes';
import { useAsyncDebounce } from 'react-table';
import useProjects from 'hooks/api/getters/useProjects/useProjects';

export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
position: 'absolute',
Expand Down Expand Up @@ -85,6 +87,9 @@ export const CommandBar = () => {
const searchInputRef = useRef<HTMLInputElement>(null);
const searchContainerRef = useRef<HTMLInputElement>(null);
const [showSuggestions, setShowSuggestions] = useState(false);
const [searchedProjects, setSearchedProjects] = useState<
CommandResultGroupItem[]
>([]);
const { lastVisited } = useRecentlyVisited();
const { routes } = useRoutes();
const allRoutes: Record<
Expand All @@ -109,8 +114,26 @@ export const CommandBar = () => {

const [value, setValue] = useState<string>('');

const { features, setTableState } = useGlobalFeatureSearch(3);
const { projects } = useProjects();

const debouncedSetSearchState = useAsyncDebounce((query) => {
setTableState({ query });

const filteredProjects = projects.filter((project) =>
project.name.toLowerCase().includes(query.toLowerCase()),
);

const mappedProjects = filteredProjects.map((project) => ({
name: project.name,
link: `/projects/${project.id}`,
}));

setSearchedProjects(mappedProjects);
}, 200);

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

Expand Down Expand Up @@ -138,8 +161,6 @@ export const CommandBar = () => {
useOnClickOutside([searchContainerRef], hideSuggestions);
useOnBlur(searchContainerRef, hideSuggestions);

const { features, setTableState } = useGlobalFeatureSearch(3);

const flags: CommandResultGroupItem[] = features.map((feature) => ({
name: feature.name,
link: `/projects/${feature.project}/features/${feature.name}`,
Expand Down Expand Up @@ -200,6 +221,11 @@ export const CommandBar = () => {
icon={'flag'}
items={flags}
/>
<CommandResultGroup
groupName={'Projects'}
icon={'flag'}
items={searchedProjects}
/>
</CommandResultsPaper>
}
elseShow={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
} from '@mui/material';
import { Link } from 'react-router-dom';
import type { Theme } from '@mui/material/styles/createTheme';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { StyledProjectIcon } from '../../layout/MainLayout/NavigationSidebar/IconRenderer';

const listItemButtonStyle = (theme: Theme) => ({
borderRadius: theme.spacing(0.5),
Expand Down Expand Up @@ -49,6 +51,10 @@ export const CommandResultGroup = ({
items,
}: CommandResultGroupProps) => {
const slicedItems = items.slice(0, 3);

if (items.length === 0) {
return null;
}
return (
<>
<StyledTypography color='textSecondary'>
Expand All @@ -64,7 +70,11 @@ export const CommandResultGroup = ({
sx={listItemButtonStyle}
>
<StyledListItemIcon>
<Icon>{icon}</Icon>
<ConditionallyRender
condition={groupName === 'Projects'}
show={<StyledProjectIcon />}
elseShow={<Icon>{icon}</Icon>}
/>
</StyledListItemIcon>
<StyledListItemText>
<Typography>{item.name}</Typography>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface IPermissionIconButtonProps {
edge?: IconButtonProps['edge'];
tooltipProps?: Omit<ITooltipResolverProps, 'children'>;
sx?: IconButtonProps['sx'];
size?: string;
size?: 'small' | 'medium' | 'large';
}

interface IButtonProps extends IPermissionIconButtonProps {
Expand Down Expand Up @@ -87,7 +87,7 @@ const BasePermissionIconButton = ({
{...rest}
disabled={!access || disabled}
aria-labelledby={id}
size='large'
size={rest.size || 'large'}
>
{children}
</IconButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export const comparisonModerator = (
): DeepOmit<IFeatureToggle, keyof IFeatureToggle> => {
const tempData = { ...data };

return deepOmit(tempData, 'lastSeenAt', 'yes', 'no');
return deepOmit(tempData, 'lastSeenAt', 'yes', 'no', 'lifecycle');
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DELETE_FEATURE,
UPDATE_FEATURE,
} from 'component/providers/AccessProvider/permissions';
import { Route, Routes } from 'react-router-dom';

const currentTime = '2024-04-25T08:05:00.000Z';
const twoMinutesAgo = '2024-04-25T08:03:00.000Z';
Expand All @@ -22,16 +23,24 @@ const renderOpenTooltip = (
loading = false,
) => {
render(
<FeatureLifecycleTooltip
stage={stage}
onArchive={onArchive}
onComplete={onComplete}
onUncomplete={onUncomplete}
loading={loading}
>
<span>child</span>
</FeatureLifecycleTooltip>,
<Routes>
<Route
path={'/projects/:projectId'}
element={
<FeatureLifecycleTooltip
stage={stage}
onArchive={onArchive}
onComplete={onComplete}
onUncomplete={onUncomplete}
loading={loading}
>
<span>child</span>
</FeatureLifecycleTooltip>
}
/>
</Routes>,
{
route: '/projects/default',
permissions: [
{ permission: DELETE_FEATURE },
{ permission: UPDATE_FEATURE },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { isSafeToArchive } from './isSafeToArchive';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { formatDateYMDHMS } from 'utils/formatDate';
import { formatDistanceToNow, parseISO } from 'date-fns';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';

const TimeLabel = styled('span')(({ theme }) => ({
color: theme.palette.text.secondary,
Expand Down Expand Up @@ -267,6 +268,8 @@ const LiveStageDescription: FC<{
loading: boolean;
children?: React.ReactNode;
}> = ({ children, onComplete, loading }) => {
const projectId = useRequiredPathParam('projectId');

return (
<>
<BoldTitle>Is this feature complete?</BoldTitle>
Expand All @@ -285,6 +288,7 @@ const LiveStageDescription: FC<{
size='small'
onClick={onComplete}
disabled={loading}
projectId={projectId}
>
Mark completed
</PermissionButton>
Expand All @@ -303,6 +307,8 @@ const SafeToArchive: FC<{
onUncomplete: () => void;
loading: boolean;
}> = ({ onArchive, onUncomplete, loading }) => {
const projectId = useRequiredPathParam('projectId');

return (
<>
<BoldTitle>Safe to archive</BoldTitle>
Expand All @@ -319,6 +325,7 @@ const SafeToArchive: FC<{
sx={{
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
gap: 2,
}}
>
Expand All @@ -329,6 +336,7 @@ const SafeToArchive: FC<{
size='small'
onClick={onUncomplete}
disabled={loading}
projectId={projectId}
>
Revert to live
</PermissionButton>
Expand All @@ -339,6 +347,7 @@ const SafeToArchive: FC<{
size='small'
sx={{ mb: 2 }}
onClick={onArchive}
projectId={projectId}
>
Archive feature
</PermissionButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => {
<StyledDetail>
<StyledLabel>Dependency:</StyledLabel>
<PermissionButton
size='small'
permission={UPDATE_FEATURE_DEPENDENCY}
projectId={feature.project}
variant='text'
onClick={() => {
setShowDependencyDialogue(true);
}}
sx={(theme) => ({
marginBottom: theme.spacing(0.4),
})}
>
Add parent feature
</PermissionButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useShowDependentFeatures } from './useShowDependentFeatures';
import type { ILastSeenEnvironments } from 'interfaces/featureToggle';
import { FeatureLifecycle } from '../FeatureLifecycle/FeatureLifecycle';
import { MarkCompletedDialogue } from '../FeatureLifecycle/MarkCompletedDialogue';
import { UserAvatar } from 'component/common/UserAvatar/UserAvatar';

const StyledContainer = styled('div')(({ theme }) => ({
borderRadius: theme.shape.borderRadiusLarge,
Expand Down Expand Up @@ -83,6 +84,10 @@ const StyledDescription = styled('p')({
wordBreak: 'break-word',
});

const StyledUserAvatar = styled(UserAvatar)(({ theme }) => ({
margin: theme.spacing(1),
}));

export const StyledLabel = styled('span')(({ theme }) => ({
color: theme.palette.text.secondary,
marginRight: theme.spacing(1),
Expand All @@ -98,6 +103,7 @@ const FeatureOverviewMetaData = () => {
const [showDelDialog, setShowDelDialog] = useState(false);
const [showMarkCompletedDialogue, setShowMarkCompletedDialogue] =
useState(false);
const flagCreatorEnabled = useUiFlag('flagCreator');

const { locationSettings } = useLocationSettings();
const showDependentFeatures = useShowDependentFeatures(feature.project);
Expand Down Expand Up @@ -166,6 +172,7 @@ const FeatureOverviewMetaData = () => {
{description}
</StyledDescription>
<PermissionIconButton
size='medium'
projectId={projectId}
permission={UPDATE_FEATURE}
component={Link}
Expand All @@ -184,6 +191,7 @@ const FeatureOverviewMetaData = () => {
<StyledDescriptionContainer>
No description.{' '}
<PermissionIconButton
size='medium'
projectId={projectId}
permission={UPDATE_FEATURE}
component={Link}
Expand Down Expand Up @@ -216,6 +224,24 @@ const FeatureOverviewMetaData = () => {
/>
</StyledDetailsContainer>
</BodyItemWithIcon>
<ConditionallyRender
condition={
Boolean(feature.createdBy) && flagCreatorEnabled
}
show={() => (
<BodyItemWithIcon>
<StyledDetailsContainer>
<StyledDetail>
<StyledLabel>Created by:</StyledLabel>
<span>{feature.createdBy?.name}</span>
</StyledDetail>
<StyledUserAvatar
src={feature.createdBy?.imageUrl}
/>
</StyledDetailsContainer>
</BodyItemWithIcon>
)}
/>
<ConditionallyRender
condition={showDependentFeatures}
show={<DependencyRow feature={feature} />}
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/interfaces/featureToggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export type Lifecycle = {
enteredStageAt: string;
};

/**
* @deprecated use FeatureSchema from openapi
*/
export interface IFeatureToggle {
stale: boolean;
archived: boolean;
Expand All @@ -57,6 +60,11 @@ export interface IFeatureToggle {
dependencies: Array<IDependency>;
lifecycle?: Lifecycle;
children: Array<string>;
createdBy?: {
id: string;
name: string;
imageUrl: string;
};
}

export interface IDependency {
Expand Down
Loading

0 comments on commit 5d31ad1

Please sign in to comment.