Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display Stories Users in Admin Panel #2763

Merged
merged 73 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
d30b434
chore: initial copy from userConfigPanel
zsiggg Sep 3, 2023
4f3847d
Merge branch 'master' into feature/stories-users
zsiggg Sep 20, 2023
c0a6cb2
feat: add stories user tab in admin panel
zsiggg Oct 11, 2023
21108aa
chore: add type AdminPanelStoriesUsers
zsiggg Oct 11, 2023
40d61d3
refactor: update types and parameters
zsiggg Oct 11, 2023
e28c35e
refactor: update AdminPanelStoriesUsers type
zsiggg Oct 12, 2023
8524723
feat: fetch users from stories db
zsiggg Oct 12, 2023
e0592f7
feat: enable role column
zsiggg Oct 12, 2023
ed659a2
chore: update csv title and columns
zsiggg Oct 12, 2023
042c88a
Merge branch 'master' of https://github.com/source-academy/frontend i…
zsiggg Feb 5, 2024
6d76d3a
Merge master
zsiggg Feb 5, 2024
2416bf1
chore: fix merge conflicts
zsiggg Feb 5, 2024
2c421ab
fix: errors from merging and dep version bumps
zsiggg Feb 12, 2024
e693a90
Merge branch 'master' into feature/stories-users
zsiggg Feb 12, 2024
1e0e09b
style: run yarn format
zsiggg Feb 12, 2024
c695a2c
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 18, 2024
3ffbe76
feat: add deleting user and updating user roles
zsiggg Feb 18, 2024
c97c3e5
refactor: linter changes and dialog box text
zsiggg Feb 18, 2024
435e3f5
Merge branch 'feature/stories-users' of https://github.com/source-aca…
zsiggg Feb 18, 2024
3a33585
style: run yarn format
zsiggg Feb 18, 2024
7cf0c0b
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 20, 2024
93d3c8b
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 21, 2024
da8c0b6
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 21, 2024
3e63d0d
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 21, 2024
e468a29
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 23, 2024
08b8479
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 23, 2024
5a86138
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 23, 2024
b9f7c84
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 23, 2024
70b6562
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 24, 2024
09a3daf
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 24, 2024
d72d0e3
Merge branch 'master' into feature/stories-users
RichDom2185 Feb 24, 2024
5282963
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 1, 2024
5b8a894
Merge branch 'master' into feature/stories-users
martin-henz Mar 3, 2024
efb152e
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 Mar 17, 2024
3ef947d
Migrate new actions to RTK
RichDom2185 Mar 17, 2024
6b8e6ef
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 17, 2024
2ca78c9
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 17, 2024
35af256
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 18, 2024
05c7748
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 21, 2024
cdeb639
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 22, 2024
56a275a
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 Mar 23, 2024
2230362
Migrate new actions to RTK
RichDom2185 Mar 23, 2024
f8881a9
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 24, 2024
11174d6
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 24, 2024
cd7d2bf
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 Mar 26, 2024
4a3ac76
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 26, 2024
856be3d
Merge branch 'master' into feature/stories-users
RichDom2185 Mar 28, 2024
7e3baa6
Merge branch 'master' into feature/stories-users
martin-henz Mar 31, 2024
fbb1676
Merge branch 'master' into feature/stories-users
RichDom2185 Apr 1, 2024
b9a39b3
Merge branch 'master' into feature/stories-users
RichDom2185 Apr 2, 2024
e66722b
Merge branch 'master' into feature/stories-users
RichDom2185 Apr 10, 2024
3bd2038
Merge branch 'master' into feature/stories-users
RichDom2185 Apr 13, 2024
520c8ce
Fix compile errors post-merge
RichDom2185 Apr 13, 2024
0281a92
Merge branch 'master' into feature/stories-users
RichDom2185 Apr 14, 2024
e98897e
Merge branch 'master' into feature/stories-users
RichDom2185 Apr 21, 2024
13a9097
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 May 1, 2024
fee46df
Merge branch 'master' into feature/stories-users
RichDom2185 May 3, 2024
a0cd88b
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 May 5, 2024
fc5b400
Migrate new saga handlers post-merge
RichDom2185 May 5, 2024
b8dc494
Reformat new saga handlers post-merge
RichDom2185 May 5, 2024
43589f3
Fix format
RichDom2185 May 5, 2024
eeb02d3
Fix incorrect action creator signature
RichDom2185 May 5, 2024
55effbf
Fix type errors
RichDom2185 May 5, 2024
b5ff92b
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 May 6, 2024
d9fb5dd
Fix format
RichDom2185 May 6, 2024
264a9a1
Merge branch 'master' into feature/stories-users
RichDom2185 May 12, 2024
094ad11
Fix incorrect merge resolution
RichDom2185 May 12, 2024
6033907
Update stories `RolesCell`
RichDom2185 May 12, 2024
55b0125
Update StoriesUserActionsCell.tsx
RichDom2185 May 12, 2024
bd24803
Update StoriesUserConfigPanel.tsx
RichDom2185 May 12, 2024
8e5ec37
Remove unnecessary typecast
RichDom2185 May 12, 2024
1595109
Fix incorrect type definition
RichDom2185 May 12, 2024
6431440
Remove unnecessary type annotations
RichDom2185 May 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/commons/application/ApplicationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,8 @@ export const defaultStories: StoriesState = {
storyList: [],
currentStoryId: null,
currentStory: null,
envs: {}
envs: {},
storiesUsers: []
};

