mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
Fix/project select (#693)
* fix: remove container for ProjectSelect * refactor: remove project store * fix: update path
This commit is contained in:
parent
821c383edd
commit
de8b3352e7
@ -54,7 +54,7 @@ const ProjectSelect = ({ currentProjectId, updateCurrentProject, ...rest }) => {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
const { updateSetting, fetchProjects, ...passDown } = rest;
|
const { updateSetting, ...passDown } = rest;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import { connect } from 'react-redux';
|
|
||||||
import ProjectSelect from './ProjectSelect';
|
|
||||||
import { fetchProjects } from '../../../store/project/actions';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => ({
|
|
||||||
...ownProps,
|
|
||||||
projects: state.projects.toJS(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, { fetchProjects })(ProjectSelect);
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import { MenuItem, Typography } from '@material-ui/core';
|
import { MenuItem, Typography } from '@material-ui/core';
|
||||||
import DropdownMenu from '../../../common/DropdownMenu/DropdownMenu';
|
import DropdownMenu from '../../../common/DropdownMenu/DropdownMenu';
|
||||||
import ProjectSelect from '../../../common/ProjectSelect';
|
import ProjectSelect from '../../../common/ProjectSelect/ProjectSelect';
|
||||||
import { useStyles } from './styles';
|
import { useStyles } from './styles';
|
||||||
import useLoading from '../../../../hooks/useLoading';
|
import useLoading from '../../../../hooks/useLoading';
|
||||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
@ -29,7 +29,8 @@ const FeatureToggleListActions = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const isDisabled = s => s === sort.type;
|
const isDisabled = s => s === sort.type;
|
||||||
const selectedOption = sortOptions.find(o => o.type === sort.type) || sortOptions[0];
|
const selectedOption =
|
||||||
|
sortOptions.find(o => o.type === sort.type) || sortOptions[0];
|
||||||
|
|
||||||
const renderSortingOptions = () =>
|
const renderSortingOptions = () =>
|
||||||
sortOptions.map(option => (
|
sortOptions.map(option => (
|
||||||
@ -63,7 +64,9 @@ const FeatureToggleListActions = ({
|
|||||||
show={
|
show={
|
||||||
<ProjectSelect
|
<ProjectSelect
|
||||||
currentProjectId={filter.project}
|
currentProjectId={filter.project}
|
||||||
updateCurrentProject={project => setFilter(prev => ({ ...prev, project }))}
|
updateCurrentProject={project =>
|
||||||
|
setFilter(prev => ({ ...prev, project }))
|
||||||
|
}
|
||||||
style={{
|
style={{
|
||||||
textTransform: 'lowercase',
|
textTransform: 'lowercase',
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
|
@ -12,7 +12,7 @@ jest.mock('../FeatureToggleListItem', () => ({
|
|||||||
default: 'ListItem',
|
default: 'ListItem',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../../common/ProjectSelect');
|
jest.mock('../../../common/ProjectSelect/ProjectSelect');
|
||||||
|
|
||||||
test('renders correctly with one feature', () => {
|
test('renders correctly with one feature', () => {
|
||||||
const features = [
|
const features = [
|
||||||
|
@ -7,7 +7,7 @@ import useProject from '../../../../hooks/api/getters/useProject/useProject';
|
|||||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import useToast from '../../../../hooks/useToast';
|
import useToast from '../../../../hooks/useToast';
|
||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { UPDATE_PROJECT } from '../../../../store/project/actions';
|
import { UPDATE_PROJECT } from '../../../providers/AccessProvider/permissions';
|
||||||
|
|
||||||
const EditProject = () => {
|
const EditProject = () => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
@ -90,10 +90,7 @@ const EditProject = () => {
|
|||||||
clearErrors={clearErrors}
|
clearErrors={clearErrors}
|
||||||
validateIdUniqueness={validateIdUniqueness}
|
validateIdUniqueness={validateIdUniqueness}
|
||||||
>
|
>
|
||||||
<PermissionButton
|
<PermissionButton permission={UPDATE_PROJECT} type="submit">
|
||||||
permission={UPDATE_PROJECT}
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
Edit project
|
Edit project
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</ProjectForm>
|
</ProjectForm>
|
||||||
|
@ -16,8 +16,8 @@ import { ProjectAccess } from '../ProjectAccess/ProjectAccess';
|
|||||||
import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment';
|
import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment';
|
||||||
import ProjectOverview from './ProjectOverview';
|
import ProjectOverview from './ProjectOverview';
|
||||||
import ProjectHealth from './ProjectHealth/ProjectHealth';
|
import ProjectHealth from './ProjectHealth/ProjectHealth';
|
||||||
import { UPDATE_PROJECT } from '../../../store/project/actions';
|
|
||||||
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
|
||||||
|
import { UPDATE_PROJECT } from '../../providers/AccessProvider/permissions';
|
||||||
|
|
||||||
const Project = () => {
|
const Project = () => {
|
||||||
const { id, activeTab } = useParams<{ id: string; activeTab: string }>();
|
const { id, activeTab } = useParams<{ id: string; activeTab: string }>();
|
||||||
|
@ -8,7 +8,6 @@ import { useCommonStyles } from '../../../../common.styles';
|
|||||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import PercentageCircle from '../../../common/PercentageCircle/PercentageCircle';
|
import PercentageCircle from '../../../common/PercentageCircle/PercentageCircle';
|
||||||
import PermissionIconButton from '../../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../../common/PermissionIconButton/PermissionIconButton';
|
||||||
import { UPDATE_PROJECT } from '../../../../store/project/actions';
|
|
||||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
@ -16,6 +15,7 @@ import {
|
|||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
|
import { UPDATE_PROJECT } from '../../../providers/AccessProvider/permissions';
|
||||||
|
|
||||||
interface IProjectInfoProps {
|
interface IProjectInfoProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -11,8 +11,8 @@ import useProjects from '../../../hooks/api/getters/useProjects/useProjects';
|
|||||||
import { Delete, Edit } from '@material-ui/icons';
|
import { Delete, Edit } from '@material-ui/icons';
|
||||||
import { getProjectEditPath } from '../../../utils/route-path-helpers';
|
import { getProjectEditPath } from '../../../utils/route-path-helpers';
|
||||||
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
|
||||||
import { UPDATE_PROJECT } from '../../../store/project/actions';
|
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
|
import { UPDATE_PROJECT } from '../../providers/AccessProvider/permissions';
|
||||||
interface IProjectCardProps {
|
interface IProjectCardProps {
|
||||||
name: string;
|
name: string;
|
||||||
featureCount: number;
|
featureCount: number;
|
||||||
|
@ -16,12 +16,6 @@ import {
|
|||||||
UPDATE_STRATEGY_SUCCESS,
|
UPDATE_STRATEGY_SUCCESS,
|
||||||
} from '../strategy/actions';
|
} from '../strategy/actions';
|
||||||
|
|
||||||
import {
|
|
||||||
ERROR_REMOVING_PROJECT,
|
|
||||||
ERROR_ADD_PROJECT,
|
|
||||||
ERROR_UPDATE_PROJECT,
|
|
||||||
} from '../project/actions';
|
|
||||||
|
|
||||||
import { UPDATE_APPLICATION_FIELD } from '../application/actions';
|
import { UPDATE_APPLICATION_FIELD } from '../application/actions';
|
||||||
|
|
||||||
import { FORBIDDEN } from '../util';
|
import { FORBIDDEN } from '../util';
|
||||||
@ -51,9 +45,6 @@ const strategies = (state = getInitState(), action) => {
|
|||||||
case ERROR_UPDATING_STRATEGY:
|
case ERROR_UPDATING_STRATEGY:
|
||||||
case ERROR_CREATING_STRATEGY:
|
case ERROR_CREATING_STRATEGY:
|
||||||
case ERROR_RECEIVE_STRATEGIES:
|
case ERROR_RECEIVE_STRATEGIES:
|
||||||
case ERROR_REMOVING_PROJECT:
|
|
||||||
case ERROR_UPDATE_PROJECT:
|
|
||||||
case ERROR_ADD_PROJECT:
|
|
||||||
return addErrorIfNotAlreadyInList(state, action.error.message);
|
return addErrorIfNotAlreadyInList(state, action.error.message);
|
||||||
case FORBIDDEN:
|
case FORBIDDEN:
|
||||||
return addErrorIfNotAlreadyInList(
|
return addErrorIfNotAlreadyInList(
|
||||||
|
@ -3,7 +3,6 @@ import features from './feature-toggle';
|
|||||||
import strategies from './strategy';
|
import strategies from './strategy';
|
||||||
import error from './error';
|
import error from './error';
|
||||||
import applications from './application';
|
import applications from './application';
|
||||||
import projects from './project';
|
|
||||||
import apiCalls from './api-calls';
|
import apiCalls from './api-calls';
|
||||||
|
|
||||||
const unleashStore = combineReducers({
|
const unleashStore = combineReducers({
|
||||||
@ -11,7 +10,6 @@ const unleashStore = combineReducers({
|
|||||||
strategies,
|
strategies,
|
||||||
error,
|
error,
|
||||||
applications,
|
applications,
|
||||||
projects,
|
|
||||||
apiCalls,
|
apiCalls,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import api from './api';
|
|
||||||
import { dispatchError } from '../util';
|
|
||||||
|
|
||||||
export const RECEIVE_PROJECT = 'RECEIVE_PROJECT';
|
|
||||||
export const ERROR_RECEIVE_PROJECT = 'ERROR_RECEIVE_PROJECT';
|
|
||||||
export const REMOVE_PROJECT = 'REMOVE_PROJECT';
|
|
||||||
export const ERROR_REMOVING_PROJECT = 'ERROR_REMOVING_PROJECT';
|
|
||||||
export const ADD_PROJECT = 'ADD_PROJECT';
|
|
||||||
export const ERROR_ADD_PROJECT = 'ERROR_ADD_PROJECT';
|
|
||||||
export const UPDATE_PROJECT = 'UPDATE_PROJECT';
|
|
||||||
export const ERROR_UPDATE_PROJECT = 'ERROR_UPDATE_PROJECT';
|
|
||||||
|
|
||||||
const addProject = project => ({ type: ADD_PROJECT, project });
|
|
||||||
const upProject = project => ({ type: UPDATE_PROJECT, project });
|
|
||||||
const delProject = project => ({ type: REMOVE_PROJECT, project });
|
|
||||||
export const receiveProjects = value => ({ type: RECEIVE_PROJECT, value });
|
|
||||||
|
|
||||||
export function fetchProjects() {
|
|
||||||
return dispatch =>
|
|
||||||
api
|
|
||||||
.fetchAll()
|
|
||||||
.then(json => {
|
|
||||||
dispatch(receiveProjects(json.projects));
|
|
||||||
})
|
|
||||||
.catch(dispatchError(dispatch, ERROR_RECEIVE_PROJECT));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeProject(project) {
|
|
||||||
return dispatch =>
|
|
||||||
api
|
|
||||||
.remove(project)
|
|
||||||
.then(() => dispatch(delProject(project)))
|
|
||||||
.catch(dispatchError(dispatch, ERROR_REMOVING_PROJECT));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createProject(project) {
|
|
||||||
return dispatch =>
|
|
||||||
api
|
|
||||||
.create(project)
|
|
||||||
.then(() => dispatch(addProject(project)))
|
|
||||||
.catch(dispatchError(dispatch, ERROR_ADD_PROJECT));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateProject(project) {
|
|
||||||
return dispatch =>
|
|
||||||
api
|
|
||||||
.update(project)
|
|
||||||
.then(() => dispatch(upProject(project)))
|
|
||||||
.catch(dispatchError(dispatch, ERROR_UPDATE_PROJECT));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function validateId(id) {
|
|
||||||
return api.validate({ id });
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
import { formatApiPath } from '../../utils/format-path';
|
|
||||||
import { throwIfNotSuccess, headers } from '../api-helper';
|
|
||||||
|
|
||||||
const URI = formatApiPath('api/admin/projects');
|
|
||||||
|
|
||||||
function fetchAll() {
|
|
||||||
return fetch(URI, { credentials: 'include' })
|
|
||||||
.then(throwIfNotSuccess)
|
|
||||||
.then(response => response.json());
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchAccess(projectId) {
|
|
||||||
return fetch(`${URI}/${projectId}/users`, { credentials: 'include' })
|
|
||||||
.then(throwIfNotSuccess)
|
|
||||||
.then(response => response.json());
|
|
||||||
}
|
|
||||||
|
|
||||||
function addUserToRole(projectId, roleId, userId) {
|
|
||||||
return fetch(`${URI}/${projectId}/users/${userId}/roles/${roleId}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers,
|
|
||||||
credentials: 'include',
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeUserFromRole(projectId, roleId, userId) {
|
|
||||||
return fetch(`${URI}/${projectId}/users/${userId}/roles/${roleId}`, {
|
|
||||||
method: 'DELETE',
|
|
||||||
headers,
|
|
||||||
credentials: 'include',
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function create(project) {
|
|
||||||
return fetch(URI, {
|
|
||||||
method: 'POST',
|
|
||||||
headers,
|
|
||||||
body: JSON.stringify(project),
|
|
||||||
credentials: 'include',
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(project) {
|
|
||||||
return fetch(`${URI}/${project.id}`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers,
|
|
||||||
body: JSON.stringify(project),
|
|
||||||
credentials: 'include',
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(project) {
|
|
||||||
return fetch(`${URI}/${project.id}`, {
|
|
||||||
method: 'DELETE',
|
|
||||||
headers,
|
|
||||||
credentials: 'include',
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate(id) {
|
|
||||||
return fetch(`${URI}/validate`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers,
|
|
||||||
credentials: 'include',
|
|
||||||
body: JSON.stringify(id),
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchProjectUser(query) {
|
|
||||||
return fetch(
|
|
||||||
`${formatApiPath('api/admin/user-admin/search')}?q=${query}`
|
|
||||||
).then(res => res.json());
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
fetchAll,
|
|
||||||
create,
|
|
||||||
update,
|
|
||||||
remove,
|
|
||||||
validate,
|
|
||||||
fetchAccess,
|
|
||||||
addUserToRole,
|
|
||||||
removeUserFromRole,
|
|
||||||
searchProjectUser,
|
|
||||||
};
|
|
@ -1,29 +0,0 @@
|
|||||||
import { List } from 'immutable';
|
|
||||||
import { RECEIVE_PROJECT, REMOVE_PROJECT, ADD_PROJECT, UPDATE_PROJECT } from './actions';
|
|
||||||
|
|
||||||
const DEFAULT_PROJECTS = [{ id: 'default', name: 'Default', initial: true }];
|
|
||||||
|
|
||||||
function getInitState() {
|
|
||||||
return new List(DEFAULT_PROJECTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
const strategies = (state = getInitState(), action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case RECEIVE_PROJECT:
|
|
||||||
return new List(action.value);
|
|
||||||
case REMOVE_PROJECT: {
|
|
||||||
const index = state.findIndex(item => item.id === action.project.id);
|
|
||||||
return state.remove(index);
|
|
||||||
}
|
|
||||||
case ADD_PROJECT:
|
|
||||||
return state.push(action.project);
|
|
||||||
case UPDATE_PROJECT: {
|
|
||||||
const index = state.findIndex(item => item.id === action.project.id);
|
|
||||||
return state.set(index, action.project);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default strategies;
|
|
@ -1,6 +1,5 @@
|
|||||||
import api from './api';
|
import api from './api';
|
||||||
import { dispatchError } from '../util';
|
import { dispatchError } from '../util';
|
||||||
import { receiveProjects } from '../project/actions';
|
|
||||||
import { receiveStrategies } from '../strategy/actions';
|
import { receiveStrategies } from '../strategy/actions';
|
||||||
|
|
||||||
export const RECEIVE_BOOTSTRAP = 'RECEIVE_CONFIG';
|
export const RECEIVE_BOOTSTRAP = 'RECEIVE_CONFIG';
|
||||||
@ -11,7 +10,6 @@ export function fetchUiBootstrap() {
|
|||||||
api
|
api
|
||||||
.fetchUIBootstrap()
|
.fetchUIBootstrap()
|
||||||
.then(json => {
|
.then(json => {
|
||||||
dispatch(receiveProjects(json.projects));
|
|
||||||
dispatch(receiveStrategies(json.strategies));
|
dispatch(receiveStrategies(json.strategies));
|
||||||
})
|
})
|
||||||
.catch(dispatchError(dispatch, ERROR_RECEIVE_BOOTSTRAP));
|
.catch(dispatchError(dispatch, ERROR_RECEIVE_BOOTSTRAP));
|
||||||
|
Loading…
Reference in New Issue
Block a user