mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
fix: make toggle list sortable inside a project (#436)
* fix: make toggle list sortable inside a project * fix: minor cleanup
This commit is contained in:
parent
4230fc98ed
commit
d42d412bc8
@ -37,6 +37,14 @@ const PaginateUI = ({
|
|||||||
}
|
}
|
||||||
}, [matches]);
|
}, [matches]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(pageIndex === 0 && start !== 0) {
|
||||||
|
setStart(0);
|
||||||
|
setLimit(STARTLIMIT);
|
||||||
|
}
|
||||||
|
}, [pageIndex, start])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={pages.length > 1}
|
condition={pages.length > 1}
|
||||||
|
@ -2,9 +2,8 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { MenuItem, Typography } from '@material-ui/core';
|
import { MenuItem, Typography } from '@material-ui/core';
|
||||||
import { HourglassEmpty, HourglassFull } from '@material-ui/icons';
|
// import { HourglassEmpty, HourglassFull } from '@material-ui/icons';
|
||||||
|
// import { MenuItemWithIcon } from '../../../common';
|
||||||
import { MenuItemWithIcon } from '../../../common';
|
|
||||||
import DropdownMenu from '../../../common/DropdownMenu/DropdownMenu';
|
import DropdownMenu from '../../../common/DropdownMenu/DropdownMenu';
|
||||||
import ProjectSelect from '../../../common/ProjectSelect';
|
import ProjectSelect from '../../../common/ProjectSelect';
|
||||||
import { useStyles } from './styles';
|
import { useStyles } from './styles';
|
||||||
@ -53,6 +52,7 @@ const FeatureToggleListActions = ({
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
/*
|
||||||
const renderMetricsOptions = () => [
|
const renderMetricsOptions = () => [
|
||||||
<MenuItemWithIcon
|
<MenuItemWithIcon
|
||||||
style={{ fontSize: '14px' }}
|
style={{ fontSize: '14px' }}
|
||||||
@ -71,12 +71,14 @@ const FeatureToggleListActions = ({
|
|||||||
key={2}
|
key={2}
|
||||||
/>,
|
/>,
|
||||||
];
|
];
|
||||||
|
*/
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.actions} ref={ref}>
|
<div className={styles.actions} ref={ref}>
|
||||||
<Typography variant="body2" data-loading>
|
<Typography variant="body2" data-loading>
|
||||||
Sorted by:
|
Sorted by:
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{/* }
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
id={'metric'}
|
id={'metric'}
|
||||||
label={`Last ${settings.showLastHour ? 'hour' : 'minute'}`}
|
label={`Last ${settings.showLastHour ? 'hour' : 'minute'}`}
|
||||||
@ -87,6 +89,7 @@ const FeatureToggleListActions = ({
|
|||||||
style={{ textTransform: 'lowercase', fontWeight: 'normal' }}
|
style={{ textTransform: 'lowercase', fontWeight: 'normal' }}
|
||||||
data-loading
|
data-loading
|
||||||
/>
|
/>
|
||||||
|
{*/}
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
id={'sorting'}
|
id={'sorting'}
|
||||||
label={`By ${settings.sort}`}
|
label={`By ${settings.sort}`}
|
||||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Chip, IconButton, ListItem } from '@material-ui/core';
|
import { Chip, IconButton, ListItem, Tooltip } from '@material-ui/core';
|
||||||
import { Undo } from '@material-ui/icons';
|
import { Undo } from '@material-ui/icons';
|
||||||
|
|
||||||
import TimeAgo from 'react-timeago';
|
import TimeAgo from 'react-timeago';
|
||||||
@ -58,9 +58,11 @@ const FeatureToggleListItem = ({
|
|||||||
commonStyles.truncate
|
commonStyles.truncate
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className={commonStyles.toggleName}>
|
<Tooltip title={description}>
|
||||||
{name}
|
<span className={commonStyles.toggleName}>
|
||||||
</span>
|
{name}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
<span className={styles.listItemToggle}>
|
<span className={styles.listItemToggle}>
|
||||||
</span>
|
</span>
|
||||||
<small>
|
<small>
|
||||||
@ -74,9 +76,11 @@ const FeatureToggleListItem = ({
|
|||||||
</Link>
|
</Link>
|
||||||
} elseShow={
|
} elseShow={
|
||||||
<>
|
<>
|
||||||
<span className={commonStyles.toggleName}>
|
<Tooltip title={description}>
|
||||||
{name}
|
<span className={commonStyles.toggleName}>
|
||||||
</span>
|
{name}
|
||||||
|
z </span>
|
||||||
|
</Tooltip>
|
||||||
<span className={styles.listItemToggle}>
|
<span className={styles.listItemToggle}>
|
||||||
</span>
|
</span>
|
||||||
<small>
|
<small>
|
||||||
@ -100,7 +104,9 @@ const FeatureToggleListItem = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Status stale={stale} showActive={false} />
|
<Status stale={stale} showActive={false} />
|
||||||
<Chip color="primary" variant="outlined" className={styles.typeChip} style={{marginLeft: '8px'}} title={`Project: ${project}`} label={project}/>
|
<Link to={`/projects/${project}`} style={{textDecoration: 'none'}}>
|
||||||
|
<Chip color="primary" variant="outlined" className={styles.typeChip} style={{marginLeft: '8px' }} title={`Project: ${project}`} label={project}/>
|
||||||
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={revive}
|
condition={revive}
|
||||||
|
@ -13,12 +13,14 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
listItemType: {
|
listItemType: {
|
||||||
width: '40px',
|
width: '40px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
marginRight: '0',
|
||||||
|
flexShrink: '0',
|
||||||
},
|
},
|
||||||
listItemSvg: {
|
listItemSvg: {
|
||||||
fill: theme.palette.icons.lightGrey,
|
fill: theme.palette.icons.lightGrey,
|
||||||
},
|
},
|
||||||
listItemLink: {
|
listItemLink: {
|
||||||
marginLeft: '10px',
|
marginLeft: '0.25rem',
|
||||||
minWidth: '0',
|
minWidth: '0',
|
||||||
},
|
},
|
||||||
listItemStrategies: {
|
listItemStrategies: {
|
||||||
|
@ -23,7 +23,7 @@ exports[`renders correctly with one feature 1`] = `
|
|||||||
"fontSize": "0.8rem",
|
"fontSize": "0.8rem",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title="No usage reported"
|
title="No usage reported from connected applications"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style={
|
style={
|
||||||
@ -68,7 +68,15 @@ exports[`renders correctly with one feature 1`] = `
|
|||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
aria-describedby={null}
|
||||||
className="toggleName"
|
className="toggleName"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="another's description"
|
||||||
>
|
>
|
||||||
Another
|
Another
|
||||||
|
|
||||||
@ -96,23 +104,33 @@ exports[`renders correctly with one feature 1`] = `
|
|||||||
<span
|
<span
|
||||||
className="makeStyles-listItemStrategies-6 hideLt920"
|
className="makeStyles-listItemStrategies-6 hideLt920"
|
||||||
>
|
>
|
||||||
<div
|
<a
|
||||||
className="MuiChip-root MuiChip-colorPrimary MuiChip-outlined MuiChip-outlinedPrimary"
|
href="/projects/default"
|
||||||
onKeyDown={[Function]}
|
onClick={[Function]}
|
||||||
onKeyUp={[Function]}
|
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"marginLeft": "8px",
|
"textDecoration": "none",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title="Project: default"
|
|
||||||
>
|
>
|
||||||
<span
|
<div
|
||||||
className="MuiChip-label"
|
className="MuiChip-root MuiChip-colorPrimary MuiChip-outlined MuiChip-outlinedPrimary"
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"marginLeft": "8px",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
title="Project: default"
|
||||||
>
|
>
|
||||||
default
|
<span
|
||||||
</span>
|
className="MuiChip-label"
|
||||||
</div>
|
>
|
||||||
|
default
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
@ -140,7 +158,7 @@ exports[`renders correctly with one feature without permission 1`] = `
|
|||||||
"fontSize": "0.8rem",
|
"fontSize": "0.8rem",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title="No usage reported"
|
title="No usage reported from connected applications"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style={
|
style={
|
||||||
@ -185,7 +203,15 @@ exports[`renders correctly with one feature without permission 1`] = `
|
|||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
aria-describedby={null}
|
||||||
className="toggleName"
|
className="toggleName"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="another's description"
|
||||||
>
|
>
|
||||||
Another
|
Another
|
||||||
|
|
||||||
@ -213,21 +239,31 @@ exports[`renders correctly with one feature without permission 1`] = `
|
|||||||
<span
|
<span
|
||||||
className="makeStyles-listItemStrategies-6 hideLt920"
|
className="makeStyles-listItemStrategies-6 hideLt920"
|
||||||
>
|
>
|
||||||
<div
|
<a
|
||||||
className="MuiChip-root MuiChip-colorPrimary MuiChip-outlined MuiChip-outlinedPrimary"
|
href="/projects/undefined"
|
||||||
onKeyDown={[Function]}
|
onClick={[Function]}
|
||||||
onKeyUp={[Function]}
|
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"marginLeft": "8px",
|
"textDecoration": "none",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title="Project: undefined"
|
|
||||||
>
|
>
|
||||||
<span
|
<div
|
||||||
className="MuiChip-label"
|
className="MuiChip-root MuiChip-colorPrimary MuiChip-outlined MuiChip-outlinedPrimary"
|
||||||
/>
|
onKeyDown={[Function]}
|
||||||
</div>
|
onKeyUp={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"marginLeft": "8px",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
title="Project: undefined"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="MuiChip-label"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
|
@ -85,60 +85,6 @@ exports[`renders correctly with one feature 1`] = `
|
|||||||
>
|
>
|
||||||
Sorted by:
|
Sorted by:
|
||||||
</p>
|
</p>
|
||||||
<button
|
|
||||||
aria-controls="metric"
|
|
||||||
aria-haspopup="true"
|
|
||||||
className="MuiButtonBase-root MuiButton-root MuiButton-text"
|
|
||||||
data-loading={true}
|
|
||||||
disabled={false}
|
|
||||||
id="metric"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"fontWeight": "normal",
|
|
||||||
"textTransform": "lowercase",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tabIndex={0}
|
|
||||||
title="Metric interval"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiButton-label"
|
|
||||||
>
|
|
||||||
Last minute
|
|
||||||
<span
|
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-hidden={true}
|
|
||||||
className="material-icons MuiIcon-root"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M7 10l5 5 5-5z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
aria-controls="sorting"
|
aria-controls="sorting"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
@ -336,63 +282,6 @@ exports[`renders correctly with one feature without permissions 1`] = `
|
|||||||
>
|
>
|
||||||
Sorted by:
|
Sorted by:
|
||||||
</p>
|
</p>
|
||||||
<button
|
|
||||||
aria-controls="metric"
|
|
||||||
aria-haspopup="true"
|
|
||||||
className="MuiButtonBase-root MuiButton-root MuiButton-text"
|
|
||||||
data-loading={true}
|
|
||||||
disabled={false}
|
|
||||||
id="metric"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"fontWeight": "normal",
|
|
||||||
"textTransform": "lowercase",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tabIndex={0}
|
|
||||||
title="Metric interval"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiButton-label"
|
|
||||||
>
|
|
||||||
Last minute
|
|
||||||
<span
|
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-hidden={true}
|
|
||||||
className="material-icons MuiIcon-root"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M7 10l5 5 5-5z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="MuiTouchRipple-root"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
aria-controls="sorting"
|
aria-controls="sorting"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
|
@ -14,6 +14,9 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
color: theme.palette.grey[600],
|
color: theme.palette.grey[600],
|
||||||
borderBottom: '1px solid ' + theme.palette.grey[200],
|
borderBottom: '1px solid ' + theme.palette.grey[200],
|
||||||
},
|
},
|
||||||
|
tableCellHeaderSortable: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
tableCellStatus: {
|
tableCellStatus: {
|
||||||
width: '50px',
|
width: '50px',
|
||||||
},
|
},
|
||||||
@ -26,6 +29,11 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
tableCellCreated: {
|
||||||
|
[theme.breakpoints.down('sm')]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
tableCellType: {
|
tableCellType: {
|
||||||
width: '32px',
|
width: '32px',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -22,14 +23,86 @@ interface IFeatureToggleListNewProps {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
const sortList = (list, sortOpt) => {
|
||||||
|
if(!list) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
if(!sortOpt.field) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
if (sortOpt.type === 'string') {
|
||||||
|
//@ts-ignore
|
||||||
|
return list.sort((a, b) => {
|
||||||
|
const fieldA = a[sortOpt.field]?.toUpperCase();
|
||||||
|
const fieldB = b[sortOpt.field]?.toUpperCase();
|
||||||
|
const direction = sortOpt.direction;
|
||||||
|
|
||||||
|
if (fieldA < fieldB) {
|
||||||
|
return direction === 0 ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (fieldA > fieldB) {
|
||||||
|
return direction === 0 ? 1 : -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (sortOpt.type === 'date') {
|
||||||
|
//@ts-ignore
|
||||||
|
return list.sort((a, b) => {
|
||||||
|
const fieldA = new Date(a[sortOpt.field]);
|
||||||
|
const fieldB = new Date(b[sortOpt.field]);
|
||||||
|
|
||||||
|
if (fieldA < fieldB) {
|
||||||
|
return sortOpt.direction === 0 ? 1 : -1;
|
||||||
|
}
|
||||||
|
if (fieldA > fieldB) {
|
||||||
|
return sortOpt.direction === 0 ? -1 : 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
const FeatureToggleListNew = ({
|
const FeatureToggleListNew = ({
|
||||||
features,
|
features,
|
||||||
loading,
|
loading,
|
||||||
projectId,
|
projectId,
|
||||||
}: IFeatureToggleListNewProps) => {
|
}: IFeatureToggleListNewProps) => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
const [sortOpt, setSortOpt] = useState({
|
||||||
|
field: 'name',
|
||||||
|
type: 'string',
|
||||||
|
direction: 0,
|
||||||
|
});
|
||||||
|
const [sortedFeatures, setSortedFeatures] = useState(sortList([...features], sortOpt));
|
||||||
|
|
||||||
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
|
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
|
||||||
usePagination(features, 50);
|
usePagination(sortedFeatures, 50);
|
||||||
|
|
||||||
|
const updateSort = (field: string) => {
|
||||||
|
let newSortOpt;
|
||||||
|
if(field === sortOpt.field) {
|
||||||
|
newSortOpt = {...sortOpt, direction: (sortOpt.direction + 1) % 2};
|
||||||
|
}
|
||||||
|
else if(['createdAt', 'lastSeenAt'].includes(field)) {
|
||||||
|
newSortOpt = {
|
||||||
|
field,
|
||||||
|
type: 'date',
|
||||||
|
direction: 0
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
newSortOpt = {
|
||||||
|
field,
|
||||||
|
type: 'string',
|
||||||
|
direction: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
setSortOpt(newSortOpt);
|
||||||
|
setSortedFeatures(sortList([...features], newSortOpt));
|
||||||
|
setPageIndex(0);
|
||||||
|
};
|
||||||
|
|
||||||
const getEnvironments = () => {
|
const getEnvironments = () => {
|
||||||
if (features.length > 0) {
|
if (features.length > 0) {
|
||||||
@ -55,6 +128,7 @@ const FeatureToggleListNew = ({
|
|||||||
type={feature.type}
|
type={feature.type}
|
||||||
environments={feature.environments}
|
environments={feature.environments}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
|
createdAt={new Date()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -69,6 +143,7 @@ const FeatureToggleListNew = ({
|
|||||||
environments={feature.environments}
|
environments={feature.environments}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
lastSeenAt={feature.lastSeenAt}
|
lastSeenAt={feature.lastSeenAt}
|
||||||
|
createdAt={feature.createdAt}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -83,31 +158,45 @@ const FeatureToggleListNew = ({
|
|||||||
className={classnames(
|
className={classnames(
|
||||||
styles.tableCell,
|
styles.tableCell,
|
||||||
styles.tableCellStatus,
|
styles.tableCellStatus,
|
||||||
styles.tableCellHeader
|
styles.tableCellHeader,
|
||||||
|
styles.tableCellHeaderSortable,
|
||||||
)}
|
)}
|
||||||
align="left"
|
align="left"
|
||||||
>
|
>
|
||||||
<span data-loading>Status</span>
|
<span data-loading onClick={() => updateSort('lastSeenAt')}>Status</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
<TableCell
|
||||||
className={classnames(
|
className={classnames(
|
||||||
styles.tableCell,
|
styles.tableCell,
|
||||||
styles.tableCellType,
|
styles.tableCellType,
|
||||||
styles.tableCellHeader
|
styles.tableCellHeader,
|
||||||
|
styles.tableCellHeaderSortable,
|
||||||
)}
|
)}
|
||||||
align="center"
|
align="center"
|
||||||
>
|
>
|
||||||
<span data-loading>Type</span>
|
<span data-loading onClick={() => updateSort('type')}>Type</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
<TableCell
|
||||||
className={classnames(
|
className={classnames(
|
||||||
styles.tableCell,
|
styles.tableCell,
|
||||||
styles.tableCellName,
|
styles.tableCellName,
|
||||||
styles.tableCellHeader
|
styles.tableCellHeader,
|
||||||
|
styles.tableCellHeaderSortable,
|
||||||
)}
|
)}
|
||||||
align="left"
|
align="left"
|
||||||
>
|
>
|
||||||
<span data-loading>Name</span>
|
<span data-loading onClick={() => updateSort('name')}>Name</span>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell
|
||||||
|
className={classnames(
|
||||||
|
styles.tableCell,
|
||||||
|
styles.tableCellCreated,
|
||||||
|
styles.tableCellHeader,
|
||||||
|
styles.tableCellHeaderSortable,
|
||||||
|
)}
|
||||||
|
align="left"
|
||||||
|
>
|
||||||
|
<span data-loading onClick={() => updateSort('createdAt')}>Created</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{getEnvironments().map((env: any) => {
|
{getEnvironments().map((env: any) => {
|
||||||
return (
|
return (
|
||||||
@ -116,7 +205,8 @@ const FeatureToggleListNew = ({
|
|||||||
className={classnames(
|
className={classnames(
|
||||||
styles.tableCell,
|
styles.tableCell,
|
||||||
styles.tableCellEnv,
|
styles.tableCellEnv,
|
||||||
styles.tableCellHeader
|
styles.tableCellHeader,
|
||||||
|
styles.tableCellHeaderSortable,
|
||||||
)}
|
)}
|
||||||
align="center"
|
align="center"
|
||||||
>
|
>
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
import { Tooltip } from '@material-ui/core';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { formatDateWithLocale, formatFullDateTimeWithLocale } from '../../../common/util';
|
||||||
|
|
||||||
|
interface CreatedAtProps {
|
||||||
|
time: Date;
|
||||||
|
//@ts-ignore
|
||||||
|
location: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CreatedAt = ({time, location}: CreatedAtProps) => {
|
||||||
|
return (
|
||||||
|
<Tooltip title={`Created at ${formatFullDateTimeWithLocale(time, location.locale)}`}>
|
||||||
|
<span>
|
||||||
|
{formatDateWithLocale(time, location.locale)}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: any) => ({
|
||||||
|
location: state.settings.toJS().location,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(CreatedAt);
|
@ -16,6 +16,7 @@ import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
import FeatureStatus from '../../FeatureView2/FeatureStatus/FeatureStatus';
|
import FeatureStatus from '../../FeatureView2/FeatureStatus/FeatureStatus';
|
||||||
import FeatureType from '../../FeatureView2/FeatureType/FeatureType';
|
import FeatureType from '../../FeatureView2/FeatureType/FeatureType';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import CreatedAt from './CreatedAt';
|
||||||
|
|
||||||
interface IFeatureToggleListNewItemProps {
|
interface IFeatureToggleListNewItemProps {
|
||||||
name: string;
|
name: string;
|
||||||
@ -23,6 +24,7 @@ interface IFeatureToggleListNewItemProps {
|
|||||||
environments: IFeatureEnvironment[];
|
environments: IFeatureEnvironment[];
|
||||||
projectId: string;
|
projectId: string;
|
||||||
lastSeenAt?: Date;
|
lastSeenAt?: Date;
|
||||||
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureToggleListNewItem = ({
|
const FeatureToggleListNewItem = ({
|
||||||
@ -31,6 +33,7 @@ const FeatureToggleListNewItem = ({
|
|||||||
type,
|
type,
|
||||||
environments,
|
environments,
|
||||||
projectId,
|
projectId,
|
||||||
|
createdAt,
|
||||||
}: IFeatureToggleListNewItemProps) => {
|
}: IFeatureToggleListNewItemProps) => {
|
||||||
const { toast, setToastData } = useToast();
|
const { toast, setToastData } = useToast();
|
||||||
const { toggleFeatureByEnvironment } = useToggleFeatureByEnv(
|
const { toggleFeatureByEnvironment } = useToggleFeatureByEnv(
|
||||||
@ -87,6 +90,10 @@ const FeatureToggleListNewItem = ({
|
|||||||
styles.tableCell, styles.tableCellName)} align="left" onClick={onClick}>
|
styles.tableCell, styles.tableCellName)} align="left" onClick={onClick}>
|
||||||
<span data-loading>{name}</span>
|
<span data-loading>{name}</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell className={classNames(
|
||||||
|
styles.tableCell, styles.tableCellCreated)} align="left" onClick={onClick}>
|
||||||
|
<CreatedAt time={createdAt} />
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
|
||||||
{environments.map((env: IEnvironments) => {
|
{environments.map((env: IEnvironments) => {
|
||||||
|
@ -83,7 +83,7 @@ const FeatureStatus = ({ lastSeenAt }: FeatureStatusProps) => {
|
|||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
toolTip={`Last usage reported ${value} ${unit} ${suffix}`}
|
toolTip={`Last usage reported ${value} ${unit}${value !== 1 ? 's' : ''} ${suffix}`}
|
||||||
color={getColor(unit)}
|
color={getColor(unit)}
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
@ -94,7 +94,7 @@ const FeatureStatus = ({ lastSeenAt }: FeatureStatusProps) => {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<Wrapper toolTip="No usage reported" color={getColor()}>
|
<Wrapper toolTip="No usage reported from connected applications" color={getColor()}>
|
||||||
<span style={{ fontSize: '1.4rem' }}>⊕</span>
|
<span style={{ fontSize: '1.4rem' }}>⊕</span>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
width: 'inherit',
|
width: 'inherit',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bodyClass: { padding: '0.5rem 2rem' },
|
bodyClass: { padding: '0.5rem 1rem' },
|
||||||
header: {
|
header: {
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
},
|
},
|
||||||
|
@ -14,8 +14,8 @@ export interface IEnvironments {
|
|||||||
export interface IFeatureToggle {
|
export interface IFeatureToggle {
|
||||||
stale: boolean;
|
stale: boolean;
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
lastSeenAt: Date;
|
lastSeenAt?: Date;
|
||||||
description: string;
|
description: string;
|
||||||
environments: IFeatureEnvironment[];
|
environments: IFeatureEnvironment[];
|
||||||
name: string;
|
name: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user