1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-14 00:19:16 +01:00

refactor: remove unused tags code (#687)

* refactor: remove unused tags code

* fix: remove feature tags

Co-authored-by: Fredrik Oseberg <fredrik.no@gmail.com>
This commit is contained in:
olav 2022-02-09 15:01:03 +01:00 committed by GitHub
parent 460a376903
commit 500d405fa5
37 changed files with 22 additions and 1133 deletions

View File

@ -8,7 +8,7 @@ import HistoryTogglePage from '../../page/history/toggle';
import { ArchiveListContainer } from '../archive/ArchiveListContainer';
import Applications from '../../page/applications';
import ApplicationView from '../../page/applications/view';
import ListTagTypes from '../../page/tag-types';
import { TagTypeList } from '../tags/TagTypeList/TagTypeList';
import Addons from '../../page/addons';
import AddonsCreate from '../../page/addons/create';
import AddonsEdit from '../../page/addons/edit';
@ -37,8 +37,8 @@ import CreateEnvironment from '../environments/CreateEnvironment/CreateEnvironme
import EditEnvironment from '../environments/EditEnvironment/EditEnvironment';
import CreateContext from '../context/CreateContext/CreateContext';
import EditContext from '../context/EditContext/EditContext';
import EditTagType from '../tagTypes/EditTagType/EditTagType';
import CreateTagType from '../tagTypes/CreateTagType/CreateTagType';
import EditTagType from '../tags/EditTagType/EditTagType';
import CreateTagType from '../tags/CreateTagType/CreateTagType';
import EditProject from '../project/Project/EditProject/EditProject';
import CreateProject from '../project/Project/CreateProject/CreateProject';
import CreateFeature from '../feature/CreateFeature/CreateFeature';
@ -314,7 +314,7 @@ export const routes = [
{
path: '/tag-types',
title: 'Tag types',
component: ListTagTypes,
component: TagTypeList,
type: 'protected',
layout: 'main',
menu: { mobile: true, advanced: true },

View File

@ -1,3 +0,0 @@
import TagTypeList from './TagTypeList';
export default TagTypeList;

View File

@ -1,157 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it supports editMode 1`] = `
<div
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
style={
Object {
"borderRadius": "10px",
"boxShadow": "none",
}
}
>
<div
className="makeStyles-headerContainer-1"
>
<div
className="makeStyles-headerTitleContainer-5"
>
<div
className=""
data-loading={true}
>
<h2
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h2"
>
Update Tag type
</h2>
</div>
</div>
</div>
<div
className="makeStyles-bodyContainer-2"
>
<section
className="contentSpacing tagTypeContainer"
>
<h6
className="MuiTypography-root MuiTypography-subtitle1"
>
Tag types allow you to group tags together in the management UI
</h6>
<form
className="addTagTypeForm contentSpacing"
onSubmit={[Function]}
>
<span>
You do not have permissions to save.
</span>
</form>
</section>
</div>
</div>
`;
exports[`renders correctly for creating 1`] = `
<div
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
style={
Object {
"borderRadius": "10px",
"boxShadow": "none",
}
}
>
<div
className="makeStyles-headerContainer-1"
>
<div
className="makeStyles-headerTitleContainer-5"
>
<div
className=""
data-loading={true}
>
<h2
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h2"
>
Create Tag type
</h2>
</div>
</div>
</div>
<div
className="makeStyles-bodyContainer-2"
>
<section
className="contentSpacing tagTypeContainer"
>
<h6
className="MuiTypography-root MuiTypography-subtitle1"
>
Tag types allow you to group tags together in the management UI
</h6>
<form
className="addTagTypeForm contentSpacing"
onSubmit={[Function]}
>
<span>
You do not have permissions to save.
</span>
</form>
</section>
</div>
</div>
`;
exports[`renders correctly for creating without permissions 1`] = `
<div
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
style={
Object {
"borderRadius": "10px",
"boxShadow": "none",
}
}
>
<div
className="makeStyles-headerContainer-1"
>
<div
className="makeStyles-headerTitleContainer-5"
>
<div
className=""
data-loading={true}
>
<h2
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h2"
>
Create Tag type
</h2>
</div>
</div>
</div>
<div
className="makeStyles-bodyContainer-2"
>
<section
className="contentSpacing tagTypeContainer"
>
<h6
className="MuiTypography-root MuiTypography-subtitle1"
>
Tag types allow you to group tags together in the management UI
</h6>
<form
className="addTagTypeForm contentSpacing"
onSubmit={[Function]}
>
<span>
You do not have permissions to save.
</span>
</form>
</section>
</div>
</div>
`;

View File

@ -1,80 +0,0 @@
import React from 'react';
import { ThemeProvider } from '@material-ui/core';
import TagTypes from '../form-tag-type-component';
import renderer from 'react-test-renderer';
import theme from '../../../themes/main-theme';
import AccessProvider from '../../providers/AccessProvider/AccessProvider';
import { createFakeStore } from '../../../accessStoreFake';
import {
CREATE_TAG_TYPE,
UPDATE_TAG_TYPE,
} from '../../providers/AccessProvider/permissions';
jest.mock('@material-ui/core/TextField');
test('renders correctly for creating', () => {
const tree = renderer
.create(
<ThemeProvider theme={theme}>
<AccessProvider
store={createFakeStore([{ permission: CREATE_TAG_TYPE }])}
>
<TagTypes
history={{}}
title="Add tag type"
createTagType={jest.fn()}
validateName={() => Promise.resolve(true)}
tagType={{ name: '', description: '', icon: '' }}
editMode={false}
submit={jest.fn()}
/>
</AccessProvider>
</ThemeProvider>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
test('renders correctly for creating without permissions', () => {
const tree = renderer
.create(
<ThemeProvider theme={theme}>
<AccessProvider store={createFakeStore([])}>
<TagTypes
history={{}}
title="Add tag type"
createTagType={jest.fn()}
validateName={() => Promise.resolve(true)}
tagType={{ name: '', description: '', icon: '' }}
editMode={false}
submit={jest.fn()}
/>
</AccessProvider>
</ThemeProvider>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
test('it supports editMode', () => {
const tree = renderer
.create(
<ThemeProvider theme={theme}>
<AccessProvider
store={createFakeStore([{ permission: UPDATE_TAG_TYPE }])}
>
<TagTypes
history={{}}
title="Add tag type"
createTagType={jest.fn()}
validateName={() => Promise.resolve(true)}
tagType={{ name: '', description: '', icon: '' }}
editMode
submit={jest.fn()}
/>
</AccessProvider>
</ThemeProvider>
)
.toJSON();
expect(tree).toMatchSnapshot();
});

View File

@ -1,17 +0,0 @@
import { connect } from 'react-redux';
import TagTypeComponent from './form-tag-type-component';
import { createTagType, validateName } from '../../store/tag-type/actions';
const mapStateToProps = () => ({
tagType: { name: '', description: '', icon: '' },
editMode: false,
});
const mapDispatchToProps = dispatch => ({
validateName: name => validateName(name),
submit: tagType => createTagType(tagType)(dispatch),
});
const FormAddContainer = connect(mapStateToProps, mapDispatchToProps)(TagTypeComponent);
export default FormAddContainer;

View File

@ -1,25 +0,0 @@
import { connect } from 'react-redux';
import Component from './form-tag-type-component';
import { updateTagType } from '../../store/tag-type/actions';
const mapStateToProps = (state, props) => {
const tagTypeBase = { name: '', description: '', icon: '' };
const realTagType = state.tagTypes.toJS().find(n => n.name === props.tagTypeName);
const tagType = Object.assign(tagTypeBase, realTagType);
return {
tagType,
editMode: true,
};
};
const mapDispatchToProps = dispatch => ({
validateName: () => {},
submit: tagType => {
updateTagType(tagType)(dispatch);
},
});
const FormAddContainer = connect(mapStateToProps, mapDispatchToProps)(Component);
export default FormAddContainer;

View File

@ -1,140 +0,0 @@
import React, { useContext, useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { FormButtons } from '../common';
import PageContent from '../common/PageContent/PageContent';
import { Typography, TextField } from '@material-ui/core';
import styles from './TagType.module.scss';
import commonStyles from '../common/common.module.scss';
import AccessContext from '../../contexts/AccessContext';
import {
CREATE_TAG_TYPE,
UPDATE_TAG_TYPE,
} from '../providers/AccessProvider/permissions';
import ConditionallyRender from '../common/ConditionallyRender';
const AddTagTypeComponent = ({
tagType,
validateName,
submit,
history,
editMode,
}) => {
const [tagTypeName, setTagTypeName] = useState(tagType.name || '');
const [tagTypeDescription, setTagTypeDescription] = useState(
tagType.description || ''
);
const [errors, setErrors] = useState({
general: undefined,
name: undefined,
description: undefined,
});
const { hasAccess } = useContext(AccessContext);
const onValidateName = async evt => {
evt.preventDefault();
const name = evt.target.value;
try {
await validateName(name);
setErrors({ name: undefined });
} catch (err) {
setErrors({ name: err.message });
}
};
const onCancel = evt => {
evt.preventDefault();
history.push('/tag-types');
};
const onSubmit = async evt => {
evt.preventDefault();
try {
await submit({
name: tagTypeName,
description: tagTypeDescription,
});
history.push('/tag-types');
} catch (e) {
setErrors({ general: e.message });
}
};
const submitText = editMode ? 'Update' : 'Create';
return (
<PageContent headerContent={`${submitText} Tag type`}>
<section
className={classnames(
commonStyles.contentSpacing,
styles.tagTypeContainer
)}
>
<Typography variant="subtitle1">
Tag types allow you to group tags together in the
management UI
</Typography>
<form
onSubmit={onSubmit}
className={classnames(
styles.addTagTypeForm,
commonStyles.contentSpacing
)}
>
<TextField
label="Name"
name="name"
placeholder="url-friendly-unique-name"
value={tagTypeName}
error={errors.name !== undefined}
helperText={errors.name}
disabled={editMode}
onBlur={onValidateName}
onChange={v => setTagTypeName(v.target.value.trim())}
variant="outlined"
size="small"
/>
<TextField
label="Description"
name="description"
placeholder="Some short explanation of the tag type"
rowsMax={4}
multiline
error={errors.description !== undefined}
helperText={errors.description}
value={tagTypeDescription}
onChange={v => setTagTypeDescription(v.target.value)}
variant="outlined"
size="small"
/>
<ConditionallyRender
condition={hasAccess(
editMode ? UPDATE_TAG_TYPE : CREATE_TAG_TYPE
)}
show={
<div className={styles.formButtons}>
<FormButtons
submitText={submitText}
onCancel={onCancel}
/>
</div>
}
elseShow={
<span>You do not have permissions to save.</span>
}
/>
</form>
</section>
</PageContent>
);
};
AddTagTypeComponent.propTypes = {
tagType: PropTypes.object.isRequired,
validateName: PropTypes.func.isRequired,
submit: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
editMode: PropTypes.bool.isRequired,
};
export default AddTagTypeComponent;

View File

@ -1,21 +0,0 @@
import { connect } from 'react-redux';
import TagTypesListComponent from './TagTypeList';
import { fetchTagTypes, removeTagType } from '../../store/tag-type/actions';
const mapStateToProps = state => {
const list = state.tagTypes.toJS();
return {
tagTypes: list,
};
};
const mapDispatchToProps = dispatch => ({
removeTagType: tagtype => {
removeTagType(tagtype)(dispatch);
},
fetchTagTypes: () => fetchTagTypes()(dispatch),
});
const TagTypesListContainer = connect(mapStateToProps, mapDispatchToProps)(TagTypesListComponent);
export default TagTypesListContainer;

View File

@ -5,7 +5,7 @@ import useToast from '../../../hooks/useToast';
import FormTemplate from '../../common/FormTemplate/FormTemplate';
import PermissionButton from '../../common/PermissionButton/PermissionButton';
import { UPDATE_TAG_TYPE } from '../../providers/AccessProvider/permissions';
import useTagForm from '../hooks/useTagForm';
import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
import TagTypeForm from '../TagTypeForm/TagTypeForm';
const CreateTagType = () => {
@ -21,7 +21,7 @@ const CreateTagType = () => {
validateNameUniqueness,
errors,
clearErrors,
} = useTagForm();
} = useTagTypeForm();
const { createTag, loading } = useTagTypesApi();
const handleSubmit = async (e: Event) => {

View File

@ -6,7 +6,7 @@ import useToast from '../../../hooks/useToast';
import FormTemplate from '../../common/FormTemplate/FormTemplate';
import PermissionButton from '../../common/PermissionButton/PermissionButton';
import { UPDATE_TAG_TYPE } from '../../providers/AccessProvider/permissions';
import useTagForm from '../hooks/useTagForm';
import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
import TagForm from '../TagTypeForm/TagTypeForm';
const EditTagType = () => {
@ -23,7 +23,7 @@ const EditTagType = () => {
getTagPayload,
errors,
clearErrors,
} = useTagForm(tagType?.name, tagType?.description);
} = useTagTypeForm(tagType?.name, tagType?.description);
const { updateTagType, loading } = useTagTypesApi();
const handleSubmit = async (e: Event) => {

View File

@ -1,32 +0,0 @@
.select {
min-width: 100px;
}
.textfield {
margin-left: 15px;
}
.header {
padding: var(--card-header-padding);
word-break: break-all;
border-bottom: var(--default-border);
display: flex;
align-items: center;
justify-content: space-between;
}
.header h1 {
font-size: var(--h1-size);
}
.container {
padding: var(--card-padding);
}
.formbuttons {
padding-top: 1rem;
}
.tagListItem {
padding: 0;
}

View File

@ -1,138 +0,0 @@
import React, { useContext, useEffect } from 'react';
import PropTypes from 'prop-types';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import { useHistory } from 'react-router-dom';
import {
Button,
IconButton,
List,
ListItem,
ListItemIcon,
ListItemText,
Tooltip,
} from '@material-ui/core';
import { Add, Label, Delete } from '@material-ui/icons';
import {
CREATE_TAG,
DELETE_TAG,
} from '../../providers/AccessProvider/permissions';
import ConditionallyRender from '../../common/ConditionallyRender/ConditionallyRender';
import HeaderTitle from '../../common/HeaderTitle';
import PageContent from '../../common/PageContent/PageContent';
import { useStyles } from './TagList.styles';
import AccessContext from '../../../contexts/AccessContext';
const TagList = ({ tags, fetchTags, removeTag }) => {
const history = useHistory();
const smallScreen = useMediaQuery('(max-width:700px)');
const styles = useStyles();
const { hasAccess } = useContext(AccessContext);
useEffect(() => {
fetchTags();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const remove = (tag, evt) => {
evt.preventDefault();
removeTag(tag);
};
const listItem = tag => (
<ListItem
key={`${tag.type}_${tag.value}`}
className={styles.tagListItem}
>
<ListItemIcon>
<Label />
</ListItemIcon>
<ListItemText primary={tag.value} secondary={tag.type} />
<ConditionallyRender
condition={hasAccess(DELETE_TAG)}
show={<DeleteButton tagType={tag.type} tagValue={tag.value} />}
/>
</ListItem>
);
const DeleteButton = ({ tagType, tagValue }) => (
<Tooltip title="Delete tag">
<IconButton
onClick={e => remove({ type: tagType, value: tagValue }, e)}
>
<Delete />
</IconButton>
</Tooltip>
);
DeleteButton.propTypes = {
tagType: PropTypes.string,
tagValue: PropTypes.string,
};
const AddButton = ({ hasAccess }) => (
<ConditionallyRender
condition={hasAccess(CREATE_TAG)}
show={
<ConditionallyRender
condition={smallScreen}
show={
<IconButton
aria-label="add tag"
onClick={() => history.push('/tag-types/create')}
>
<Add />
</IconButton>
}
elseShow={
<Tooltip title="Add new tag">
<Button
color="primary"
startIcon={<Add />}
onClick={() =>
history.push('/tag-types/create')
}
variant="contained"
>
Add new tag
</Button>
</Tooltip>
}
/>
}
/>
);
return (
<PageContent
headerContent={
<HeaderTitle
title="Tags"
actions={<AddButton hasAccess={hasAccess} />}
/>
}
>
<List>
<ConditionallyRender
condition={tags.length > 0}
show={tags.map(tag => listItem(tag))}
elseShow={
<ListItem className={styles.tagListItem}>
<ListItemText primary="No tags available" />
</ListItem>
}
/>
</List>
</PageContent>
);
};
TagList.propTypes = {
tags: PropTypes.array.isRequired,
fetchTags: PropTypes.func.isRequired,
removeTag: PropTypes.func.isRequired,
};
export default TagList;

View File

@ -1,7 +0,0 @@
import { makeStyles } from '@material-ui/styles';
export const useStyles = makeStyles({
tagListItem: {
padding: 0,
},
});

View File

@ -1,3 +0,0 @@
import TagsListComponent from './TagList';
export default TagsListComponent;

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import useTagTypesApi from '../../../hooks/api/actions/useTagTypesApi/useTagTypesApi';
const useTagForm = (initialTagName = '', initialTagDesc = '') => {
const useTagTypeForm = (initialTagName = '', initialTagDesc = '') => {
const [tagName, setTagName] = useState(initialTagName);
const [tagDesc, setTagDesc] = useState(initialTagDesc);
const [errors, setErrors] = useState({});
@ -66,4 +66,4 @@ const useTagForm = (initialTagName = '', initialTagDesc = '') => {
};
};
export default useTagForm;
export default useTagTypeForm;

View File

@ -2,12 +2,12 @@ import { useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { Link, useHistory } from 'react-router-dom';
import {
Button,
IconButton,
List,
ListItem,
ListItemIcon,
ListItemText,
IconButton,
Button,
Tooltip,
} from '@material-ui/core';
import { Add, Delete, Edit, Label } from '@material-ui/icons';
@ -20,14 +20,14 @@ import {
} from '../../providers/AccessProvider/permissions';
import Dialogue from '../../common/Dialogue/Dialogue';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import styles from '../TagType.module.scss';
import styles from './TagTypeList.module.scss';
import AccessContext from '../../../contexts/AccessContext';
import useTagTypesApi from '../../../hooks/api/actions/useTagTypesApi/useTagTypesApi';
import useTagTypes from '../../../hooks/api/getters/useTagTypes/useTagTypes';
import useToast from '../../../hooks/useToast';
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
const TagTypeList = () => {
export const TagTypeList = () => {
const { hasAccess } = useContext(AccessContext);
const [deletion, setDeletion] = useState({ open: false });
const history = useHistory();
@ -160,5 +160,3 @@ TagTypeList.propTypes = {
fetchTagTypes: PropTypes.func.isRequired,
removeTagType: PropTypes.func.isRequired,
};
export default TagTypeList;

View File

@ -1,20 +1,18 @@
import React from 'react';
import TagTypesList from '../TagTypeList';
import { TagTypeList } from '../TagTypeList';
import renderer from 'react-test-renderer';
import { MemoryRouter } from 'react-router-dom';
import { ThemeProvider } from '@material-ui/styles';
import theme from '../../../themes/main-theme';
import { createFakeStore } from '../../../accessStoreFake';
import AccessProvider from '../../providers/AccessProvider/AccessProvider';
import theme from '../../../../themes/main-theme';
import { createFakeStore } from '../../../../accessStoreFake';
import AccessProvider from '../../../providers/AccessProvider/AccessProvider';
import {
ADMIN,
CREATE_TAG_TYPE,
UPDATE_TAG_TYPE,
DELETE_TAG_TYPE,
} from '../../providers/AccessProvider/permissions';
import UIProvider from '../../providers/UIProvider/UIProvider';
} from '../../../providers/AccessProvider/permissions';
import UIProvider from '../../../providers/UIProvider/UIProvider';
test('renders an empty list correctly', () => {
const tree = renderer.create(
@ -24,7 +22,7 @@ test('renders an empty list correctly', () => {
<AccessProvider
store={createFakeStore([{ permission: ADMIN }])}
>
<TagTypesList
<TagTypeList
tagTypes={[]}
fetchTagTypes={jest.fn()}
removeTagType={jest.fn()}
@ -50,7 +48,7 @@ test('renders a list with elements correctly', () => {
{ permission: DELETE_TAG_TYPE },
])}
>
<TagTypesList
<TagTypeList
tagTypes={[
{
name: 'simple',

View File

@ -1,15 +0,0 @@
import { connect } from 'react-redux';
import TagComponent from './form-tag-component';
import { create } from '../../store/tag/actions';
const mapStateToProps = () => ({
tag: { type: '', value: '' },
});
const mapDispatchToProps = dispatch => ({
submit: tag => create(tag)(dispatch),
});
const FormAddContainer = connect(mapStateToProps, mapDispatchToProps)(TagComponent);
export default FormAddContainer;

View File

@ -1,107 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { TextField } from '@material-ui/core';
import styles from './Tag.module.scss';
import { FormButtons } from '../common';
import PageContent from '../common/PageContent/PageContent';
import TagSelect from '../common/TagSelect/TagSelect';
class AddTagComponent extends Component {
constructor(props) {
super(props);
this.state = {
tag: props.tag,
errors: {},
dirty: false,
currentLegalValue: '',
};
}
static getDerivedStateFromProps(props, state) {
if (!state.tag.id && props.tag.id) {
return { tag: props.tag };
} else {
return null;
}
}
setValue = (field, value) => {
const { tag } = this.state;
tag[field] = value;
this.setState({ tag, dirty: true });
};
onCancel = evt => {
evt.preventDefault();
this.props.history.push('/tags');
};
onSubmit = async evt => {
evt.preventDefault();
const { tag } = this.state;
if (!tag.type || tag.type === '') {
tag.type = 'simple';
}
try {
await this.props.submit(tag);
this.props.history.push('/tags');
} catch (e) {
this.setState({
errors: {
general: e.message,
},
});
}
};
render() {
const { tag, errors } = this.state;
const submitText = 'Create';
return (
<PageContent headerContent={`${submitText} Tag`}>
<section className={styles.container}>
<form onSubmit={this.onSubmit}>
<p style={{ color: 'red' }}>{errors.general}</p>
<TagSelect
name="type"
value={tag.type}
onChange={v =>
this.setValue('type', v.target.value)
}
className={styles.select}
/>
<TextField
label="Value"
name="value"
placeholder="Your tag"
size="small"
variant="outlined"
rowsMax={4}
value={tag.value}
error={errors.value !== undefined}
helperText={errors.value}
onChange={v =>
this.setValue('value', v.target.value)
}
className={styles.textfield}
/>
<div className={styles.formbuttons}>
<FormButtons
submitText={submitText}
onCancel={this.onCancel}
/>
</div>
</form>
</section>
</PageContent>
);
}
}
AddTagComponent.propTypes = {
tag: PropTypes.object.isRequired,
submit: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
};
export default AddTagComponent;

View File

@ -1,24 +0,0 @@
import { connect } from 'react-redux';
import TagsListComponent from './TagList';
import { fetchTags, removeTag } from '../../store/tag/actions';
const mapStateToProps = state => {
const list = state.tags.toJS();
return {
tags: list,
};
};
const mapDispatchToProps = dispatch => ({
removeTag: tag => {
// eslint-disable-next-line no-alert
if (window.confirm('Are you sure you want to remove this tag?')) {
removeTag(tag)(dispatch);
}
},
fetchTags: () => fetchTags()(dispatch),
});
const TagsListContainer = connect(mapStateToProps, mapDispatchToProps)(TagsListComponent);
export default TagsListContainer;

View File

@ -1,11 +0,0 @@
import React from 'react';
import AddTagType from '../../component/tag-types/create-tag-type-container';
import PropTypes from 'prop-types';
const render = ({ history }) => <AddTagType title="Add tag type" history={history} />;
render.propTypes = {
history: PropTypes.object.isRequired,
};
export default render;

View File

@ -1,13 +0,0 @@
import React from 'react';
import EditTagType from './../../component/tag-types/edit-tag-type-container';
import PropTypes from 'prop-types';
const render = ({ match: { params }, history }) => (
<EditTagType tagTypeName={params.name} title="Edit Tag type" history={history} />
);
render.propTypes = {
match: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
};
export default render;

View File

@ -1,11 +0,0 @@
import React from 'react';
import TagTypes from '../../component/tag-types';
import PropTypes from 'prop-types';
const render = ({ history }) => <TagTypes history={history} />;
render.propTypes = {
history: PropTypes.object.isRequired,
};
export default render;

View File

@ -1,11 +0,0 @@
import React from 'react';
import AddTag from '../../component/tags/create-tag-container';
import PropTypes from 'prop-types';
const render = ({ history }) => <AddTag title="Add Tag" history={history} />;
render.propTypes = {
history: PropTypes.object.isRequired,
};
export default render;

View File

@ -1,11 +0,0 @@
import React from 'react';
import Tags from '../../component/tags';
import PropTypes from 'prop-types';
const render = ({ history }) => <Tags history={history} />;
render.propTypes = {
history: PropTypes.object.isRequired,
};
export default render;

View File

@ -1,7 +1,5 @@
import { combineReducers } from 'redux';
import features from './feature-toggle';
import tagTypes from './tag-type';
import tags from './tag';
import strategies from './strategy';
import error from './error';
import user from './user';
@ -13,8 +11,6 @@ import apiCalls from './api-calls';
const unleashStore = combineReducers({
features,
strategies,
tagTypes,
tags,
error,
user,
applications,

View File

@ -1,77 +0,0 @@
import api from './api';
import { dispatchError } from '../util';
export const START_FETCH_TAG_TYPES = 'START_FETCH_TAG_TYPES';
export const RECEIVE_TAG_TYPES = 'RECEIVE_TAG_TYPES';
export const ERROR_FETCH_TAG_TYPES = 'ERROR_FETCH_TAG_TYPES';
export const START_CREATE_TAG_TYPE = 'START_CREATE_TAG_TYPE';
export const ADD_TAG_TYPE = 'ADD_TAG_TYPE';
export const ERROR_CREATE_TAG_TYPE = 'ERROR_CREATE_TAG_TYPE';
export const START_DELETE_TAG_TYPE = 'START_DELETE_TAG_TYPE';
export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
export const ERROR_DELETE_TAG_TYPE = 'ERROR_DELETE_TAG_TYPE';
export const START_UPDATE_TAG_TYPE = 'START_UPDATE_TAG_TYPE';
export const UPDATE_TAG_TYPE = 'UPDATE_TAG_TYPE';
export const ERROR_UPDATE_TAG_TYPE = 'ERROR_UPDATE_TAG_TYPE';
export function receiveTagTypes(json) {
return {
type: RECEIVE_TAG_TYPES,
value: json,
receivedAt: Date.now(),
};
}
export function fetchTagTypes() {
return dispatch => {
dispatch({ type: START_FETCH_TAG_TYPES });
return api
.fetchTagTypes()
.then(json => dispatch(receiveTagTypes(json)))
.catch(dispatchError(dispatch, ERROR_FETCH_TAG_TYPES));
};
}
export function createTagType({ name, description, icon }) {
return dispatch => {
dispatch({ type: START_CREATE_TAG_TYPE });
return api
.create({ name, description, icon })
.then(() =>
dispatch({
type: ADD_TAG_TYPE,
tagType: { name, description, icon },
})
)
.catch(dispatchError(dispatch, ERROR_CREATE_TAG_TYPE));
};
}
export function updateTagType({ name, description, icon }) {
return dispatch => {
dispatch({ type: START_UPDATE_TAG_TYPE });
return api
.update({ name, description, icon })
.then(() =>
dispatch({
type: UPDATE_TAG_TYPE,
tagType: { name, description, icon },
})
)
.catch(dispatchError(dispatch, ERROR_UPDATE_TAG_TYPE));
};
}
export function removeTagType(name) {
return dispatch => {
dispatch({ type: START_DELETE_TAG_TYPE });
return api
.deleteTagType(name)
.then(() => dispatch({ type: DELETE_TAG_TYPE, tagType: { name } }))
.catch(dispatchError(dispatch, ERROR_DELETE_TAG_TYPE));
};
}
export function validateName(name) {
return api.validateTagType({ name });
}

View File

@ -1,58 +0,0 @@
import { formatApiPath } from '../../utils/format-path';
import { throwIfNotSuccess, headers } from '../api-helper';
const URI = formatApiPath('api/admin/tag-types');
function fetchTagTypes() {
return fetch(URI, { credentials: 'include' })
.then(throwIfNotSuccess)
.then(response => response.json());
}
function validateTagType(tagType) {
return fetch(`${URI}/validate`, {
method: 'POST',
headers,
credentials: 'include',
body: JSON.stringify(tagType),
}).then(throwIfNotSuccess);
}
function create(tagType) {
return validateTagType(tagType)
.then(() =>
fetch(URI, {
method: 'POST',
headers,
credentials: 'include',
body: JSON.stringify(tagType),
})
)
.then(throwIfNotSuccess);
}
function update(tagType) {
return fetch(`${URI}/${tagType.name}`, {
method: 'PUT',
headers,
credentials: 'include',
body: JSON.stringify(tagType),
}).then(throwIfNotSuccess);
}
function deleteTagType(tagTypeName) {
return fetch(`${URI}/${tagTypeName}`, {
method: 'DELETE',
headers,
credentials: 'include',
}).then(throwIfNotSuccess);
}
const api = {
fetchTagTypes,
create,
update,
deleteTagType,
validateTagType,
};
export default api;

View File

@ -1,33 +0,0 @@
import { List, Map as $Map } from 'immutable';
import { RECEIVE_TAG_TYPES, ADD_TAG_TYPE, DELETE_TAG_TYPE, UPDATE_TAG_TYPE, ERROR_FETCH_TAG_TYPES } from './actions';
const debug = require('debug')('unleash:tag-type-store');
const tagTypes = (state = new List([]), action) => {
switch (action.type) {
case ADD_TAG_TYPE:
debug('Add tagtype');
return state.push(new $Map(action.tagType));
case DELETE_TAG_TYPE:
debug('Delete tagtype');
return state.filter(tagtype => tagtype.get('name') !== action.tagType.name);
case RECEIVE_TAG_TYPES:
debug('Receive tag types', action);
return new List(action.value.tagTypes.map($Map));
case ERROR_FETCH_TAG_TYPES:
debug('Error receiving tag types', action);
return state;
case UPDATE_TAG_TYPE:
return state.map(tagtype => {
if (tagtype.get('name') === action.tagType.name) {
return new $Map(action.tagType);
} else {
return tagtype;
}
});
default:
return state;
}
};
export default tagTypes;

View File

@ -1,50 +0,0 @@
import api from './api';
import { dispatchError } from '../util';
export const START_FETCH_TAGS = 'START_FETCH_TAGS';
export const RECEIVE_TAGS = 'RECEIVE_TAGS';
export const ERROR_FETCH_TAGS = 'ERROR_FETCH_TAGS';
export const START_CREATE_TAG = 'START_CREATE_TAG';
export const ADD_TAG = 'ADD_TAG';
export const ERROR_CREATE_TAG = 'ERROR_CREATE_TAG';
export const START_DELETE_TAG = 'START_DELETE_TAG';
export const DELETE_TAG = 'DELETE_TAG';
export const ERROR_DELETE_TAG = 'ERROR_DELETE_TAG';
function receiveTags(json) {
return {
type: RECEIVE_TAGS,
value: json,
receivedAt: Date.now(),
};
}
export function fetchTags() {
return dispatch => {
dispatch({ type: START_FETCH_TAGS });
return api
.fetchTags()
.then(json => dispatch(receiveTags(json)))
.catch(dispatchError(dispatch, ERROR_FETCH_TAGS));
};
}
export function create({ type, value }) {
return dispatch => {
dispatch({ type: START_CREATE_TAG });
return api
.create({ type, value })
.then(() => dispatch({ type: ADD_TAG, tag: { type, value } }))
.catch(dispatchError(dispatch, ERROR_CREATE_TAG));
};
}
export function removeTag(tag) {
return dispatch => {
dispatch({ type: START_DELETE_TAG });
return api
.deleteTag(tag)
.then(() => dispatch({ type: DELETE_TAG, tag }))
.catch(dispatchError(dispatch, ERROR_DELETE_TAG));
};
}

View File

@ -1,33 +0,0 @@
import { formatApiPath } from '../../utils/format-path';
import { throwIfNotSuccess, headers } from '../api-helper';
const URI = formatApiPath('api/admin/tags');
function fetchTags() {
return fetch(URI, { credentials: 'include' })
.then(throwIfNotSuccess)
.then(response => response.json());
}
function create(tag) {
return fetch(URI, {
method: 'POST',
headers,
credentials: 'include',
body: JSON.stringify(tag),
}).then(throwIfNotSuccess);
}
function deleteTag(tag) {
return fetch(`${URI}/${tag.type}/${encodeURIComponent(tag.value)}`, {
method: 'DELETE',
headers,
credentials: 'include',
}).then(throwIfNotSuccess);
}
export default {
fetchTags,
deleteTag,
create,
};

View File

@ -1,24 +0,0 @@
import { List, Map as $Map } from 'immutable';
import { ADD_TAG, DELETE_TAG, ERROR_FETCH_TAGS, RECEIVE_TAGS } from './actions';
const debug = require('debug')('unleash:tag-store');
const tags = (state = new List([]), action) => {
switch (action.type) {
case ADD_TAG:
debug('Add tag');
return state.push(new $Map(action.tag));
case DELETE_TAG:
debug('Delete tag');
return state.filter(tag => tag.get('type') !== action.tag.type && tag.get('value') !== action.tag.value);
case RECEIVE_TAGS:
debug('Receive tags', action);
return new List(action.value.tags.map($Map));
case ERROR_FETCH_TAGS:
debug('Error receiving tag types', action);
return state;
default:
return state;
}
};
export default tags;

View File

@ -1,7 +1,6 @@
import api from './api';
import { dispatchError } from '../util';
import { receiveProjects } from '../project/actions';
import { receiveTagTypes } from '../tag-type/actions';
import { receiveStrategies } from '../strategy/actions';
export const RECEIVE_BOOTSTRAP = 'RECEIVE_CONFIG';
@ -13,7 +12,6 @@ export function fetchUiBootstrap() {
.fetchUIBootstrap()
.then(json => {
dispatch(receiveProjects(json.projects));
dispatch(receiveTagTypes(json));
dispatch(receiveStrategies(json.strategies));
})
.catch(dispatchError(dispatch, ERROR_RECEIVE_BOOTSTRAP));