mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-17 01:17:29 +02:00
Merge branch 'master' into react_16
This commit is contained in:
commit
c18ad66bb2
@ -7,9 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
The latest version of this document is always available in
|
The latest version of this document is always available in
|
||||||
[releases][releases-url].
|
[releases][releases-url].
|
||||||
|
|
||||||
|
|
||||||
## [Unrelesed]
|
## [Unrelesed]
|
||||||
- fix(package): Upgrade react to version 16.2.0
|
- fix(package): Upgrade react to version 16.2.0
|
||||||
|
|
||||||
|
## [3.0.0]
|
||||||
|
- Nothing new, just locking down the version.
|
||||||
|
|
||||||
## [3.0.0-alpha.8]
|
## [3.0.0-alpha.8]
|
||||||
- feat(timestamps): Make formatting of timestamps configurable.
|
- feat(timestamps): Make formatting of timestamps configurable.
|
||||||
- fix(package): Update react-mdl to version 1.11.0
|
- fix(package): Update react-mdl to version 1.11.0
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "unleash-frontend",
|
"name": "unleash-frontend",
|
||||||
"description": "unleash your features",
|
"description": "unleash your features",
|
||||||
"version": "3.0.0-alpha.8",
|
"version": "3.0.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"unleash",
|
"unleash",
|
||||||
"feature toggle",
|
"feature toggle",
|
||||||
|
2
frontend/src/__mocks__/react-mdl.js
vendored
2
frontend/src/__mocks__/react-mdl.js
vendored
@ -5,12 +5,14 @@ module.exports = {
|
|||||||
CardMenu: 'react-mdl-CardMenu',
|
CardMenu: 'react-mdl-CardMenu',
|
||||||
DataTable: 'react-mdl-DataTable',
|
DataTable: 'react-mdl-DataTable',
|
||||||
Cell: 'react-mdl-Cell',
|
Cell: 'react-mdl-Cell',
|
||||||
|
Chip: 'react-mdl-Chip',
|
||||||
Grid: 'react-mdl-Grid',
|
Grid: 'react-mdl-Grid',
|
||||||
Icon: 'react-mdl-Icon',
|
Icon: 'react-mdl-Icon',
|
||||||
IconButton: 'react-mdl-IconButton',
|
IconButton: 'react-mdl-IconButton',
|
||||||
List: 'react-mdl-List',
|
List: 'react-mdl-List',
|
||||||
ListItem: 'react-mdl-ListItem',
|
ListItem: 'react-mdl-ListItem',
|
||||||
ListItemContent: 'react-mdl-ListItemContent',
|
ListItemContent: 'react-mdl-ListItemContent',
|
||||||
|
ListItemAction: 'react-mdl-ListItemAction',
|
||||||
ProgressBar: 'react-mdl-ProgressBar',
|
ProgressBar: 'react-mdl-ProgressBar',
|
||||||
Switch: 'react-mdl-Switch',
|
Switch: 'react-mdl-Switch',
|
||||||
Tab: 'react-mdl-Tab',
|
Tab: 'react-mdl-Tab',
|
||||||
|
@ -5,81 +5,116 @@ exports[`renders correctly with archived toggles 1`] = `
|
|||||||
className="fullwidth"
|
className="fullwidth"
|
||||||
shadow={0}
|
shadow={0}
|
||||||
>
|
>
|
||||||
<div
|
<div>
|
||||||
className="horisontalScroll"
|
<div
|
||||||
>
|
|
||||||
<react-mdl-DataTable
|
|
||||||
className="fullwidth"
|
|
||||||
rows={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"createdAt": "2016-10-25T15:38:28.573Z",
|
|
||||||
"description": "Disables the confirm-functionality from API",
|
|
||||||
"enabled": false,
|
|
||||||
"name": "adin-pay-confirm-disabled",
|
|
||||||
"reviveName": "adin-pay-confirm-disabled",
|
|
||||||
"strategies": Array [
|
|
||||||
Object {
|
|
||||||
"name": "default",
|
|
||||||
"parameters": Object {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"createdAt": "2016-08-03T12:41:35.631Z",
|
|
||||||
"description": "Enables use of schibsted payment from order-payment-management",
|
|
||||||
"enabled": true,
|
|
||||||
"name": "adin-pay-platform-sch-payment",
|
|
||||||
"reviveName": "adin-pay-platform-sch-payment",
|
|
||||||
"strategies": Array [
|
|
||||||
Object {
|
|
||||||
"name": "default",
|
|
||||||
"parameters": Object {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"border": 0,
|
"position": "relative",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<react-mdl-TableHeader
|
<react-mdl-List>
|
||||||
cellFormatter={[Function]}
|
<react-mdl-ListItem
|
||||||
name="reviveName"
|
className="archiveList"
|
||||||
style={
|
>
|
||||||
Object {
|
<span
|
||||||
"width": "25px",
|
className="listItemToggle"
|
||||||
}
|
>
|
||||||
}
|
Toggle name
|
||||||
>
|
</span>
|
||||||
Revive
|
<span
|
||||||
</react-mdl-TableHeader>
|
className="listItemRevive"
|
||||||
<react-mdl-TableHeader
|
>
|
||||||
cellFormatter={[Function]}
|
Revive
|
||||||
name="enabled"
|
</span>
|
||||||
style={
|
</react-mdl-ListItem>
|
||||||
Object {
|
<hr />
|
||||||
"width": "25px",
|
<react-mdl-List>
|
||||||
}
|
<react-mdl-ListItem
|
||||||
}
|
twoLine={true}
|
||||||
>
|
>
|
||||||
Enabled
|
<react-mdl-ListItemAction>
|
||||||
</react-mdl-TableHeader>
|
<react-mdl-Icon
|
||||||
<react-mdl-TableHeader
|
name="keyboard_arrow_right"
|
||||||
name="name"
|
/>
|
||||||
>
|
</react-mdl-ListItemAction>
|
||||||
Toggle name
|
<react-mdl-ListItemContent>
|
||||||
</react-mdl-TableHeader>
|
<a
|
||||||
<react-mdl-TableHeader
|
className="listLink truncate"
|
||||||
name="createdAt"
|
onClick={[Function]}
|
||||||
numeric={true}
|
style={Object {}}
|
||||||
>
|
>
|
||||||
Created
|
adin-pay-confirm-disabled
|
||||||
</react-mdl-TableHeader>
|
<span>
|
||||||
</react-mdl-DataTable>
|
<span
|
||||||
|
className="strategiesList hideLt920"
|
||||||
|
>
|
||||||
|
<react-mdl-Chip
|
||||||
|
className="strategyChip"
|
||||||
|
>
|
||||||
|
default
|
||||||
|
</react-mdl-Chip>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
className="mdl-list__item-sub-title"
|
||||||
|
>
|
||||||
|
Disables the confirm-functionality from API
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</react-mdl-ListItemContent>
|
||||||
|
<react-mdl-ListItemAction
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<react-mdl-Icon
|
||||||
|
name="undo"
|
||||||
|
/>
|
||||||
|
</react-mdl-ListItemAction>
|
||||||
|
</react-mdl-ListItem>
|
||||||
|
<react-mdl-ListItem
|
||||||
|
twoLine={true}
|
||||||
|
>
|
||||||
|
<react-mdl-ListItemAction>
|
||||||
|
<react-mdl-Icon
|
||||||
|
name="keyboard_arrow_right"
|
||||||
|
/>
|
||||||
|
</react-mdl-ListItemAction>
|
||||||
|
<react-mdl-ListItemContent>
|
||||||
|
<a
|
||||||
|
className="listLink truncate"
|
||||||
|
onClick={[Function]}
|
||||||
|
style={Object {}}
|
||||||
|
>
|
||||||
|
adin-pay-platform-sch-payment
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
className="strategiesList hideLt920"
|
||||||
|
>
|
||||||
|
<react-mdl-Chip
|
||||||
|
className="strategyChip"
|
||||||
|
>
|
||||||
|
default
|
||||||
|
</react-mdl-Chip>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
className="mdl-list__item-sub-title"
|
||||||
|
>
|
||||||
|
Enables use of schibsted payment from order-payment-management
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</react-mdl-ListItemContent>
|
||||||
|
<react-mdl-ListItemAction
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<react-mdl-Icon
|
||||||
|
name="undo"
|
||||||
|
/>
|
||||||
|
</react-mdl-ListItemAction>
|
||||||
|
</react-mdl-ListItem>
|
||||||
|
</react-mdl-List>
|
||||||
|
</react-mdl-List>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</react-mdl-Card>
|
</react-mdl-Card>
|
||||||
`;
|
`;
|
||||||
|
@ -26,12 +26,10 @@ const archive = [
|
|||||||
|
|
||||||
test('renders correctly with no archived toggles', () => {
|
test('renders correctly with no archived toggles', () => {
|
||||||
const tree = renderer.create(<ArchiveList fetchArchive={jest.fn()} archive={[]} />).toJSON();
|
const tree = renderer.create(<ArchiveList fetchArchive={jest.fn()} archive={[]} />).toJSON();
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders correctly with archived toggles', () => {
|
test('renders correctly with archived toggles', () => {
|
||||||
const tree = renderer.create(<ArchiveList fetchArchive={jest.fn()} archive={archive} />).toJSON();
|
const tree = renderer.create(<ArchiveList fetchArchive={jest.fn()} archive={archive} />).toJSON();
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { DataTable, TableHeader, IconButton, Icon, Card } from 'react-mdl';
|
import { Icon, Card, List, ListItem, ListItemContent, ListItemAction, Chip } from 'react-mdl';
|
||||||
import { styles as commonStyles } from '../common';
|
import { styles as commonStyles } from '../common';
|
||||||
|
import styles from './archive.scss';
|
||||||
|
|
||||||
class ArchiveList extends Component {
|
class ArchiveList extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
name: PropTypes.string,
|
||||||
archive: PropTypes.array,
|
archive: PropTypes.array,
|
||||||
fetchArchive: PropTypes.func,
|
fetchArchive: PropTypes.func,
|
||||||
revive: PropTypes.func,
|
revive: PropTypes.func,
|
||||||
@ -14,7 +16,44 @@ class ArchiveList extends Component {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.fetchArchive();
|
this.props.fetchArchive();
|
||||||
}
|
}
|
||||||
|
renderStrategyDetail(feature) {
|
||||||
|
let strategiesList = (
|
||||||
|
<span>
|
||||||
|
{feature.strategies.map((s, i) => (
|
||||||
|
<span style={{ marginLeft: `8px` }} key={i}>
|
||||||
|
<strong>{s.name}</strong>
|
||||||
|
{Object.keys(s.parameters).map((p, j) => <i key={j}> {s.parameters[p]}</i>)}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
return strategiesList;
|
||||||
|
}
|
||||||
|
renderStrategiesInList(feature) {
|
||||||
|
let display = [];
|
||||||
|
if (feature.strategies && feature.strategies.length > 0) {
|
||||||
|
const strategiesToShow = Math.min(feature.strategies.length, 3);
|
||||||
|
const remainingStrategies = feature.strategies.length - strategiesToShow;
|
||||||
|
|
||||||
|
const strategyChips =
|
||||||
|
feature.strategies &&
|
||||||
|
feature.strategies.slice(0, strategiesToShow).map((s, i) => (
|
||||||
|
<span key={i} className={[styles.strategiesList, commonStyles.hideLt920].join(' ')}>
|
||||||
|
<Chip className={styles.strategyChip}>{s.name}</Chip>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
const remaining = (
|
||||||
|
<span className={[styles.strategiesList, commonStyles.hideLt920].join(' ')}>
|
||||||
|
<Chip className={styles.strategyChip}>+{remainingStrategies}</Chip>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
if (remainingStrategies > 0) {
|
||||||
|
display.push(remaining);
|
||||||
|
}
|
||||||
|
display.push(strategyChips);
|
||||||
|
}
|
||||||
|
return display;
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const { archive, revive } = this.props;
|
const { archive, revive } = this.props;
|
||||||
archive.forEach(e => {
|
archive.forEach(e => {
|
||||||
@ -22,30 +61,72 @@ class ArchiveList extends Component {
|
|||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<Card shadow={0} className={commonStyles.fullwidth}>
|
<Card shadow={0} className={commonStyles.fullwidth}>
|
||||||
{archive.length > 0 ? (
|
{archive && archive.length > 0 ? (
|
||||||
<div className={commonStyles.horisontalScroll}>
|
<div>
|
||||||
<DataTable rows={archive} className={commonStyles.fullwidth} style={{ border: 0 }}>
|
<div style={{ position: 'relative' }}>
|
||||||
<TableHeader
|
<List>
|
||||||
style={{ width: '25px' }}
|
<ListItem className={styles.archiveList}>
|
||||||
name="reviveName"
|
<span className={styles.listItemToggle}>Toggle name</span>
|
||||||
cellFormatter={reviveName => (
|
<span className={styles.listItemRevive}>Revive</span>
|
||||||
<IconButton colored name="undo" onClick={() => revive(reviveName)} />
|
</ListItem>
|
||||||
)}
|
<hr />
|
||||||
>
|
<List>
|
||||||
Revive
|
{archive.map((feature, i) => (
|
||||||
</TableHeader>
|
<ListItem key={i} twoLine>
|
||||||
<TableHeader
|
<ListItemAction>
|
||||||
style={{ width: '25px' }}
|
{this.props.name && feature.name === this.props.name ? (
|
||||||
name="enabled"
|
<Icon name="keyboard_arrow_down" />
|
||||||
cellFormatter={v => (v ? 'Yes' : '-')}
|
) : (
|
||||||
>
|
<Icon name="keyboard_arrow_right" />
|
||||||
Enabled
|
)}
|
||||||
</TableHeader>
|
</ListItemAction>
|
||||||
<TableHeader name="name">Toggle name</TableHeader>
|
<ListItemContent>
|
||||||
<TableHeader numeric name="createdAt">
|
{this.props.name && feature.name === this.props.name ? (
|
||||||
Created
|
<Link
|
||||||
</TableHeader>
|
to={`/archive`}
|
||||||
</DataTable>
|
className={[commonStyles.listLink, commonStyles.truncate].join(
|
||||||
|
' '
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{this.renderStrategiesInList(feature).map((strategyChip, i) => (
|
||||||
|
<span key={i}>{strategyChip}</span>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{feature.name}
|
||||||
|
<div className={'mdl-list__item-sub-title'}>
|
||||||
|
{feature.description}
|
||||||
|
</div>
|
||||||
|
<div className={'mdl-list__item-sub-title'}>
|
||||||
|
{this.renderStrategyDetail(feature)}
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Link
|
||||||
|
to={`/archive/${feature.name}`}
|
||||||
|
className={[commonStyles.listLink, commonStyles.truncate].join(
|
||||||
|
' '
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{feature.name}
|
||||||
|
|
||||||
|
{this.renderStrategiesInList(feature).map((strategyChip, i) => (
|
||||||
|
<span key={i}>{strategyChip}</span>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<div className={'mdl-list__item-sub-title'}>
|
||||||
|
{feature.description}
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</ListItemContent>
|
||||||
|
<ListItemAction onClick={() => revive(feature.name)}>
|
||||||
|
<Icon name="undo" />
|
||||||
|
</ListItemAction>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={commonStyles.emptyState}>
|
<div className={commonStyles.emptyState}>
|
||||||
|
40
frontend/src/component/archive/archive.scss
Normal file
40
frontend/src/component/archive/archive.scss
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
.archiveList {
|
||||||
|
background-color: #fff;
|
||||||
|
color: rgba(0, 0, 0, 0.54);
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 16px 0 18px;
|
||||||
|
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItemToggle {
|
||||||
|
width: 40%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 20%;
|
||||||
|
}
|
||||||
|
.listItemCreated {
|
||||||
|
width: 10%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
.listItemRevive{
|
||||||
|
width: 5%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 10%;
|
||||||
|
}
|
||||||
|
.toggleDetails {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 24px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 18px;
|
||||||
|
color: rgba(0, 0, 0, 0.54);
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.strategiesList {
|
||||||
|
flex-shrink: 0;
|
||||||
|
float: right;
|
||||||
|
margin-left: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,6 @@ class AddFeatureToggleComponent extends Component {
|
|||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<StrategiesSection
|
<StrategiesSection
|
||||||
configuredStrategies={configuredStrategies}
|
configuredStrategies={configuredStrategies}
|
||||||
addStrategy={addStrategy}
|
addStrategy={addStrategy}
|
||||||
|
@ -66,8 +66,11 @@ ReactDOM.render(
|
|||||||
<Route pageTitle="Event history" path="/history" component={HistoryPage} />
|
<Route pageTitle="Event history" path="/history" component={HistoryPage} />
|
||||||
<Route pageTitle=":toggleName" path="/history/:toggleName" component={HistoryTogglePage} />
|
<Route pageTitle=":toggleName" path="/history/:toggleName" component={HistoryTogglePage} />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route pageTitle="Archived Toggles" link="/archive">
|
||||||
|
<Route pageTitle="Archived Toggles" path="/archive" component={Archive} />
|
||||||
|
<Route pageTitle=":name" path="/archive/:name" component={Archive} />
|
||||||
|
</Route>
|
||||||
|
|
||||||
<Route pageTitle="Archived Toggles" path="/archive" component={Archive} />
|
|
||||||
<Route pageTitle="Applications" link="/applications">
|
<Route pageTitle="Applications" link="/applications">
|
||||||
<Route pageTitle="Applications" path="/applications" component={Applications} />
|
<Route pageTitle="Applications" path="/applications" component={Applications} />
|
||||||
<Route pageTitle=":name" path="/applications/:name" component={ApplicationView} />
|
<Route pageTitle=":name" path="/applications/:name" component={ApplicationView} />
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Archive from '../../component/archive/archive-container';
|
import Archive from '../../component/archive/archive-list-container';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const render = () => <Archive />;
|
const render = ({ params }) => <Archive name={params.name} />;
|
||||||
|
render.propTypes = {
|
||||||
|
params: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
export default render;
|
export default render;
|
||||||
|
Loading…
Reference in New Issue
Block a user