1
0
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:
Fredrik Strand Oseberg 2022-02-10 23:45:30 +01:00 committed by GitHub
parent 821c383edd
commit de8b3352e7
14 changed files with 13 additions and 204 deletions

View File

@ -54,7 +54,7 @@ const ProjectSelect = ({ currentProjectId, updateCurrentProject, ...rest }) => {
];
};
const { updateSetting, fetchProjects, ...passDown } = rest;
const { updateSetting, ...passDown } = rest;
return (
<React.Fragment>

View File

@ -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);

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { MenuItem, Typography } from '@material-ui/core';
import DropdownMenu from '../../../common/DropdownMenu/DropdownMenu';
import ProjectSelect from '../../../common/ProjectSelect';
import ProjectSelect from '../../../common/ProjectSelect/ProjectSelect';
import { useStyles } from './styles';
import useLoading from '../../../../hooks/useLoading';
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
@ -29,7 +29,8 @@ const FeatureToggleListActions = ({
};
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 = () =>
sortOptions.map(option => (
@ -63,7 +64,9 @@ const FeatureToggleListActions = ({
show={
<ProjectSelect
currentProjectId={filter.project}
updateCurrentProject={project => setFilter(prev => ({ ...prev, project }))}
updateCurrentProject={project =>
setFilter(prev => ({ ...prev, project }))
}
style={{
textTransform: 'lowercase',
fontWeight: 'normal',

View File

@ -12,7 +12,7 @@ jest.mock('../FeatureToggleListItem', () => ({
default: 'ListItem',
}));
jest.mock('../../../common/ProjectSelect');
jest.mock('../../../common/ProjectSelect/ProjectSelect');
test('renders correctly with one feature', () => {
const features = [

View File

@ -7,7 +7,7 @@ import useProject from '../../../../hooks/api/getters/useProject/useProject';
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
import useToast from '../../../../hooks/useToast';
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
import { UPDATE_PROJECT } from '../../../../store/project/actions';
import { UPDATE_PROJECT } from '../../../providers/AccessProvider/permissions';
const EditProject = () => {
const { uiConfig } = useUiConfig();
@ -90,10 +90,7 @@ const EditProject = () => {
clearErrors={clearErrors}
validateIdUniqueness={validateIdUniqueness}
>
<PermissionButton
permission={UPDATE_PROJECT}
type="submit"
>
<PermissionButton permission={UPDATE_PROJECT} type="submit">
Edit project
</PermissionButton>
</ProjectForm>

View File

@ -16,8 +16,8 @@ import { ProjectAccess } from '../ProjectAccess/ProjectAccess';
import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment';
import ProjectOverview from './ProjectOverview';
import ProjectHealth from './ProjectHealth/ProjectHealth';
import { UPDATE_PROJECT } from '../../../store/project/actions';
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
import { UPDATE_PROJECT } from '../../providers/AccessProvider/permissions';
const Project = () => {
const { id, activeTab } = useParams<{ id: string; activeTab: string }>();

View File

@ -8,7 +8,6 @@ import { useCommonStyles } from '../../../../common.styles';
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
import PercentageCircle from '../../../common/PercentageCircle/PercentageCircle';
import PermissionIconButton from '../../../common/PermissionIconButton/PermissionIconButton';
import { UPDATE_PROJECT } from '../../../../store/project/actions';
import ConditionallyRender from '../../../common/ConditionallyRender';
import {
Accordion,
@ -16,6 +15,7 @@ import {
AccordionDetails,
AccordionSummary,
} from '@material-ui/core';
import { UPDATE_PROJECT } from '../../../providers/AccessProvider/permissions';
interface IProjectInfoProps {
id: string;

View File

@ -11,8 +11,8 @@ import useProjects from '../../../hooks/api/getters/useProjects/useProjects';
import { Delete, Edit } from '@material-ui/icons';
import { getProjectEditPath } from '../../../utils/route-path-helpers';
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
import { UPDATE_PROJECT } from '../../../store/project/actions';
import useToast from '../../../hooks/useToast';
import { UPDATE_PROJECT } from '../../providers/AccessProvider/permissions';
interface IProjectCardProps {
name: string;
featureCount: number;

View File

@ -16,12 +16,6 @@ import {
UPDATE_STRATEGY_SUCCESS,
} from '../strategy/actions';
import {
ERROR_REMOVING_PROJECT,
ERROR_ADD_PROJECT,
ERROR_UPDATE_PROJECT,
} from '../project/actions';
import { UPDATE_APPLICATION_FIELD } from '../application/actions';
import { FORBIDDEN } from '../util';
@ -51,9 +45,6 @@ const strategies = (state = getInitState(), action) => {
case ERROR_UPDATING_STRATEGY:
case ERROR_CREATING_STRATEGY:
case ERROR_RECEIVE_STRATEGIES:
case ERROR_REMOVING_PROJECT:
case ERROR_UPDATE_PROJECT:
case ERROR_ADD_PROJECT:
return addErrorIfNotAlreadyInList(state, action.error.message);
case FORBIDDEN:
return addErrorIfNotAlreadyInList(

View File

@ -3,7 +3,6 @@ import features from './feature-toggle';
import strategies from './strategy';
import error from './error';
import applications from './application';
import projects from './project';
import apiCalls from './api-calls';
const unleashStore = combineReducers({
@ -11,7 +10,6 @@ const unleashStore = combineReducers({
strategies,
error,
applications,
projects,
apiCalls,
});

View File

@ -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 });
}

View File

@ -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,
};

View File

@ -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;

View File

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