export const createDefaultStoriesEnv = (
Expand Down
18 changes: 16 additions & 2 deletions src/commons/application/actions/SessionActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ import {
NotificationFilterFunction
} from '../../notificationBadge/NotificationBadgeTypes';
import { generateOctokitInstance } from '../../utils/GitHubPersistenceHelper';
import { Role } from '../ApplicationTypes';
import { Role, StoriesRole } from '../ApplicationTypes';
import {
AdminPanelCourseRegistration,
CourseRegistration,
DELETE_STORIES_USER_USER_GROUPS,
NotificationConfiguration,
NotificationPreference,
TimeOption,
Tokens,
UPDATE_ASSESSMENT,
UPDATE_COURSE_RESEARCH_AGREEMENT,
UPDATE_STORIES_USER_ROLE,
UPDATE_TOTAL_XP,
UpdateCourseConfiguration,
User
Expand Down Expand Up @@ -174,11 +176,23 @@ export const updateCourseResearchAgreement = createAction(
(agreedToResearch: boolean) => ({ payload: { agreedToResearch } })
);

export const updateStoriesUserRole = createAction(
UPDATE_STORIES_USER_ROLE,
(userId: number, role: StoriesRole) => ({ payload: { userId, role } })
);

export const deleteStoriesUserUserGroups = createAction(
DELETE_STORIES_USER_USER_GROUPS,
(userId: number) => ({ payload: { userId } })
);

// For compatibility with existing code (actions helper)
export default {
...newActions,
updateTotalXp,
updateAssessment,
...newActions2,
updateCourseResearchAgreement
updateCourseResearchAgreement,
updateStoriesUserRole,
deleteStoriesUserUserGroups
};
2 changes: 2 additions & 0 deletions src/commons/application/types/SessionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { GameState, Role, Story } from '../ApplicationTypes';
export const UPDATE_TOTAL_XP = 'UPDATE_TOTAL_XP';
export const UPDATE_ASSESSMENT = 'UPDATE_ASSESSMENT';
export const UPDATE_COURSE_RESEARCH_AGREEMENT = 'UPDATE_COURSE_RESEARCH_AGREEMENT';
export const UPDATE_STORIES_USER_ROLE = 'UPDATE_STORIES_USER_ROLE';
export const DELETE_STORIES_USER_USER_GROUPS = 'DELETE_STORIES_USER_USER_GROUPS';

export type SessionState = {
// Tokens
Expand Down
40 changes: 38 additions & 2 deletions src/commons/sagas/StoriesSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@ import { call, put, select } from 'redux-saga/effects';
import StoriesActions from 'src/features/stories/StoriesActions';
import {
deleteStory,
deleteUserUserGroups,
getAdminPanelStoriesUsers,
getStories,
getStoriesUser,
getStory,
postStory,
putStoriesUserRole,
updateStory
} from 'src/features/stories/storiesComponents/BackendAccess';
import { StoryData, StoryListView, StoryView } from 'src/features/stories/StoriesTypes';

import SessionActions from '../application/actions/SessionActions';
import { OverallState, StoriesRole } from '../application/ApplicationTypes';
import { Tokens } from '../application/types/SessionTypes';
import { combineSagaHandlers } from '../redux/utils';
import { resetSideContent } from '../sideContent/SideContentActions';
import { actions } from '../utils/ActionsHelper';
import { showWarningMessage } from '../utils/notifications/NotificationsHelper';
import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper';
import { defaultStoryContent } from '../utils/StoriesHelper';
import { selectTokens } from './BackendSaga';
import { evalCodeSaga } from './WorkspaceSaga/helpers/evalCode';

const StoriesSaga = combineSagaHandlers(StoriesActions, {
// TODO: Refactor and combine in a future commit
const sagaActions = { ...StoriesActions, ...SessionActions };
const StoriesSaga = combineSagaHandlers(sagaActions, {
// TODO: This should be using `takeLatest`, not `takeEvery`
getStoriesList: function* () {
const tokens: Tokens = yield selectTokens();
Expand Down Expand Up @@ -141,6 +147,36 @@ const StoriesSaga = combineSagaHandlers(StoriesActions, {
action.type,
env
);
},
fetchAdminPanelStoriesUsers: function* (action) {
const tokens: Tokens = yield selectTokens();

const storiesUsers = yield call(getAdminPanelStoriesUsers, tokens);

if (storiesUsers) {
yield put(actions.setAdminPanelStoriesUsers(storiesUsers));
}
},
updateStoriesUserRole: function* (action) {
const tokens: Tokens = yield selectTokens();
const { userId, role } = action.payload;

const resp: Response | null = yield call(putStoriesUserRole, tokens, userId, role);

if (resp) {
yield put(actions.fetchAdminPanelStoriesUsers());
yield call(showSuccessMessage, 'Role updated!');
}
},
deleteStoriesUserUserGroups: function* (action) {
const tokens: Tokens = yield selectTokens();
const { userId } = action.payload;

const resp: Response | null = yield call(deleteUserUserGroups, tokens, userId);
if (resp) {
yield put(actions.fetchAdminPanelStoriesUsers());
yield call(showSuccessMessage, 'Stories user deleted!');
}
}
});

Expand Down
14 changes: 13 additions & 1 deletion src/features/stories/StoriesActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import { StoriesRole } from 'src/commons/application/ApplicationTypes';
import { createActions } from 'src/commons/redux/utils';

import {
AdminPanelStoriesUser,
CLEAR_STORIES_USER_AND_GROUP,
FETCH_ADMIN_PANEL_STORIES_USERS,
GET_STORIES_USER,
SET_ADMIN_PANEL_STORIES_USERS,
SET_CURRENT_STORIES_GROUP,
SET_CURRENT_STORIES_USER,
StoryData,
Expand Down Expand Up @@ -53,6 +56,13 @@ export const setCurrentStoriesGroup = createAction(
export const clearStoriesUserAndGroup = createAction(CLEAR_STORIES_USER_AND_GROUP, () => ({
payload: {}
}));
export const fetchAdminPanelStoriesUsers = createAction(FETCH_ADMIN_PANEL_STORIES_USERS, () => ({
payload: {}
}));
export const setAdminPanelStoriesUsers = createAction(
SET_ADMIN_PANEL_STORIES_USERS,
(users: AdminPanelStoriesUser[]) => ({ payload: { users } })
);

// For compatibility with existing code (reducer)
export const {
Expand Down Expand Up @@ -80,5 +90,7 @@ export default {
getStoriesUser,
setCurrentStoriesUser,
setCurrentStoriesGroup,
clearStoriesUserAndGroup
clearStoriesUserAndGroup,
fetchAdminPanelStoriesUsers,
setAdminPanelStoriesUsers
};
7 changes: 6 additions & 1 deletion src/features/stories/StoriesReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
updateStoriesList
} from './StoriesActions';
import { DEFAULT_ENV } from './storiesComponents/UserBlogContent';
import { StoriesState } from './StoriesTypes';
import { SET_ADMIN_PANEL_STORIES_USERS, StoriesState } from './StoriesTypes';

export const StoriesReducer: Reducer<StoriesState, SourceActionType> = (
state = defaultStories,
Expand Down Expand Up @@ -187,6 +187,11 @@ const oldStoriesReducer: Reducer<StoriesState, SourceActionType> = (
action
) => {
switch (action.type) {
case SET_ADMIN_PANEL_STORIES_USERS:
return {
...state,
storiesUsers: action.payload.users
};
default:
return state;
}
Expand Down
11 changes: 11 additions & 0 deletions src/features/stories/StoriesTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const CLEAR_STORIES_USER_AND_GROUP = 'CLEAR_STORIES_USER_AND_GROUP';
// TODO: Investigate possibility of combining the two actions
export const SET_CURRENT_STORIES_USER = 'SET_CURRENT_STORIES_USER';
export const SET_CURRENT_STORIES_GROUP = 'SET_CURRENT_STORIES_GROUP';
export const FETCH_ADMIN_PANEL_STORIES_USERS = 'FETCH_ADMIN_PANEL_STORIES_USERS';
export const SET_ADMIN_PANEL_STORIES_USERS = 'SET_ADMIN_PANEL_STORIES_USERS';

export type StoryMetadata = {
authorId: number;
Expand Down Expand Up @@ -53,9 +55,18 @@ export type StoriesAuthState = {
readonly role?: StoriesRole;
};

export type AdminPanelStoriesUser = {
readonly id: number;
readonly name: string;
readonly username: string;
readonly provider: string;
readonly role: string;
};

export type StoriesState = {
readonly storyList: StoryListView[];
readonly currentStoryId: number | null;
readonly currentStory: StoryData | null;
readonly envs: { [key: string]: StoriesEnvState };
readonly storiesUsers: AdminPanelStoriesUser[];
} & StoriesAuthState;
57 changes: 56 additions & 1 deletion src/features/stories/storiesComponents/BackendAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { store } from 'src/pages/createStore';

import { Tokens } from '../../../commons/application/types/SessionTypes';
import { NameUsernameRole } from '../../../pages/academy/adminPanel/subcomponents/AddStoriesUserPanel';
import { StoryListView, StoryView } from '../StoriesTypes';
import { AdminPanelStoriesUser, StoryListView, StoryView } from '../StoriesTypes';

// Helpers

Expand Down Expand Up @@ -150,3 +150,58 @@ export const deleteStory = async (tokens: Tokens, id: number): Promise<StoryView
const story = await resp.json();
return story;
};

export const getAdminPanelStoriesUsers = async (
tokens: Tokens
): Promise<AdminPanelStoriesUser[] | null> => {
const resp = await requestStoryBackend(`/groups/${getStoriesGroupId()}/users`, 'GET', {
...tokens
});
if (!resp) {
return null;
}
const users = await resp.json();
return users;
};

export const putStoriesUserRole = async (
tokens: Tokens,
userId: number,
role: StoriesRole
): Promise<Response | null> => {
const resp = await requestStoryBackend(
`/groups/${getStoriesGroupId()}/users/${userId}/role`,
'PUT',
{
...tokens,
body: { role }
}
);

if (!resp) {
showWarningMessage("Failed to update stories user's role");
return null;
}
const user = await resp.json();
return user;
};

export const deleteUserUserGroups = async (
tokens: Tokens,
userId: number
): Promise<Response | null> => {
const resp = await requestStoryBackend(
`/groups/${getStoriesGroupId()}/users/${userId}`,
'DELETE',
{
...tokens
}
);

if (!resp) {
showWarningMessage('Failed to delete stories user');
return null;
}
const user = await resp.json();
return user;
};
21 changes: 20 additions & 1 deletion src/pages/academy/adminPanel/AdminPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import 'ag-grid-community/styles/ag-theme-balham.css';
import { Button, Divider, H1, Intent, Tab, Tabs } from '@blueprintjs/core';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import { useSession } from 'src/commons/utils/Hooks';
import { StoriesRole } from 'src/commons/application/ApplicationTypes';
import { useSession, useTypedSelector } from 'src/commons/utils/Hooks';
import {
addNewStoriesUsersToCourse,
addNewUsersToCourse
} from 'src/features/academy/AcademyActions';
import { fetchAdminPanelStoriesUsers } from 'src/features/stories/StoriesActions';

import SessionActions from '../../../commons/application/actions/SessionActions';
import { UpdateCourseConfiguration } from '../../../commons/application/types/SessionTypes';
Expand All @@ -20,6 +22,7 @@ import AssessmentConfigPanel, {
} from './subcomponents/assessmentConfigPanel/AssessmentConfigPanel';
import CourseConfigPanel from './subcomponents/CourseConfigPanel';
import NotificationConfigPanel from './subcomponents/NotificationConfigPanel';
import StoriesUserConfigPanel from './subcomponents/storiesUserConfigPanel/StoriesUserConfigPanel';
import UserConfigPanel from './subcomponents/userConfigPanel/UserConfigPanel';

const defaultCourseConfig: UpdateCourseConfiguration = {
Expand All @@ -40,12 +43,14 @@ const AdminPanel: React.FC = () => {

const dispatch = useDispatch();
const session = useSession();
const stories = useTypedSelector(state => state.stories);

useEffect(() => {
dispatch(SessionActions.fetchCourseConfig());
dispatch(SessionActions.fetchAssessmentConfigs());
dispatch(SessionActions.fetchAdminPanelCourseRegistrations());
dispatch(SessionActions.fetchNotificationConfigs());
dispatch(fetchAdminPanelStoriesUsers());
}, [dispatch]);

useEffect(() => {
Expand Down Expand Up @@ -83,6 +88,15 @@ const AdminPanel: React.FC = () => {
}
};

const storiesUserConfigPanelProps = {
userId: stories.userId,
storiesUsers: stories.storiesUsers,
handleUpdateStoriesUserRole: (id: number, role: StoriesRole) =>
dispatch(SessionActions.updateStoriesUserRole(id, role)),
handleDeleteStoriesUserFromUserGroup: (id: number) =>
dispatch(SessionActions.deleteStoriesUserUserGroups(id))
};

// Handler to submit changes to Course Configration and Assessment Configuration to the backend.
// Changes made to users are handled separately.
const submitHandler = useCallback(() => {
Expand Down Expand Up @@ -156,6 +170,11 @@ const AdminPanel: React.FC = () => {
/>
}
/>
<Tab
id="stories-users"
title="Stories Users"
panel={<StoriesUserConfigPanel {...storiesUserConfigPanelProps} />}
/>
<Tab
id="add-users"
title="Add Users"
Expand Down
Loading
Loading