Skip to content

Commit

Permalink
feat: remove immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Oct 25, 2023
1 parent 031a5f2 commit 4c5d1fe
Show file tree
Hide file tree
Showing 11 changed files with 1,196 additions and 1,155 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"license": "AGPL3.0-only",
"dependencies": {
"@emotion/styled": "11.11.0",
"@graasp/apps-query-client": "2.0.1",
"@graasp/sdk": "1.1.2",
"@graasp/apps-query-client": "github:graasp/graasp-apps-query-client#181-remove-immutable",
"@graasp/sdk": "1.9.2",
"@json2csv/plainjs": "7.0.1",
"@mui/icons-material": "5.11.16",
"@mui/material": "5.13.3",
Expand All @@ -21,7 +21,6 @@
"@testing-library/react": "14.0.0",
"http-status-codes": "2.2.0",
"i18next": "22.5.0",
"immutable": "4.3.0",
"lodash": "4.17.21",
"prop-types": "15.8.1",
"qs": "6.11.2",
Expand Down Expand Up @@ -69,6 +68,7 @@
"@cypress/code-coverage": "3.10.7",
"@cypress/instrument-cra": "1.4.0",
"@tanstack/react-query-devtools": "4.29.12",
"@types/lodash": "4.14.200",
"@types/react": "18.2.8",
"@types/react-dom": "18.2.4",
"@typescript-eslint/eslint-plugin": "5.59.8",
Expand Down
6 changes: 3 additions & 3 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ export const App = () => {

useEffect(() => {
// handle a change of language
const lang = context?.get('lang') ?? DEFAULT_LANG;
const lang = context?.lang ?? DEFAULT_LANG;
if (i18n.language !== lang) {
i18n.changeLanguage(lang);
}
}, [context]);

const renderContent = () => {
switch (context?.get('context')) {
switch (context?.context) {
case Context.Builder:
return (
<>
Expand All @@ -45,7 +45,7 @@ export const App = () => {
default:
return (
<>
{(context?.get('standalone') || isHeaderVisible) && <Header />}
{(context?.standalone || isHeaderVisible) && <Header />}
<PlayerView />
</>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/common/ConfirmDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ ConfirmDialog.propTypes = {
text: PropTypes.string,
confirmText: PropTypes.string,
cancelText: PropTypes.string,
confirmButtonCypress: PropTypes.string.isRequired,
};

ConfirmDialog.defaultProps = {
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/admin/AdminView.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import { useState } from 'react';
import Grid from '@mui/material/Grid';
import { useTranslation } from 'react-i18next';
import Fab from '@mui/material/Fab';
Expand Down Expand Up @@ -40,7 +40,7 @@ export const AdminView = () => {
return <Loader />;
}

const members = context?.get('members') ?? [];
const members = context?.members ?? [];

const onClick = () => {
setIsOpenSettings(true);
Expand Down
3 changes: 1 addition & 2 deletions src/components/views/admin/AnalyzerView.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import _ from 'lodash';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material';
import { List } from 'immutable';
import { removeStopwords } from 'stopword';
import Loader from '../../common/Loader';
import WordCloud from 'react-wordcloud';
Expand All @@ -13,7 +12,7 @@ import { wordCloudId } from '../../../config/selectors';
const formatWords = (appData) => {
const wordArray = appData
.filter((a) => a.type === APP_DATA_TYPES.INPUT)
.map((a) => List(_.words(a.data?.text?.toLowerCase())))
.map((a) => _.words(a.data?.text?.toLowerCase()))
.flatten();

// strip stopwords and create count map
Expand Down
7 changes: 3 additions & 4 deletions src/components/views/admin/BuilderView.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { useContext } from 'react';
import { Context } from '@graasp/apps-query-client';
import AdminView from './AdminView';
import { PERMISSION_LEVELS } from '../../../config/settings';
import PlayerView from '../read/PlayerView';
import { useLocalContext } from '@graasp/apps-query-client';

const BuilderView = () => {
const context = useContext(Context);
switch (context.get('permission')) {
const context = useLocalContext();
switch (context.permission) {
case PERMISSION_LEVELS.ADMIN:
case PERMISSION_LEVELS.WRITE:
return <AdminView />;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
import _ from 'lodash';
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import TableRow from '@mui/material/TableRow';
import TableCell from '@mui/material/TableCell';
import IconButton from '@mui/material/IconButton';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import ConfirmDialog from '../../common/ConfirmDialog';
import FormDialog from '../../common/FormDialog';
import { showErrorToast } from '../../../utils/toasts';
import { ACTION_TYPES } from '../../../config/actionTypes';
import { MUTATION_KEYS, useMutation } from '../../../config/queryClient';
import { mutations } from '../../../config/queryClient';
import {
deleteButtonCypress,
deleteConfirmButtonCypress,
editFeedbackButtonCypress,
feedbackTextCypress,
} from '../../../config/selectors';
import { AppData, Member, UUID } from '@graasp/sdk';

const Response = ({ id, data, student, feedbackResource }) => {
type Props = {
id: UUID;
data?: string;
student?: Member;
feedbackResource?: AppData;
};

const Response = ({ id, data, student, feedbackResource }: Props) => {
const { t } = useTranslation();
const [feedbackText, setFeedbackText] = useState('');
const [feedbackText, setFeedbackText] = useState<string>('');
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
const [feedbackDialogOpen, setFeedbackDialogOpen] = useState(false);
const { mutate: postAppData } = useMutation(MUTATION_KEYS.POST_APP_DATA);
const { mutate: patchAppData } = useMutation(MUTATION_KEYS.PATCH_APP_DATA);
const { mutate: deleteAppData } = useMutation(MUTATION_KEYS.DELETE_APP_DATA);
const { mutate: postAppData } = mutations.usePostAppData();
const { mutate: patchAppData } = mutations.usePatchAppData();
const { mutate: deleteAppData } = mutations.useDeleteAppData();

useEffect(() => {
if (feedbackResource) {
setFeedbackText(feedbackResource?.data?.text);
// todo: use app data with generic type
setFeedbackText(feedbackResource.data.text as string);
}
}, [feedbackResource]);

Expand All @@ -44,31 +52,31 @@ const Response = ({ id, data, student, feedbackResource }) => {

const handleConfirmDelete = () => {
deleteAppData({ id });
if (!_.isEmpty(feedbackResource)) {
if (feedbackResource && !_.isEmpty(feedbackResource)) {
deleteAppData({ id: feedbackResource.id });
}
handleToggleConfirmDialog();
};

const handleSubmitFeedback = (text) => {
const handleSubmitFeedback = (text: string) => {
if (!student?.id) {
showErrorToast(
'Currently we do not support giving feedback to anonymous users.'
);
}

// if no feedback resource yet, create it, otherwise, update it
if (_.isEmpty(feedbackResource)) {
postAppData({
memberId: student.id,
data: { text, memberId: student.id },
type: ACTION_TYPES.FEEDBACK,
});
} else {
patchAppData({
id: feedbackResource.id,
data: { text, memberId: student.id },
});
// if no feedback resource yet, create it, otherwise, update it
if (!feedbackResource || _.isEmpty(feedbackResource)) {
postAppData({
member: student,
data: { text, memberId: student.id },
type: ACTION_TYPES.FEEDBACK,
});
} else {
patchAppData({
id: feedbackResource.id,
data: { text, memberId: student.id },
});
}
}
handleToggleFeedbackDialog();
};
Expand Down Expand Up @@ -98,7 +106,7 @@ const Response = ({ id, data, student, feedbackResource }) => {

return (
<TableRow key={id}>
<TableCell>{student.name}</TableCell>
<TableCell>{student?.name ?? t('Anonymous')}</TableCell>
<TableCell>{data}</TableCell>
<TableCell>{renderFeedbackCell()}</TableCell>
<TableCell>
Expand Down Expand Up @@ -126,24 +134,4 @@ const Response = ({ id, data, student, feedbackResource }) => {
);
};

Response.propTypes = {
data: PropTypes.string,
student: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}).isRequired,
feedbackResource: PropTypes.shape({
data: PropTypes.shape({
text: PropTypes.string.isRequired,
memberId: PropTypes.string.isRequired,
}).isRequired,
}),
id: PropTypes.string.isRequired,
};

Response.defaultProps = {
data: '',
feedbackResource: {},
};

export default Response;
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import Typography from '@mui/material/Typography';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
Expand All @@ -7,16 +6,15 @@ import TableRow from '@mui/material/TableRow';
import TableCell from '@mui/material/TableCell';
import TableBody from '@mui/material/TableBody';
import { styled } from '@mui/material';
import { List } from 'immutable';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import Response from './Response';
import { RESPONSES_COLUMNS } from '../../../config/settings';
import {
responsesTableCypress,
tableNoResponsesCypress,
} from '../../../config/selectors';
import { APP_DATA_TYPES } from '../../../config/appDataTypes';
import { AppData, Member } from '@graasp/sdk';

const StyledPaper = styled(Paper)(({ theme }) => ({
width: '100%',
Expand All @@ -28,18 +26,19 @@ const StyledTable = styled(Table)({
minWidth: 700,
});

const Responses = ({ students, appData }) => {
const { t } = useTranslation();
type Props = {
students: Member[];
appData: AppData[];
};

const anonymousUser = {
name: t('Anonymous'),
};
const Responses = ({ students, appData }: Props) => {
const { t } = useTranslation();

const renderAppInstanceResources = () => {
const nonEmptyData = appData.filter(({ data }) => Boolean(data?.text));

// if there are no resources, show an empty table
if (nonEmptyData.isEmpty()) {
if (!nonEmptyData.length) {
return (
<TableRow data-cy={tableNoResponsesCypress}>
<TableCell align="center" colSpan={4}>
Expand All @@ -57,16 +56,16 @@ const Responses = ({ students, appData }) => {
);
// map each app instance resource to a row in the table
return responses.map(({ id, member, data }) => {
const m = students.find((m) => m.id === member.id) ?? anonymousUser;
const feedbackResource = feedbacks.find(
({ data: { memberId: mId } }) => mId === m.id
);
const m = students.find((m) => m.id === member.id);
const feedbackResource = m
? feedbacks.find(({ data: { memberId: mId } }) => mId === m.id)
: undefined;
return (
<Response
id={id}
key={id}
student={m}
data={data?.text}
data={data?.text as string}
feedbackResource={feedbackResource}
/>
);
Expand Down Expand Up @@ -94,19 +93,4 @@ const Responses = ({ students, appData }) => {
);
};

Responses.propTypes = {
appData: PropTypes.instanceOf(List),
students: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
})
),
};

Responses.defaultProps = {
appData: List(),
students: [],
};

export default Responses;
9 changes: 4 additions & 5 deletions src/components/views/admin/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import Dialog, { DialogProps } from '@mui/material/Dialog';
import FormControlLabel from '@mui/material/FormControlLabel';
import { useTranslation } from 'react-i18next';
import Loader from '../../common/Loader';
import { mutations } from '../../../config/queryClient';
import { mutations, hooks } from '../../../config/queryClient';
import { headerVisibilityCypress } from '../../../config/selectors';
import { hooks } from '../../../config/queryClient';
import { SETTINGS } from '../../../config/settings';
import { AppSettingRecord } from '@graasp/sdk/frontend';
import { AppSetting } from '@graasp/sdk';

type Props = {
open?: boolean;
Expand All @@ -20,12 +19,12 @@ type Props = {
const Settings = ({ open = false, handleClose }: Props): JSX.Element => {
const { t } = useTranslation();
const { data: settings, isLoading } = hooks.useAppSettings();
const [headerVisibility, setHeaderVisibility] = useState<AppSettingRecord>();
const [headerVisibility, setHeaderVisibility] = useState<AppSetting>();
const { mutate: postAppSetting } = mutations.usePostAppSetting();
const { mutate: patchAppSetting } = mutations.usePatchAppSetting();

useEffect(() => {
if (settings && !settings.isEmpty()) {
if (settings?.length) {
setHeaderVisibility(
settings.find(({ name }) => name === SETTINGS.HEADER_VISIBILITY)
);
Expand Down
Loading

0 comments on commit 4c5d1fe

Please sign in to comment.