From 2bc37b49c179b2e6a8a72073f2943fe2ba93631a Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 31 May 2023 14:09:25 +0530 Subject: [PATCH 1/2] fix: remove react-recompose --- package.json | 1 - src/api/hubHandler.ts | 2 +- src/api/withHubAPI.ts | 83 --------------- src/redux/actions/index.ts | 1 + src/redux/actions/user.ts | 44 ++++++-- src/redux/reducer/user.ts | 106 ++++++++++++++++++-- src/redux/state/user.ts | 2 +- src/screens/hub/HubManager.tsx | 6 +- src/screens/hub/views/overview/Overview.tsx | 84 +++++----------- src/typings.d.ts | 2 - 10 files changed, 164 insertions(+), 167 deletions(-) delete mode 100644 src/api/withHubAPI.ts diff --git a/package.json b/package.json index 5d35cf6..85e796c 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,6 @@ "lodash.isequal": "^4.5.0", "react": "18.2.0", "react-dom": "18.2.0", - "react-recompose": "0.33.0", "react-redux": "7.2.4", "react-router-dom": "6.6.0", "redux": "4.0.5", diff --git a/src/api/hubHandler.ts b/src/api/hubHandler.ts index d67d2f6..1db7fdd 100644 --- a/src/api/hubHandler.ts +++ b/src/api/hubHandler.ts @@ -26,4 +26,4 @@ export const jupyterHubAPIRequest = ( }, body: data ? JSON.stringify(data) : null }); -} +}; diff --git a/src/api/withHubAPI.ts b/src/api/withHubAPI.ts deleted file mode 100644 index dfb14b5..0000000 --- a/src/api/withHubAPI.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { withProps } from 'react-recompose'; -import { jupyterHubAPIRequest } from './hubHandler'; - -const withHubAPI = withProps(() => ({ - // - // INFO. - info: () => - jupyterHubAPIRequest('/info', 'GET') - .then(data => data.json()), - // USER. - createUser: (names: string[], admin: boolean) => - jupyterHubAPIRequest('/users', 'POST', { names, admin }), - getUser: (name: string) => - jupyterHubAPIRequest('/users/' + name + '?include_stopped_servers', 'GET').then(data => data.json()), - updateUser: (name: string, updatedName: string, admin: boolean) => - jupyterHubAPIRequest('/users/' + name, 'PATCH', { - name: updatedName, - admin - }), - validateUser: (name: string) => - jupyterHubAPIRequest('/users/' + name, 'GET') - .then(data => data.status) - .then(data => (data > 200 ? false : true)), - getUsers: (offset: number, limit: number, name_filter: string) => - jupyterHubAPIRequest( - `/users?include_stopped_servers&offset=${offset}&limit=${limit}&name_filter=${ - name_filter || '' - }`, - 'GET' - ).then(data => data.json()), - refreshUsers: () => jupyterHubAPIRequest('/users', 'GET').then(data => data.json()), - deleteUser: (username: string) => - jupyterHubAPIRequest('/users/' + username, 'DELETE'), - // - // SERVER. - startServer: (name: string, serverName = '') => - jupyterHubAPIRequest('/users/' + name + '/servers/' + (serverName || ''), 'POST'), - startAllServers: (names: string[]) => - names.map((e: string) => jupyterHubAPIRequest('/users/' + e + '/server', 'POST')), - stopServer: (name: string, serverName = '') => - jupyterHubAPIRequest('/users/' + name + '/servers/' + (serverName || ''), 'DELETE'), - stopAllServers: (names: string[]) => - names.map((e: string) => jupyterHubAPIRequest('/users/' + e + '/server', 'DELETE')), - // - // GROUP. - createGroup: (name: string) => - jupyterHubAPIRequest('/groups/' + name, 'POST'), - getGroup: (name: string) => - jupyterHubAPIRequest('/groups/' + name, 'GET').then(data => data.json()), - updateGrouo: (propobject: Record, groupname: string) => - jupyterHubAPIRequest('/groups/' + groupname + '/properties', 'PUT', propobject), - updateGroups: (offset: number, limit: number) => - jupyterHubAPIRequest(`/groups?offset=${offset}&limit=${limit}`, 'GET').then(data => - data.json() - ), - addUserToGroup: (users: string[], groupName: string) => - jupyterHubAPIRequest('/groups/' + groupName + '/users', 'POST', { users }), - removeUserFromGroup: (users: string[], groupName: string) => - jupyterHubAPIRequest('/groups/' + groupName + '/users', 'DELETE', { users }), - refreshGroups: () => - jupyterHubAPIRequest('/groups', 'GET').then(data => data.json()), - deleteGroup: (name: string) => jupyterHubAPIRequest('/groups/' + name, 'DELETE'), - // - // SERVICE. - getServices: () => - jupyterHubAPIRequest('/services', 'GET').then(data => data.json()), - getService: (naeme: string) => - jupyterHubAPIRequest('/services/' + name, 'GET').then(data => data.json()), - // - // PROXY. - getProxyRoutes: () => - jupyterHubAPIRequest('/proxy', 'GET').then(data => data.json()), - // - // HUB. - shutdownHub: () => jupyterHubAPIRequest('/shutdown', 'POST'), - // - // NOOP. - noop: () => { - return null; - }, -})); - -export default withHubAPI; diff --git a/src/redux/actions/index.ts b/src/redux/actions/index.ts index 65707b2..176ecf3 100644 --- a/src/redux/actions/index.ts +++ b/src/redux/actions/index.ts @@ -14,6 +14,7 @@ export const VALIDATE_USER = 'VALIDATE_USER'; export const USER_ERROR = 'USER_ERROR'; export const USER_ERROR_CLEAR = 'USER_ERROR_CLEAR'; export const USER_SUCCESS_CLEAR = 'USER_SUCCESS_CLEAR'; +export const SHUTDOWN_HUB = 'SHUTDOWN_HUB'; export const GROUP_PAGINATION = 'GROUP_PAGINATION'; export const SET_GROUP_OFFSET = 'SET_GROUP_OFFSET'; diff --git a/src/redux/actions/user.ts b/src/redux/actions/user.ts index 2dd4dd9..c46c289 100644 --- a/src/redux/actions/user.ts +++ b/src/redux/actions/user.ts @@ -15,7 +15,8 @@ import { GET_USER, USER_ERROR, USER_ERROR_CLEAR, - USER_SUCCESS_CLEAR + USER_SUCCESS_CLEAR, + SHUTDOWN_HUB } from './index'; export const setUserOffset = (offset: number) => async ( @@ -107,7 +108,10 @@ export const addUsers = (usernames: string[], admin: boolean) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/users', 'POST', { usernames, admin }); + const res = await jupyterHubAPIRequest('/users', 'POST', { + usernames, + admin + }); if (res.status >= 400) { if (res.status === 409) { throw new Error('User already exists'); @@ -210,7 +214,8 @@ export const startServer = (name: string, serverName: string) => async ( throw new Error('Error starting user: ' + res.statusText); } dispatch({ - type: START_SERVER + type: START_SERVER, + payload: { name, serverName } }); } catch (err: any) { dispatch({ @@ -232,7 +237,8 @@ export const stopServer = (name: string, serverName: string) => async ( throw new Error('Error stopping server: ' + res.statusText); } dispatch({ - type: STOP_SERVER + type: STOP_SERVER, + payload: { name, serverName } }); } catch (err: any) { dispatch({ @@ -254,7 +260,8 @@ export const startAllServers = (names: string[]) => async ( return; }); dispatch({ - type: START_ALL_SERVERS + type: START_ALL_SERVERS, + payload: names }); } catch (err: any) { dispatch({ @@ -269,14 +276,37 @@ export const stopAllServers = (names: string[]) => async ( ): Promise => { try { names.map(async (e: string) => { - const res = await jupyterHubAPIRequest('/users/' + e + '/server', 'DELETE'); + const res = await jupyterHubAPIRequest( + '/users/' + e + '/server', + 'DELETE' + ); if (res.status >= 400) { throw new Error('Error stopping servers: ' + res.statusText); } return; }); dispatch({ - type: STOP_ALL_SERVERS + type: STOP_ALL_SERVERS, + payload: names + }); + } catch (err: any) { + dispatch({ + type: USER_ERROR, + payload: { msg: err.message } + }); + } +}; + +export const shutdownHub = () => async ( + dispatch: Dispatch +): Promise => { + try { + const res = await jupyterHubAPIRequest('/shutdown', 'POST'); + if (res.status >= 400) { + throw new Error('Error shutting down hub: ' + res.statusText); + } + dispatch({ + type: SHUTDOWN_HUB }); } catch (err: any) { dispatch({ diff --git a/src/redux/reducer/user.ts b/src/redux/reducer/user.ts index af2df71..0e28586 100644 --- a/src/redux/reducer/user.ts +++ b/src/redux/reducer/user.ts @@ -14,7 +14,8 @@ import { GET_USER, USER_ERROR, USER_ERROR_CLEAR, - USER_SUCCESS_CLEAR + USER_SUCCESS_CLEAR, + SHUTDOWN_HUB } from './../actions'; function userReducer( @@ -58,7 +59,8 @@ function userReducer( case REFRESH_USERS: return { ...state, - users: payload + users: payload.items, + user_page: payload._pagination }; // make sure you go redirect after these: case ADD_USERS: @@ -77,12 +79,102 @@ function userReducer( ...state, success: 'User deleted successfully!' }; + case SHUTDOWN_HUB: + return { + ...state, + success: 'Jupyterhub shutdown successful!' + }; // make sure you call user pagination after these: - case START_SERVER: - case STOP_SERVER: - case START_ALL_SERVERS: - case STOP_ALL_SERVERS: - return state; + case START_SERVER: { + const updatedUsers = state.users.map(user => { + if (user.name === payload.name) { + return { + ...user, + servers: { + ...user.servers, + [payload.serverName]: { + ...user.servers[payload.serverName], + ready: true, + stopped: false + } + } + }; + } + return user; + }); + return { + ...state, + users: updatedUsers, + success: 'Server started successfully!' + }; + } + case STOP_SERVER: { + const updatedUsers = state.users.map(user => { + if (user.name === payload.name) { + return { + ...user, + servers: { + ...user.servers, + [payload.serverName]: { + ...user.servers[payload.serverName], + ready: false, + stopped: true + } + } + }; + } + return user; + }); + return { + ...state, + users: updatedUsers, + success: 'Server stopped successfully!' + }; + } + case START_ALL_SERVERS: { + const updatedUsers = state.users.map(user => { + if (payload.includes(user.name)) { + return { + ...user, + servers: { + '': { + ...user.servers[''], + ready: true, + stopped: false + } + } + }; + } + return user; + }); + return { + ...state, + users: updatedUsers, + success: 'Servers started successfully!' + }; + } + case STOP_ALL_SERVERS: { + const updatedUsers = state.users.map(user => { + if (payload.includes(user.name)) { + return { + ...user, + servers: { + '': { + ...user.servers[''], + ready: false, + stopped: true + } + } + }; + } + return user; + }); + return { + ...state, + users: updatedUsers, + success: 'Servers stopped successfully!' + }; + } // error case USER_ERROR: return { diff --git a/src/redux/state/user.ts b/src/redux/state/user.ts index abb14c4..dced720 100644 --- a/src/redux/state/user.ts +++ b/src/redux/state/user.ts @@ -42,5 +42,5 @@ export type User = { pending: boolean | null; roles: string[]; server: Server | null; - servers: Server[]; + servers: Record; }; diff --git a/src/screens/hub/HubManager.tsx b/src/screens/hub/HubManager.tsx index 1395eb5..a5d848f 100644 --- a/src/screens/hub/HubManager.tsx +++ b/src/screens/hub/HubManager.tsx @@ -1,4 +1,3 @@ -import { compose } from 'react-recompose'; import { Routes, Route } from 'react-router-dom'; import Breadcrumbs from '../../components/Breadcrumbs'; import HubSidebar from '../../components/HubSidebar'; @@ -8,11 +7,8 @@ import GroupEdit from './views/group/GroupEdit'; import Users from './views/user/Users'; import UserEdit from './views/user/UserEdit'; import Servers from './views/server/Servers'; -import withHubAPI from '../../api/withHubAPI'; import { Box, PageLayout } from '@primer/react'; -const OverviewCompose = compose(withHubAPI)(Overview); - const HubManager = (): JSX.Element => { return ( <> @@ -23,7 +19,7 @@ const HubManager = (): JSX.Element => { - } /> + } /> } /> } /> } /> diff --git a/src/screens/hub/views/overview/Overview.tsx b/src/screens/hub/views/overview/Overview.tsx index e015790..09f64b0 100644 --- a/src/screens/hub/views/overview/Overview.tsx +++ b/src/screens/hub/views/overview/Overview.tsx @@ -18,17 +18,16 @@ import { MainState } from '../../../../redux/store'; import { setUserOffset, setNameFilter, - getUsersPagination + getUsersPagination, + shutdownHub, + startServer, + stopServer, + startAllServers, + stopAllServers } from '../../../../redux/actions/user'; import { UserState } from '../../../../redux/state/user'; -const Overview = (props: { - shutdownHub: any; - startServer: any; - stopServer: any; - startAll: any; - stopAll: any; -}): JSX.Element => { +const Overview = (): JSX.Element => { const navigate = useNavigate(); const dispatch = useDispatch(); @@ -39,8 +38,7 @@ const Overview = (props: { const limit = user_page ? user_page.limit : 10; const total = user_page ? user_page.total : undefined; - const { shutdownHub, startServer, stopServer, startAll, stopAll } = props; - + console.log(users); useEffect(() => { dispatch(getUsersPagination(offset, limit, name_filter)); }, [getUsersPagination, offset, limit, name_filter]); @@ -53,29 +51,6 @@ const Overview = (props: { dispatch(setNameFilter(event.target.value)); }, 300); - const startAllServers = () => { - Promise.all(startAll(users.map((e: { name: any }) => e.name))) - .then(res => { - return res; - }) - .then(res => { - dispatch(getUsersPagination(offset, limit, name_filter)); - return res; - }); - }; - - const stopAllServers = () => { - Promise.all(stopAll(users.map((e: { name: any }) => e.name))) - .then(res => { - res.filter(e => !e.ok); - return res; - }) - .then(res => { - dispatch(getUsersPagination(offset, limit, name_filter)); - return res; - }); - }; - const StopServerButton = ({ serverName, userName @@ -90,18 +65,7 @@ const Overview = (props: { disabled={isDisabled} onClick={() => { setIsDisabled(true); - stopServer(userName, serverName) - .then((res: { status: number }) => { - if (res.status < 300) { - dispatch(getUsersPagination(offset, limit, name_filter)); - } else { - setIsDisabled(false); - } - return res; - }) - .catch(() => { - setIsDisabled(false); - }); + dispatch(stopServer(userName, serverName)); }} > Stop Server @@ -123,18 +87,7 @@ const Overview = (props: { disabled={isDisabled} onClick={() => { setIsDisabled(true); - startServer(userName, serverName) - .then((res: { status: number }) => { - if (res.status < 300) { - dispatch(getUsersPagination(offset, limit, name_filter)); - } else { - setIsDisabled(false); - } - return res; - }) - .catch(() => { - setIsDisabled(false); - }); + dispatch(startServer(userName, serverName)); }} > Start Server @@ -335,11 +288,20 @@ const Overview = (props: { block sx={{ mb: 3 }} variant="primary" - onClick={startAllServers} + onClick={() => { + dispatch(startAllServers(users.map((e: { name: any }) => e.name))); + }} > Start All Servers - diff --git a/src/typings.d.ts b/src/typings.d.ts index f9c095d..46a8d46 100755 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -1,7 +1,5 @@ /// -declare module 'react-recompose'; - declare module "*.jpg" { const value: any; export default value; From 83aabcf1f087244e2be9492ff2f3cc5307bc4d5e Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 31 May 2023 15:39:05 +0530 Subject: [PATCH 2/2] chore: use jupyterhubapi --- src/api/jupyterHubAPI.ts | 238 +++++++++++++++++++++++++++++++++++++ src/redux/actions/group.ts | 80 ++----------- src/redux/actions/user.ts | 101 +++------------- 3 files changed, 266 insertions(+), 153 deletions(-) create mode 100644 src/api/jupyterHubAPI.ts diff --git a/src/api/jupyterHubAPI.ts b/src/api/jupyterHubAPI.ts new file mode 100644 index 0000000..cfb2588 --- /dev/null +++ b/src/api/jupyterHubAPI.ts @@ -0,0 +1,238 @@ +import { jupyterHubAPIRequest } from './hubHandler'; + +const jupyterHubApi = { + // INFO + info: (): Promise => jupyterHubAPIRequest('/info', 'GET'), + // USER + createUser: (names: string[], admin: boolean): Promise => + jupyterHubAPIRequest('/users', 'POST', { names, admin }), + getUser: async (name: string): Promise => { + const res = await jupyterHubAPIRequest( + '/users/' + name + '?include_stopped_servers', + 'GET' + ); + if (res.status >= 400) { + if (res.status === 404) { + throw new Error("User doesn't exist"); + } else { + throw new Error('Error fetching user: ' + res.statusText); + } + } + const payload = await res.json(); + return payload; + }, + addUsers: async (usernames: string[], admin: boolean): Promise => { + const res = await jupyterHubAPIRequest('/users', 'POST', { + usernames, + admin + }); + if (res.status >= 400) { + if (res.status === 409) { + throw new Error('User already exists'); + } else { + throw new Error('Error creating user: ' + res.statusText); + } + } + }, + updateUser: async ( + name: string, + updatedName: string, + admin: boolean + ): Promise => { + const res = await jupyterHubAPIRequest('/users/' + name, 'PATCH', { + name: updatedName, + admin + }); + if (res.status >= 400) { + if (res.status === 400) { + throw new Error('Username is taken.'); + } else { + throw new Error('Error editing user: ' + res.statusText); + } + } + const payload = await res.json(); + return payload; + }, + validateUser: (name: string): Promise => + jupyterHubAPIRequest('/users/' + name, 'GET') + .then(data => data.status) + .then(data => (data > 200 ? false : true)), + getUsers: async ( + offset: number, + limit: number, + name_filter: string + ): Promise => { + const res = await jupyterHubAPIRequest( + `/users?include_stopped_servers&offset=${offset}&limit=${limit}&name_filter=${ + name_filter || '' + }`, + 'GET' + ); + if (res.status >= 400) { + throw new Error('Error fetching users: ' + res.statusText); + } + const payload = await res.json(); + return payload; + }, + refreshUsers: async (): Promise => { + const res = await jupyterHubAPIRequest('/users', 'GET'); + if (res.status >= 400) { + throw new Error('Error refreshing users: ' + res.statusText); + } + const payload = await res.json(); + return payload; + }, + deleteUser: async (username: string): Promise => { + const res = await jupyterHubAPIRequest('/users/' + username, 'DELETE'); + if (res.status >= 400) { + throw new Error('Error deleting user: ' + res.statusText); + } + }, + // SERVER + startServer: async (name: string, serverName = ''): Promise => { + const res = await jupyterHubAPIRequest( + '/users/' + name + '/servers/' + (serverName || ''), + 'POST' + ); + if (res.status >= 400) { + throw new Error('Error starting user: ' + res.statusText); + } + }, + startAllServers: async (names: string[]): Promise => { + const requests = names.map(e => + jupyterHubAPIRequest('/users/' + e + '/server', 'POST') + ); + const res = await Promise.all(requests); + if (res.some(response => response.status >= 400)) { + throw new Error('Error starting servers'); + } + }, + stopServer: async (name: string, serverName = ''): Promise => { + const res = await jupyterHubAPIRequest( + '/users/' + name + '/servers/' + (serverName || ''), + 'DELETE' + ); + if (res.status >= 400) { + throw new Error('Error stopping server: ' + res.statusText); + } + }, + stopAllServers: async (names: string[]): Promise => { + const requests = names.map(e => + jupyterHubAPIRequest('/users/' + e + '/server', 'DELETE') + ); + const res = await Promise.all(requests); + if (res.some(response => response.status >= 400)) { + throw new Error('Error starting servers'); + } + }, + // GROUP + createGroup: async (name: string): Promise => { + const res = await jupyterHubAPIRequest('/groups/' + name, 'POST'); + if (res.status >= 400) { + if (res.status === 409) { + throw new Error('Group already exists'); + } else { + throw new Error('Error creating group: ' + res.statusText); + } + } + }, + getGroup: async (name: string): Promise => { + const res = await jupyterHubAPIRequest('/groups/' + name, 'GET'); + if (res.status >= 400) { + if (res.status === 404) { + throw new Error("Group doesn't exist"); + } else { + throw new Error('Error fetching group: ' + res.statusText); + } + } + const payload = await res.json(); + return payload; + }, + updateGroup: async ( + propobject: Record, + groupname: string + ): Promise => { + const res = await jupyterHubAPIRequest( + '/groups/' + groupname + '/properties', + 'PUT', + propobject + ); + if (res.status >= 400) { + throw new Error('Error updating group properties: ' + res.statusText); + } + const payload = await res.json(); + return payload; + }, + updateGroups: async (offset: number, limit: number): Promise => { + const res = await jupyterHubAPIRequest( + `/groups?offset=${offset}&limit=${limit}`, + 'GET' + ); + if (res.status >= 400) { + throw new Error('Error fetching groups: ' + res.statusText); + } + const payload = await res.json(); + return payload; + }, + addUsersToGroup: async (users: string[], groupName: string): Promise => { + const res = await jupyterHubAPIRequest( + '/groups/' + groupName + '/users', + 'POST', + { users } + ); + if (res.status >= 400) { + throw new Error(`Error adding user to group ${res.statusText}`); + } + const payload = await res.json(); + return payload; + }, + removeUsersFromGroup: async ( + users: string[], + groupName: string + ): Promise => { + const res = await jupyterHubAPIRequest( + '/groups/' + groupName + '/users', + 'DELETE', + { + users + } + ); + if (res.status >= 400) { + throw new Error('Error removing users: ' + res.statusText); + } + const payload = await res.json(); + return payload; + }, + refreshGroups: async (): Promise => { + const res = await jupyterHubAPIRequest('/groups', 'GET'); + if (res.status >= 400) { + throw new Error('Error refreshing groups: ' + res.statusText); + } + const payload = await res.json(); + return payload; + }, + deleteGroup: async (name: string): Promise => { + const res = await jupyterHubAPIRequest('/groups/' + name, 'DELETE'); + if (res.status >= 400) { + throw new Error('Error deleting group: ' + res.statusText); + } + }, + // SERVICE + getServices: (): Promise => + jupyterHubAPIRequest('/services', 'GET'), + getService: (naeme: string): Promise => + jupyterHubAPIRequest('/services/' + name, 'GET'), + // PROXY + getProxyRoutes: (): Promise => + jupyterHubAPIRequest('/proxy', 'GET'), + // HUB + shutdownHub: async (): Promise => { + const res = await jupyterHubAPIRequest('/shutdown', 'POST'); + if (res.status >= 400) { + throw new Error('Error shutting down hub: ' + res.statusText); + } + } + // +}; + +export default jupyterHubApi; diff --git a/src/redux/actions/group.ts b/src/redux/actions/group.ts index 95ce770..71eb1f9 100644 --- a/src/redux/actions/group.ts +++ b/src/redux/actions/group.ts @@ -1,5 +1,5 @@ import { Dispatch, AnyAction } from 'redux'; -import { jupyterHubAPIRequest } from '../../api/hubHandler'; +import jupyterHubApi from '../../api/jupyterHubAPI'; import { GROUP_PAGINATION, SET_GROUP_OFFSET, @@ -35,15 +35,7 @@ export const getCurrentGroup = (groupname: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/groups/' + groupname, 'GET'); - if (res.status >= 400) { - if (res.status === 404) { - throw new Error("Group doesn't exist"); - } else { - throw new Error('Error fetching group: ' + res.statusText); - } - } - const payload = await res.json(); + const payload = await jupyterHubApi.getGroup(groupname); dispatch({ type: GET_GROUP, payload @@ -60,14 +52,7 @@ export const getGroupsPagination = (offset: number, limit: number) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest( - `/groups?offset=${offset}&limit=${limit}`, - 'GET' - ); - if (res.status >= 400) { - throw new Error('Error fetching groups: ' + res.statusText); - } - const payload = await res.json(); + const payload = await jupyterHubApi.updateGroups(offset, limit); dispatch({ type: GROUP_PAGINATION, payload @@ -84,14 +69,7 @@ export const createGroup = (groupname: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/groups/' + groupname, 'POST'); - if (res.status >= 400) { - if (res.status === 409) { - throw new Error('Group already exists'); - } else { - throw new Error('Error creating group: ' + res.statusText); - } - } + await jupyterHubApi.createGroup(groupname); dispatch({ type: CREATE_GROUP }); @@ -107,10 +85,7 @@ export const deleteGroup = (groupname: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/groups/' + groupname, 'DELETE'); - if (res.status >= 400) { - throw new Error('Error deleting group: ' + res.statusText); - } + await jupyterHubApi.deleteGroup(groupname); dispatch({ type: DELETE_GROUP }); @@ -127,15 +102,7 @@ export const updateGroupProps = ( propobject: Record ) => async (dispatch: Dispatch): Promise => { try { - const res = await jupyterHubAPIRequest( - '/groups/' + groupname + '/properties', - 'PUT', - propobject - ); - if (res.status >= 400) { - throw new Error('Error updating group properties: ' + res.statusText); - } - const payload = await res.json(); + const payload = await jupyterHubApi.updateGroup(propobject, groupname); dispatch({ type: UPDATE_GROUP_PROPS, payload @@ -152,11 +119,7 @@ export const refreshGroups = () => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/groups', 'GET'); - if (res.status >= 400) { - throw new Error('Error refreshing groups: ' + res.statusText); - } - const payload = await res.json(); + const payload = await jupyterHubApi.refreshGroups(); dispatch({ type: REFRESH_GROUPS, payload @@ -173,15 +136,7 @@ export const removeFromGroup = (groupname: string, users: string[]) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest( - '/groups/' + groupname + '/users', - 'DELETE', - { users } - ); - if (res.status >= 400) { - throw new Error('Error removing users: ' + res.statusText); - } - const payload = await res.json(); + const payload = await jupyterHubApi.removeUsersFromGroup(users, groupname); dispatch({ type: REMOVE_FROM_GROUP, payload @@ -198,21 +153,12 @@ export const addUserToGroup = (groupname: string, username: string) => async ( dispatch: Dispatch ): Promise => { try { - const resStatus = (await jupyterHubAPIRequest('/users/' + username, 'GET')).status; - if (resStatus === 200) { - const res = await jupyterHubAPIRequest( - '/groups/' + groupname + '/users', - 'POST', - { - users: [username] - } + const userExists = await jupyterHubApi.validateUser(username); + if (userExists) { + const payload = await jupyterHubApi.addUsersToGroup( + [username], + groupname ); - if (res.status >= 400) { - throw new Error( - `Error adding user ${username} to group ${res.statusText}` - ); - } - const payload = await res.json(); dispatch({ type: ADD_TO_GROUP, payload diff --git a/src/redux/actions/user.ts b/src/redux/actions/user.ts index c46c289..8280f10 100644 --- a/src/redux/actions/user.ts +++ b/src/redux/actions/user.ts @@ -1,5 +1,5 @@ import { Dispatch, AnyAction } from 'redux'; -import { jupyterHubAPIRequest } from '../../api/hubHandler'; +import jupyterHubApi from '../../api/jupyterHubAPI'; import { USER_PAGINATION, SET_USER_OFFSET, @@ -55,15 +55,7 @@ export const getCurrentUser = (username: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/users/' + username, 'GET'); - if (res.status >= 400) { - if (res.status === 404) { - throw new Error("User doesn't exist"); - } else { - throw new Error('Error fetching user: ' + res.statusText); - } - } - const payload = await res.json(); + const payload = await jupyterHubApi.getUser(username); dispatch({ type: GET_USER, payload @@ -82,16 +74,7 @@ export const getUsersPagination = ( name_filter: string ) => async (dispatch: Dispatch): Promise => { try { - const res = await jupyterHubAPIRequest( - `/users?include_stopped_servers&offset=${offset}&limit=${limit}&name_filter=${ - name_filter || '' - }`, - 'GET' - ); - if (res.status >= 400) { - throw new Error('Error fetching users: ' + res.statusText); - } - const payload = await res.json(); + const payload = await jupyterHubApi.getUsers(offset, limit, name_filter); dispatch({ type: USER_PAGINATION, payload @@ -108,17 +91,7 @@ export const addUsers = (usernames: string[], admin: boolean) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/users', 'POST', { - usernames, - admin - }); - if (res.status >= 400) { - if (res.status === 409) { - throw new Error('User already exists'); - } else { - throw new Error('Error creating user: ' + res.statusText); - } - } + await jupyterHubApi.addUsers(usernames, admin); dispatch({ type: ADD_USERS }); @@ -134,10 +107,7 @@ export const deleteUser = (username: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/users/' + username, 'DELETE'); - if (res.status >= 400) { - throw new Error('Error deleting user: ' + res.statusText); - } + await jupyterHubApi.deleteUser(username); dispatch({ type: DELETE_USER }); @@ -155,18 +125,11 @@ export const editUser = ( admin: boolean ) => async (dispatch: Dispatch): Promise => { try { - const res = await jupyterHubAPIRequest('/users/' + username, 'PATCH', { - name: updated_username, + const payload = await jupyterHubApi.updateUser( + username, + updated_username, admin - }); - if (res.status >= 400) { - if (res.status === 400) { - throw new Error('Username is taken.'); - } else { - throw new Error('Error editing user: ' + res.statusText); - } - } - const payload = await res.json(); + ); dispatch({ type: EDIT_USER, payload @@ -185,11 +148,7 @@ export const refreshUsers = () => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/users', 'GET'); - if (res.status >= 400) { - throw new Error('Error refreshing users: ' + res.statusText); - } - const payload = await res.json(); + const payload = await jupyterHubApi.refreshUsers(); dispatch({ type: REFRESH_USERS, payload @@ -206,13 +165,7 @@ export const startServer = (name: string, serverName: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest( - '/users/' + name + '/servers/' + (serverName || ''), - 'POST' - ); - if (res.status >= 400) { - throw new Error('Error starting user: ' + res.statusText); - } + await jupyterHubApi.startServer(name, serverName); dispatch({ type: START_SERVER, payload: { name, serverName } @@ -229,13 +182,7 @@ export const stopServer = (name: string, serverName: string) => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest( - '/users/' + name + '/servers/' + (serverName || ''), - 'DELETE' - ); - if (res.status >= 400) { - throw new Error('Error stopping server: ' + res.statusText); - } + await jupyterHubApi.stopServer(name, serverName); dispatch({ type: STOP_SERVER, payload: { name, serverName } @@ -252,13 +199,7 @@ export const startAllServers = (names: string[]) => async ( dispatch: Dispatch ): Promise => { try { - names.map(async (e: string) => { - const res = await jupyterHubAPIRequest('/users/' + e + '/server', 'POST'); - if (res.status >= 400) { - throw new Error('Error starting servers: ' + res.statusText); - } - return; - }); + await jupyterHubApi.startAllServers(names); dispatch({ type: START_ALL_SERVERS, payload: names @@ -275,16 +216,7 @@ export const stopAllServers = (names: string[]) => async ( dispatch: Dispatch ): Promise => { try { - names.map(async (e: string) => { - const res = await jupyterHubAPIRequest( - '/users/' + e + '/server', - 'DELETE' - ); - if (res.status >= 400) { - throw new Error('Error stopping servers: ' + res.statusText); - } - return; - }); + await jupyterHubApi.stopAllServers(names); dispatch({ type: STOP_ALL_SERVERS, payload: names @@ -301,10 +233,7 @@ export const shutdownHub = () => async ( dispatch: Dispatch ): Promise => { try { - const res = await jupyterHubAPIRequest('/shutdown', 'POST'); - if (res.status >= 400) { - throw new Error('Error shutting down hub: ' + res.statusText); - } + await jupyterHubApi.shutdownHub(); dispatch({ type: SHUTDOWN_HUB });