mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-04 13:48:56 +02:00
fix: misc ui fixes post tables upgrade (#1049)
* fix: misc ui fixes post tables upgrade * fix: update snaps, small cleanup * refactor: ReportCard to styled, misc improvements * cleanup remaining styles file * rename `Feature Toggle Name` to just `name` * refactor: address PR comments
This commit is contained in:
parent
bad17e3606
commit
682921d5bf
@ -1,116 +0,0 @@
|
|||||||
.card {
|
|
||||||
width: 100%;
|
|
||||||
padding: var(--card-padding);
|
|
||||||
margin: var(--card-margin-y) 0;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
font-size: var(--h1-size);
|
|
||||||
font-weight: 'bold';
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardContainer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.reportCardHealth {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
.reportCardAction {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
.reportCardToggle {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardHealthInnerContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardHealthRating {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--success);
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardList {
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardList li {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardList li span {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
font-size: var(--p-size);
|
|
||||||
}
|
|
||||||
|
|
||||||
.check,
|
|
||||||
.danger {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.check {
|
|
||||||
color: var(--success);
|
|
||||||
}
|
|
||||||
|
|
||||||
.danger {
|
|
||||||
color: var(--danger);
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardActionContainer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardActionText {
|
|
||||||
max-width: 300px;
|
|
||||||
font-size: var(--p-size);
|
|
||||||
margin-left: 35px;
|
|
||||||
}
|
|
||||||
.reportCardNoActionText {
|
|
||||||
max-width: 300px;
|
|
||||||
font-size: var(--p-size);
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportCardBtn {
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.healthDanger {
|
|
||||||
color: var(--danger);
|
|
||||||
}
|
|
||||||
|
|
||||||
.healthWarning {
|
|
||||||
color: var(--warning);
|
|
||||||
}
|
|
||||||
.lastUpdate {
|
|
||||||
color: #585858;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.reportCardContainer {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.reportCardToggle {
|
|
||||||
margin: 10px 5px;
|
|
||||||
flex-basis: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,132 +1,180 @@
|
|||||||
import classnames from 'classnames';
|
import { Box, Paper, styled } from '@mui/material';
|
||||||
import { Paper } from '@mui/material';
|
|
||||||
import CheckIcon from '@mui/icons-material/Check';
|
import CheckIcon from '@mui/icons-material/Check';
|
||||||
import ReportProblemOutlinedIcon from '@mui/icons-material/ReportProblemOutlined';
|
import ReportProblemOutlinedIcon from '@mui/icons-material/ReportProblemOutlined';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import styles from './ReportCard.module.scss';
|
|
||||||
import ReactTimeAgo from 'react-timeago';
|
import ReactTimeAgo from 'react-timeago';
|
||||||
import { IProjectHealthReport } from 'interfaces/project';
|
import { IProjectHealthReport } from 'interfaces/project';
|
||||||
|
|
||||||
|
const StyledBoxActive = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: theme.palette.success.dark,
|
||||||
|
'& svg': {
|
||||||
|
color: theme.palette.success.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledBoxStale = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: theme.palette.warning.dark,
|
||||||
|
'& svg': {
|
||||||
|
color: theme.palette.warning.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledPaper = styled(Paper)(({ theme }) => ({
|
||||||
|
padding: theme.spacing(4),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
boxShadow: 'none',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
[theme.breakpoints.down('md')]: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: theme.spacing(2),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHeader = styled('h2')(({ theme }) => ({
|
||||||
|
fontSize: theme.fontSizes.mainHeader,
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHealthRating = styled('p')(({ theme }) => ({
|
||||||
|
fontSize: '2rem',
|
||||||
|
fontWeight: theme.fontWeight.bold,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledLastUpdated = styled('p')(({ theme }) => ({
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledList = styled('ul')(({ theme }) => ({
|
||||||
|
listStyleType: 'none',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
'& svg': {
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAlignedItem = styled('p')(({ theme }) => ({
|
||||||
|
marginLeft: theme.spacing(4),
|
||||||
|
}));
|
||||||
|
|
||||||
interface IReportCardProps {
|
interface IReportCardProps {
|
||||||
healthReport: IProjectHealthReport;
|
healthReport: IProjectHealthReport;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReportCard = ({ healthReport }: IReportCardProps) => {
|
export const ReportCard = ({ healthReport }: IReportCardProps) => {
|
||||||
const healthLessThan50 = healthReport.health < 50;
|
const healthRatingColor =
|
||||||
const healthLessThan75 = healthReport.health < 75;
|
healthReport.health < 50
|
||||||
|
? 'error.main'
|
||||||
const healthClasses = classnames(styles.reportCardHealthRating, {
|
: healthReport.health < 75
|
||||||
[styles.healthWarning]: healthLessThan75,
|
? 'warning.main'
|
||||||
[styles.healthDanger]: healthLessThan50,
|
: 'success.main';
|
||||||
});
|
|
||||||
|
|
||||||
const renderActiveToggles = () => (
|
const renderActiveToggles = () => (
|
||||||
<>
|
<StyledBoxActive>
|
||||||
<CheckIcon className={styles.check} />
|
<CheckIcon />
|
||||||
<span>{healthReport.activeCount} active toggles</span>
|
<span>{healthReport.activeCount} active toggles</span>
|
||||||
</>
|
</StyledBoxActive>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderStaleToggles = () => (
|
const renderStaleToggles = () => (
|
||||||
<>
|
<StyledBoxStale>
|
||||||
<ReportProblemOutlinedIcon className={styles.danger} />
|
<ReportProblemOutlinedIcon />
|
||||||
<span>{healthReport.staleCount} stale toggles</span>
|
<span>{healthReport.staleCount} stale toggles</span>
|
||||||
</>
|
</StyledBoxStale>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderPotentiallyStaleToggles = () => (
|
const renderPotentiallyStaleToggles = () => (
|
||||||
<>
|
<StyledBoxStale>
|
||||||
<ReportProblemOutlinedIcon className={styles.danger} />
|
<ReportProblemOutlinedIcon />
|
||||||
<span>
|
<span>
|
||||||
{healthReport.potentiallyStaleCount} potentially stale toggles
|
{healthReport.potentiallyStaleCount} potentially stale toggles
|
||||||
</span>
|
</span>
|
||||||
</>
|
</StyledBoxStale>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className={styles.card}>
|
<StyledPaper>
|
||||||
<div className={styles.reportCardContainer}>
|
<Box>
|
||||||
<div className={styles.reportCardHealth}>
|
<StyledHeader>Health rating</StyledHeader>
|
||||||
<h2 className={styles.header}>Health rating</h2>
|
<ConditionallyRender
|
||||||
<div className={styles.reportCardHealthInnerContainer}>
|
condition={healthReport.health > -1}
|
||||||
<ConditionallyRender
|
show={
|
||||||
condition={healthReport.health > -1}
|
<>
|
||||||
show={
|
<StyledHealthRating
|
||||||
<div>
|
sx={{ color: healthRatingColor }}
|
||||||
<p className={healthClasses}>
|
>
|
||||||
{healthReport.health}%
|
{healthReport.health}%
|
||||||
</p>
|
</StyledHealthRating>
|
||||||
<p className={styles.lastUpdate}>
|
<StyledLastUpdated>
|
||||||
Last updated:{' '}
|
Last updated:{' '}
|
||||||
<ReactTimeAgo
|
<ReactTimeAgo
|
||||||
date={healthReport.updatedAt}
|
date={healthReport.updatedAt}
|
||||||
live={false}
|
live={false}
|
||||||
/>
|
/>
|
||||||
</p>
|
</StyledLastUpdated>
|
||||||
</div>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Box>
|
||||||
</div>
|
<Box>
|
||||||
<div className={styles.reportCardToggle}>
|
<StyledHeader>Toggle report</StyledHeader>
|
||||||
<h2 className={styles.header}>Toggle report</h2>
|
<StyledList>
|
||||||
<ul className={styles.reportCardList}>
|
<li>
|
||||||
<li>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(healthReport.activeCount)}
|
|
||||||
show={renderActiveToggles}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(healthReport.activeCount)}
|
condition={Boolean(healthReport.activeCount)}
|
||||||
show={
|
show={renderActiveToggles}
|
||||||
<p className={styles.reportCardActionText}>
|
|
||||||
Also includes potentially stale toggles.
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
</li>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(healthReport.activeCount)}
|
||||||
|
show={
|
||||||
|
<StyledAlignedItem>
|
||||||
|
Also includes potentially stale toggles.
|
||||||
|
</StyledAlignedItem>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(healthReport.staleCount)}
|
condition={Boolean(healthReport.staleCount)}
|
||||||
show={renderStaleToggles}
|
show={renderStaleToggles}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</StyledList>
|
||||||
</div>
|
</Box>
|
||||||
|
<Box>
|
||||||
<div className={styles.reportCardAction}>
|
<StyledHeader>Potential actions</StyledHeader>
|
||||||
<h2 className={styles.header}>Potential actions</h2>
|
<StyledList>
|
||||||
<div className={styles.reportCardActionContainer}>
|
<li>
|
||||||
<ul className={styles.reportCardList}>
|
|
||||||
<li>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(
|
|
||||||
healthReport.potentiallyStaleCount
|
|
||||||
)}
|
|
||||||
show={renderPotentiallyStaleToggles}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(
|
condition={Boolean(
|
||||||
healthReport.potentiallyStaleCount
|
healthReport.potentiallyStaleCount
|
||||||
)}
|
)}
|
||||||
show={
|
show={renderPotentiallyStaleToggles}
|
||||||
<p className={styles.reportCardActionText}>
|
|
||||||
Review your feature toggles and delete
|
|
||||||
unused toggles.
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<p className={styles.reportCardNoActionText}>
|
|
||||||
No action is required
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
</StyledList>
|
||||||
</div>
|
<ConditionallyRender
|
||||||
</Paper>
|
condition={Boolean(healthReport.potentiallyStaleCount)}
|
||||||
|
show={
|
||||||
|
<StyledAlignedItem>
|
||||||
|
Review your feature toggles and delete unused
|
||||||
|
toggles.
|
||||||
|
</StyledAlignedItem>
|
||||||
|
}
|
||||||
|
elseShow={
|
||||||
|
<StyledAlignedItem>
|
||||||
|
No action is required
|
||||||
|
</StyledAlignedItem>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</StyledPaper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,12 +4,20 @@ import { ReportProblemOutlined, Check } from '@mui/icons-material';
|
|||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import { IReportTableRow } from 'component/Reporting/ReportTable/ReportTable';
|
import { IReportTableRow } from 'component/Reporting/ReportTable/ReportTable';
|
||||||
|
|
||||||
const StyledText = styled('span')(({ theme }) => ({
|
const StyledTextPotentiallyStale = styled('span')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
gap: '1ch',
|
gap: '1ch',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
textAlign: 'right',
|
color: theme.palette.warning.dark,
|
||||||
'& svg': { color: theme.palette.inactiveIcon },
|
'& svg': { color: theme.palette.warning.main },
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledTextHealthy = styled('span')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
gap: '1ch',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: theme.palette.success.dark,
|
||||||
|
'& svg': { color: theme.palette.success.main },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface IReportStatusCellProps {
|
interface IReportStatusCellProps {
|
||||||
@ -24,20 +32,20 @@ export const ReportStatusCell: VFC<IReportStatusCellProps> = ({
|
|||||||
if (row.original.status === 'potentially-stale') {
|
if (row.original.status === 'potentially-stale') {
|
||||||
return (
|
return (
|
||||||
<TextCell>
|
<TextCell>
|
||||||
<StyledText>
|
<StyledTextPotentiallyStale>
|
||||||
<ReportProblemOutlined />
|
<ReportProblemOutlined />
|
||||||
<span>Potentially stale</span>
|
<span>Potentially stale</span>
|
||||||
</StyledText>
|
</StyledTextPotentiallyStale>
|
||||||
</TextCell>
|
</TextCell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextCell>
|
<TextCell>
|
||||||
<StyledText>
|
<StyledTextHealthy>
|
||||||
<Check />
|
<Check />
|
||||||
<span>Healthy</span>
|
<span>Healthy</span>
|
||||||
</StyledText>
|
</StyledTextHealthy>
|
||||||
</TextCell>
|
</TextCell>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -55,7 +55,7 @@ export const ReportTable = ({ projectId, features }: IReportTableProps) => {
|
|||||||
const initialState = useMemo(
|
const initialState = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
hiddenColumns: [],
|
hiddenColumns: [],
|
||||||
sortBy: [{ id: 'name' }],
|
sortBy: [{ id: 'createdAt', desc: true }],
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@ -84,9 +84,11 @@ export const ReportTable = ({ projectId, features }: IReportTableProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const hiddenColumns = [];
|
||||||
if (isSmallScreen) {
|
if (isSmallScreen) {
|
||||||
setHiddenColumns(['createdAt', 'expiredAt']);
|
hiddenColumns.push('createdAt', 'expiredAt');
|
||||||
}
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isSmallScreen]);
|
}, [setHiddenColumns, isSmallScreen]);
|
||||||
|
|
||||||
const header = (
|
const header = (
|
||||||
@ -101,8 +103,6 @@ export const ReportTable = ({ projectId, features }: IReportTableProps) => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(rows);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent header={header}>
|
<PageContent header={header}>
|
||||||
<SearchHighlightProvider value={globalFilter}>
|
<SearchHighlightProvider value={globalFilter}>
|
||||||
@ -131,15 +131,15 @@ export const ReportTable = ({ projectId, features }: IReportTableProps) => {
|
|||||||
condition={globalFilter?.length > 0}
|
condition={globalFilter?.length > 0}
|
||||||
show={
|
show={
|
||||||
<TablePlaceholder>
|
<TablePlaceholder>
|
||||||
No features found matching “
|
No feature toggles found matching “
|
||||||
{globalFilter}
|
{globalFilter}
|
||||||
”
|
”
|
||||||
</TablePlaceholder>
|
</TablePlaceholder>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<TablePlaceholder>
|
<TablePlaceholder>
|
||||||
No features available. Get started by adding a
|
No feature toggles available. Get started by
|
||||||
new feature toggle.
|
adding a new feature toggle.
|
||||||
</TablePlaceholder>
|
</TablePlaceholder>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -182,7 +182,7 @@ const COLUMNS = [
|
|||||||
disableGlobalFilter: true,
|
disableGlobalFilter: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Feature toggle name',
|
Header: 'Name',
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
width: '60%',
|
width: '60%',
|
||||||
sortType: 'alphanumeric',
|
sortType: 'alphanumeric',
|
||||||
@ -204,8 +204,8 @@ const COLUMNS = [
|
|||||||
{
|
{
|
||||||
Header: 'Status',
|
Header: 'Status',
|
||||||
accessor: 'status',
|
accessor: 'status',
|
||||||
align: 'right',
|
|
||||||
Cell: ReportStatusCell,
|
Cell: ReportStatusCell,
|
||||||
|
disableGlobalFilter: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'State',
|
Header: 'State',
|
||||||
|
@ -13,7 +13,6 @@ import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightC
|
|||||||
import { ApiTokenDocs } from 'component/admin/apiToken/ApiTokenDocs/ApiTokenDocs';
|
import { ApiTokenDocs } from 'component/admin/apiToken/ApiTokenDocs/ApiTokenDocs';
|
||||||
import { CreateApiTokenButton } from 'component/admin/apiToken/CreateApiTokenButton/CreateApiTokenButton';
|
import { CreateApiTokenButton } from 'component/admin/apiToken/CreateApiTokenButton/CreateApiTokenButton';
|
||||||
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
|
||||||
import { Key } from '@mui/icons-material';
|
import { Key } from '@mui/icons-material';
|
||||||
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
|
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
|
||||||
import { CopyApiTokenButton } from 'component/admin/apiToken/CopyApiTokenButton/CopyApiTokenButton';
|
import { CopyApiTokenButton } from 'component/admin/apiToken/CopyApiTokenButton/CopyApiTokenButton';
|
||||||
@ -176,12 +175,10 @@ const COLUMNS = [
|
|||||||
Header: 'Project',
|
Header: 'Project',
|
||||||
accessor: 'project',
|
accessor: 'project',
|
||||||
Cell: (props: any) => (
|
Cell: (props: any) => (
|
||||||
<TextCell>
|
<ProjectsList
|
||||||
<ProjectsList
|
project={props.row.original.project}
|
||||||
project={props.row.original.project}
|
projects={props.row.original.projects}
|
||||||
projects={props.row.original.projects}
|
/>
|
||||||
/>
|
|
||||||
</TextCell>
|
|
||||||
),
|
),
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,17 @@
|
|||||||
|
import { styled } from '@mui/material';
|
||||||
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
||||||
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { Fragment, VFC } from 'react';
|
import { Fragment, VFC } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
const StyledLink = styled(Link)(() => ({
|
||||||
|
textDecoration: 'none',
|
||||||
|
'&:hover, &:focus': {
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
interface IProjectsListProps {
|
interface IProjectsListProps {
|
||||||
project?: string;
|
project?: string;
|
||||||
projects?: string | string[];
|
projects?: string | string[];
|
||||||
@ -22,25 +31,29 @@ export const ProjectsList: VFC<IProjectsListProps> = ({
|
|||||||
: [];
|
: [];
|
||||||
|
|
||||||
if (fields.length === 0) {
|
if (fields.length === 0) {
|
||||||
return <Highlighter search={searchQuery}>*</Highlighter>;
|
return (
|
||||||
|
<TextCell>
|
||||||
|
<Highlighter search={searchQuery}>*</Highlighter>
|
||||||
|
</TextCell>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<TextCell>
|
||||||
{fields.map((item, index) => (
|
{fields.map((item, index) => (
|
||||||
<Fragment key={item}>
|
<Fragment key={item}>
|
||||||
{index > 0 && ', '}
|
{index > 0 && ', '}
|
||||||
{!item || item === '*' ? (
|
{!item || item === '*' ? (
|
||||||
<Highlighter search={searchQuery}>*</Highlighter>
|
<Highlighter search={searchQuery}>*</Highlighter>
|
||||||
) : (
|
) : (
|
||||||
<Link to={`/projects/${item}`}>
|
<StyledLink to={`/projects/${item}`}>
|
||||||
<Highlighter search={searchQuery}>
|
<Highlighter search={searchQuery}>
|
||||||
{item}
|
{item}
|
||||||
</Highlighter>
|
</Highlighter>
|
||||||
</Link>
|
</StyledLink>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</TextCell>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -69,7 +69,7 @@ export const BillingHistory: VFC<IBillingHistoryProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const initialState = useMemo(
|
const initialState = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
sortBy: [{ id: 'createdAt', desc: false }],
|
sortBy: [{ id: 'dueDate' }],
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -175,10 +175,11 @@ const ProjectRoleList = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setHiddenColumns([]);
|
const hiddenColumns = [];
|
||||||
if (isExtraSmallScreen) {
|
if (isExtraSmallScreen) {
|
||||||
setHiddenColumns(['Icon']);
|
hiddenColumns.push('Icon');
|
||||||
}
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isExtraSmallScreen]);
|
}, [setHiddenColumns, isExtraSmallScreen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -139,6 +139,7 @@ const UsersList = () => {
|
|||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 'name',
|
||||||
Header: 'Name',
|
Header: 'Name',
|
||||||
accessor: (row: any) => row.name || '',
|
accessor: (row: any) => row.name || '',
|
||||||
width: '40%',
|
width: '40%',
|
||||||
@ -231,10 +232,10 @@ const UsersList = () => {
|
|||||||
hiddenColumns.push('type');
|
hiddenColumns.push('type');
|
||||||
}
|
}
|
||||||
if (isSmallScreen) {
|
if (isSmallScreen) {
|
||||||
hiddenColumns.push(...['createdAt', 'username']);
|
hiddenColumns.push('createdAt', 'username');
|
||||||
}
|
}
|
||||||
if (isExtraSmallScreen) {
|
if (isExtraSmallScreen) {
|
||||||
hiddenColumns.push(...['imageUrl', 'role', 'last-login']);
|
hiddenColumns.push('imageUrl', 'role', 'last-login');
|
||||||
}
|
}
|
||||||
setHiddenColumns(hiddenColumns);
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isExtraSmallScreen, isSmallScreen, isBillingUsers]);
|
}, [setHiddenColumns, isExtraSmallScreen, isSmallScreen, isBillingUsers]);
|
||||||
|
@ -58,6 +58,7 @@ const PermissionIconButton = ({
|
|||||||
{...tooltipProps}
|
{...tooltipProps}
|
||||||
title={formatAccessText(access, tooltipProps?.title)}
|
title={formatAccessText(access, tooltipProps?.title)}
|
||||||
arrow
|
arrow
|
||||||
|
onClick={e => e.preventDefault()}
|
||||||
>
|
>
|
||||||
<div id={id} role="tooltip">
|
<div id={id} role="tooltip">
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -75,7 +75,7 @@ const CreateEnvironment = () => {
|
|||||||
show={
|
show={
|
||||||
<FormTemplate
|
<FormTemplate
|
||||||
loading={loading}
|
loading={loading}
|
||||||
title="Create Environment"
|
title="Create environment"
|
||||||
description="Environments allow you to manage your
|
description="Environments allow you to manage your
|
||||||
product lifecycle from local development
|
product lifecycle from local development
|
||||||
through production. Your projects and
|
through production. Your projects and
|
||||||
|
@ -16,7 +16,7 @@ export const CreateEnvironmentButton = () => {
|
|||||||
permission={ADMIN}
|
permission={ADMIN}
|
||||||
disabled={!Boolean(uiConfig.flags.EEA)}
|
disabled={!Boolean(uiConfig.flags.EEA)}
|
||||||
>
|
>
|
||||||
New Environment
|
New environment
|
||||||
</ResponsiveButton>
|
</ResponsiveButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
} from 'component/common/Table';
|
} from 'component/common/Table';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { TableBody } from '@mui/material';
|
import { Alert, styled, TableBody } from '@mui/material';
|
||||||
import { CloudCircle } from '@mui/icons-material';
|
import { CloudCircle } from '@mui/icons-material';
|
||||||
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
||||||
import { EnvironmentActionCell } from 'component/environments/EnvironmentActionCell/EnvironmentActionCell';
|
import { EnvironmentActionCell } from 'component/environments/EnvironmentActionCell/EnvironmentActionCell';
|
||||||
@ -25,6 +25,10 @@ import useEnvironmentApi, {
|
|||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
|
const StyledAlert = styled(Alert)(({ theme }) => ({
|
||||||
|
marginBottom: theme.spacing(4),
|
||||||
|
}));
|
||||||
|
|
||||||
export const EnvironmentTable = () => {
|
export const EnvironmentTable = () => {
|
||||||
const { changeSortOrder } = useEnvironmentApi();
|
const { changeSortOrder } = useEnvironmentApi();
|
||||||
const { setToastApiError } = useToast();
|
const { setToastApiError } = useToast();
|
||||||
@ -82,6 +86,11 @@ export const EnvironmentTable = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent header={header}>
|
<PageContent header={header}>
|
||||||
|
<StyledAlert severity="info">
|
||||||
|
This is the order of environments that you have today in each
|
||||||
|
feature toggle. Rearranging them here will change also the order
|
||||||
|
inside each feature toggle.
|
||||||
|
</StyledAlert>
|
||||||
<SearchHighlightProvider value={globalFilter}>
|
<SearchHighlightProvider value={globalFilter}>
|
||||||
<Table {...getTableProps()}>
|
<Table {...getTableProps()}>
|
||||||
<SortableTableHeader headerGroups={headerGroups as any} />
|
<SortableTableHeader headerGroups={headerGroups as any} />
|
||||||
|
@ -104,7 +104,7 @@ export const CopyFeatureToggle = () => {
|
|||||||
</p>
|
</p>
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<TextField
|
<TextField
|
||||||
label="Feature toggle name"
|
label="Name"
|
||||||
name="name"
|
name="name"
|
||||||
value={newToggleName || ''}
|
value={newToggleName || ''}
|
||||||
onBlur={onValidateName}
|
onBlur={onValidateName}
|
||||||
|
@ -64,7 +64,7 @@ const columns = [
|
|||||||
disableGlobalFilter: true,
|
disableGlobalFilter: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Feature toggle name',
|
Header: 'Name',
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
Cell: FeatureNameCell,
|
Cell: FeatureNameCell,
|
||||||
@ -101,7 +101,7 @@ const columns = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const defaultSort: SortingRule<string> = { id: 'createdAt', desc: false };
|
const defaultSort: SortingRule<string> = { id: 'createdAt', desc: true };
|
||||||
|
|
||||||
export const FeatureToggleListTable: VFC = () => {
|
export const FeatureToggleListTable: VFC = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -162,19 +162,14 @@ export const FeatureToggleListTable: VFC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSmallScreen) {
|
const hiddenColumns = ['description'];
|
||||||
setHiddenColumns([
|
if (isMediumScreen) {
|
||||||
'lastSeenAt',
|
hiddenColumns.push('lastSeenAt', 'stale');
|
||||||
'type',
|
|
||||||
'stale',
|
|
||||||
'description',
|
|
||||||
'createdAt',
|
|
||||||
]);
|
|
||||||
} else if (isMediumScreen) {
|
|
||||||
setHiddenColumns(['lastSeenAt', 'stale', 'description']);
|
|
||||||
} else {
|
|
||||||
setHiddenColumns(['description']);
|
|
||||||
}
|
}
|
||||||
|
if (isSmallScreen) {
|
||||||
|
hiddenColumns.push('type', 'createdAt');
|
||||||
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isSmallScreen, isMediumScreen]);
|
}, [setHiddenColumns, isSmallScreen, isMediumScreen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -289,15 +284,15 @@ export const FeatureToggleListTable: VFC = () => {
|
|||||||
condition={globalFilter?.length > 0}
|
condition={globalFilter?.length > 0}
|
||||||
show={
|
show={
|
||||||
<TablePlaceholder>
|
<TablePlaceholder>
|
||||||
No features or projects found matching “
|
No feature toggles found matching “
|
||||||
{globalFilter}
|
{globalFilter}
|
||||||
”
|
”
|
||||||
</TablePlaceholder>
|
</TablePlaceholder>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<TablePlaceholder>
|
<TablePlaceholder>
|
||||||
No features available. Get started by adding a
|
No feature toggles available. Get started by
|
||||||
new feature toggle.
|
adding a new feature toggle.
|
||||||
</TablePlaceholder>
|
</TablePlaceholder>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -45,11 +45,11 @@ export const FeatureMetricsTable = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const hiddenColumns = [];
|
||||||
if (isMediumScreen) {
|
if (isMediumScreen) {
|
||||||
setHiddenColumns(['appName', 'environment']);
|
hiddenColumns.push('appName', 'environment');
|
||||||
} else {
|
|
||||||
setHiddenColumns([]);
|
|
||||||
}
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isMediumScreen]);
|
}, [setHiddenColumns, isMediumScreen]);
|
||||||
|
|
||||||
if (metrics.length === 0) {
|
if (metrics.length === 0) {
|
||||||
@ -98,6 +98,7 @@ const COLUMNS = [
|
|||||||
accessor: 'environment',
|
accessor: 'environment',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 'requested',
|
||||||
Header: 'Requested',
|
Header: 'Requested',
|
||||||
accessor: (original: any) => original.yes + original.no,
|
accessor: (original: any) => original.yes + original.no,
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,6 @@ import * as jsonpatch from 'fast-json-patch';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Box,
|
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
@ -27,7 +26,6 @@ import useDeleteVariantMarkup from './useDeleteVariantMarkup';
|
|||||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { Edit, Delete } from '@mui/icons-material';
|
|
||||||
import { useTable, useSortBy, useGlobalFilter } from 'react-table';
|
import { useTable, useSortBy, useGlobalFilter } from 'react-table';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
@ -35,7 +33,6 @@ import { SortableTableHeader, TablePlaceholder } from 'component/common/Table';
|
|||||||
import { sortTypes } from 'utils/sortTypes';
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
import { PayloadOverridesCell } from './PayloadOverridesCell/PayloadOverridesCell';
|
import { PayloadOverridesCell } from './PayloadOverridesCell/PayloadOverridesCell';
|
||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
|
||||||
import theme from 'themes/theme';
|
import theme from 'themes/theme';
|
||||||
import { VariantsActionCell } from './VariantsActionsCell/VariantsActionsCell';
|
import { VariantsActionCell } from './VariantsActionsCell/VariantsActionsCell';
|
||||||
|
|
||||||
@ -211,11 +208,14 @@ export const FeatureVariantsList = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isMediumScreen) {
|
const hiddenColumns = [];
|
||||||
setHiddenColumns(['weightType', 'data']);
|
if (isLargeScreen) {
|
||||||
} else if (isLargeScreen) {
|
hiddenColumns.push('weightType');
|
||||||
setHiddenColumns(['weightType']);
|
|
||||||
}
|
}
|
||||||
|
if (isMediumScreen) {
|
||||||
|
hiddenColumns.push('data');
|
||||||
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isMediumScreen, isLargeScreen]);
|
}, [setHiddenColumns, isMediumScreen, isLargeScreen]);
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
|
@ -8,8 +8,7 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
},
|
},
|
||||||
menuContainer: {
|
menuContainer: {
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
padding: theme.spacing(1),
|
padding: theme.spacing(1, 1.5),
|
||||||
paddingRight: theme.spacing(3),
|
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
borderRadius: theme.shape.borderRadius,
|
borderRadius: theme.shape.borderRadius,
|
||||||
|
@ -121,6 +121,7 @@ export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
|
|||||||
aria-expanded={isOpen ? 'true' : undefined}
|
aria-expanded={isOpen ? 'true' : undefined}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
type="button"
|
type="button"
|
||||||
|
size="large"
|
||||||
className={classes.button}
|
className={classes.button}
|
||||||
data-loading
|
data-loading
|
||||||
>
|
>
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
useFlexLayout,
|
useFlexLayout,
|
||||||
useSortBy,
|
useSortBy,
|
||||||
useTable,
|
useTable,
|
||||||
|
SortingRule,
|
||||||
} from 'react-table';
|
} from 'react-table';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
@ -68,6 +69,13 @@ type ListItemType = Pick<
|
|||||||
|
|
||||||
const staticColumns = ['Actions', 'name'];
|
const staticColumns = ['Actions', 'name'];
|
||||||
|
|
||||||
|
const defaultSort: SortingRule<string> & {
|
||||||
|
columns?: string[];
|
||||||
|
} = {
|
||||||
|
id: 'createdAt',
|
||||||
|
desc: true,
|
||||||
|
};
|
||||||
|
|
||||||
export const ProjectFeatureToggles = ({
|
export const ProjectFeatureToggles = ({
|
||||||
features,
|
features,
|
||||||
loading,
|
loading,
|
||||||
@ -205,7 +213,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
maxWidth: 80,
|
maxWidth: 80,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Feature toggle name',
|
Header: 'Name',
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
Cell: ({ value }: { value: string }) => (
|
Cell: ({ value }: { value: string }) => (
|
||||||
<LinkCell
|
<LinkCell
|
||||||
@ -268,9 +276,10 @@ export const ProjectFeatureToggles = ({
|
|||||||
[projectId, environments, onToggle, loading]
|
[projectId, environments, onToggle, loading]
|
||||||
);
|
);
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const [storedParams, setStoredParams] = useLocalStorage<{
|
const [storedParams, setStoredParams] = useLocalStorage(
|
||||||
columns?: string[];
|
`${projectId}:ProjectFeatureToggles`,
|
||||||
}>(`${projectId}:ProjectFeatureToggles`, {});
|
defaultSort
|
||||||
|
);
|
||||||
|
|
||||||
const initialState = useMemo(
|
const initialState = useMemo(
|
||||||
() => {
|
() => {
|
||||||
@ -304,7 +313,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
id: searchParams.get('sort') || 'createdAt',
|
id: searchParams.get('sort') || 'createdAt',
|
||||||
desc: searchParams.has('order')
|
desc: searchParams.has('order')
|
||||||
? searchParams.get('order') === 'desc'
|
? searchParams.get('order') === 'desc'
|
||||||
: false,
|
: storedParams.desc,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
hiddenColumns,
|
hiddenColumns,
|
||||||
@ -365,14 +374,20 @@ export const ProjectFeatureToggles = ({
|
|||||||
setSearchParams(tableState, {
|
setSearchParams(tableState, {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
|
setStoredParams({
|
||||||
|
id: sortBy[0].id,
|
||||||
|
desc: sortBy[0].desc || false,
|
||||||
|
columns: tableState.columns.split(','),
|
||||||
|
});
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [loading, sortBy, hiddenColumns, globalFilter, setSearchParams]);
|
}, [loading, sortBy, hiddenColumns, globalFilter, setSearchParams]);
|
||||||
|
|
||||||
const onCustomizeColumns = useCallback(
|
const onCustomizeColumns = useCallback(
|
||||||
visibleColumns => {
|
visibleColumns => {
|
||||||
setStoredParams({
|
setStoredParams(storedParams => ({
|
||||||
|
...storedParams,
|
||||||
columns: visibleColumns,
|
columns: visibleColumns,
|
||||||
});
|
}));
|
||||||
},
|
},
|
||||||
[setStoredParams]
|
[setStoredParams]
|
||||||
);
|
);
|
||||||
@ -490,15 +505,15 @@ export const ProjectFeatureToggles = ({
|
|||||||
condition={globalFilter?.length > 0}
|
condition={globalFilter?.length > 0}
|
||||||
show={
|
show={
|
||||||
<TablePlaceholder>
|
<TablePlaceholder>
|
||||||
No features found matching “
|
No feature toggles found matching “
|
||||||
{globalFilter}
|
{globalFilter}
|
||||||
”
|
”
|
||||||
</TablePlaceholder>
|
</TablePlaceholder>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<TablePlaceholder>
|
<TablePlaceholder>
|
||||||
No features available. Get started by adding a
|
No feature toggles available. Get started by
|
||||||
new feature toggle.
|
adding a new feature toggle.
|
||||||
</TablePlaceholder>
|
</TablePlaceholder>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -68,10 +68,10 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
fontSize: '0.8rem',
|
fontSize: '0.8rem',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
padding: '0.8rem',
|
padding: '0.8rem',
|
||||||
['&:first-of-type']: {
|
'&:first-of-type': {
|
||||||
marginLeft: '0',
|
marginLeft: '0',
|
||||||
},
|
},
|
||||||
['&:last-of-type']: {
|
'&:last-of-type': {
|
||||||
marginRight: '0',
|
marginRight: '0',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useMemo, useState, VFC } from 'react';
|
import { useMemo, VFC } from 'react';
|
||||||
import { useSortBy, useTable } from 'react-table';
|
import { useSortBy, useTable } from 'react-table';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@ -19,6 +19,10 @@ import PermissionIconButton from 'component/common/PermissionIconButton/Permissi
|
|||||||
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
|
||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
sortBy: [{ id: 'name' }],
|
||||||
|
};
|
||||||
|
|
||||||
interface IProjectAccessTableProps {
|
interface IProjectAccessTableProps {
|
||||||
access: IProjectAccessOutput;
|
access: IProjectAccessOutput;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -34,7 +38,6 @@ export const ProjectAccessTable: VFC<IProjectAccessTableProps> = ({
|
|||||||
handleRoleChange,
|
handleRoleChange,
|
||||||
handleRemoveAccess,
|
handleRemoveAccess,
|
||||||
}) => {
|
}) => {
|
||||||
const [initialState] = useState({});
|
|
||||||
const data = access.users;
|
const data = access.users;
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
@ -54,12 +57,13 @@ export const ProjectAccessTable: VFC<IProjectAccessTableProps> = ({
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 'name',
|
||||||
Header: 'Name',
|
Header: 'Name',
|
||||||
accessor: 'name',
|
accessor: (row: any) => row.name || '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Username',
|
|
||||||
id: 'username',
|
id: 'username',
|
||||||
|
Header: 'Username',
|
||||||
accessor: 'email',
|
accessor: 'email',
|
||||||
Cell: ({ row: { original: user } }: any) => (
|
Cell: ({ row: { original: user } }: any) => (
|
||||||
<TextCell>{user.email || user.username}</TextCell>
|
<TextCell>{user.email || user.username}</TextCell>
|
||||||
@ -84,8 +88,8 @@ export const ProjectAccessTable: VFC<IProjectAccessTableProps> = ({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Actions',
|
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
|
Header: 'Actions',
|
||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 80,
|
width: 80,
|
||||||
|
@ -70,10 +70,12 @@ export const ProjectCard = ({
|
|||||||
<PermissionIconButton
|
<PermissionIconButton
|
||||||
permission={UPDATE_PROJECT}
|
permission={UPDATE_PROJECT}
|
||||||
projectId={id}
|
projectId={id}
|
||||||
className={classes.actionsBtn}
|
|
||||||
data-loading
|
data-loading
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
tooltipProps={{ title: 'Options' }}
|
tooltipProps={{
|
||||||
|
title: 'Options',
|
||||||
|
className: classes.actionsBtn,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<MoreVertIcon />
|
<MoreVertIcon />
|
||||||
</PermissionIconButton>
|
</PermissionIconButton>
|
||||||
|
@ -73,11 +73,11 @@ export const SegmentTable = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const hiddenColumns = ['description'];
|
||||||
if (isSmallScreen) {
|
if (isSmallScreen) {
|
||||||
setHiddenColumns(['description', 'createdAt', 'createdBy']);
|
hiddenColumns.push('createdAt', 'createdBy');
|
||||||
} else {
|
|
||||||
setHiddenColumns(['description']);
|
|
||||||
}
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
}, [setHiddenColumns, isSmallScreen]);
|
}, [setHiddenColumns, isSmallScreen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -307,6 +307,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-1"
|
id="useId-1"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -357,6 +358,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-2"
|
id="useId-2"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -477,6 +479,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-3"
|
id="useId-3"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -527,6 +530,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-4"
|
id="useId-4"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -647,6 +651,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-5"
|
id="useId-5"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -697,6 +702,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-6"
|
id="useId-6"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -817,6 +823,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-7"
|
id="useId-7"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -867,6 +874,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-8"
|
id="useId-8"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -987,6 +995,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-9"
|
id="useId-9"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
@ -1037,6 +1046,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
data-mui-internal-clone-element={true}
|
data-mui-internal-clone-element={true}
|
||||||
id="useId-10"
|
id="useId-10"
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onMouseLeave={[Function]}
|
||||||
onMouseOver={[Function]}
|
onMouseOver={[Function]}
|
||||||
|
@ -67,7 +67,7 @@ export default createTheme({
|
|||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
light: colors.green[50],
|
light: colors.green[50],
|
||||||
main: colors.green[500],
|
main: colors.green[600],
|
||||||
dark: colors.green[800],
|
dark: colors.green[800],
|
||||||
border: colors.green[300],
|
border: colors.green[300],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user