api update and html rendering
This commit is contained in:
51
package-lock.json
generated
51
package-lock.json
generated
@@ -8230,6 +8230,11 @@
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"dompurify": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.1.tgz",
|
||||
"integrity": "sha512-xGWt+NHAQS+4tpgbOAI08yxW0Pr256Gu/FNE2frZVTbgrBUn8M7tz7/ktS/LZ2MHeGqz6topj0/xY+y8R5FBFw=="
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
@@ -11087,6 +11092,15 @@
|
||||
"wbuf": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"html-dom-parser": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-1.0.2.tgz",
|
||||
"integrity": "sha512-Jq4oVkVSn+10ut3fyc2P/Fs1jqTo0l45cP6Q8d2ef/9jfkYwulO0QXmyLI0VUiZrXF4czpGgMEJRa52CQ6Fk8Q==",
|
||||
"requires": {
|
||||
"domhandler": "4.2.2",
|
||||
"htmlparser2": "6.1.0"
|
||||
}
|
||||
},
|
||||
"html-element-map": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz",
|
||||
@@ -11140,6 +11154,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-react-parser": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-1.3.0.tgz",
|
||||
"integrity": "sha512-lhpkOFH8pwqEjlNUYCWvjT43/JVCZO9MAZuCS6afT1/VP+bZcNxNUs4AUqiMzH0QPSDHwM/GFNXZNok1KTA4BQ==",
|
||||
"requires": {
|
||||
"domhandler": "4.2.2",
|
||||
"html-dom-parser": "1.0.2",
|
||||
"react-property": "2.0.0",
|
||||
"style-to-js": "1.1.0"
|
||||
}
|
||||
},
|
||||
"html-webpack-new-relic-plugin": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-new-relic-plugin/-/html-webpack-new-relic-plugin-4.1.0.tgz",
|
||||
@@ -11795,6 +11820,11 @@
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"dev": true
|
||||
},
|
||||
"inline-style-parser": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
|
||||
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "7.3.3",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
|
||||
@@ -21482,6 +21512,11 @@
|
||||
"warning": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"react-property": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
|
||||
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
|
||||
},
|
||||
"react-proptype-conditional-require": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz",
|
||||
@@ -23761,6 +23796,22 @@
|
||||
"schema-utils": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"style-to-js": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.0.tgz",
|
||||
"integrity": "sha512-1OqefPDxGrlMwcbfpsTVRyzwdhr4W0uxYQzeA2F1CBc8WG04udg2+ybRnvh3XYL4TdHQrCahLtax2jc8xaE6rA==",
|
||||
"requires": {
|
||||
"style-to-object": "0.3.0"
|
||||
}
|
||||
},
|
||||
"style-to-object": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
|
||||
"integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
|
||||
"requires": {
|
||||
"inline-style-parser": "0.1.1"
|
||||
}
|
||||
},
|
||||
"stylehacks": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz",
|
||||
|
||||
@@ -39,11 +39,13 @@
|
||||
"@reduxjs/toolkit": "^1.6.1",
|
||||
"classnames": "^2.3.1",
|
||||
"core-js": "3.16.2",
|
||||
"dompurify": "^2.3.1",
|
||||
"email-prop-type": "^3.0.1",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-to-json": "^3.6.2",
|
||||
"font-awesome": "4.7.0",
|
||||
"history": "5.0.1",
|
||||
"html-react-parser": "^1.3.0",
|
||||
"lodash": "^4.17.21",
|
||||
"node-sass": "^6.0.1",
|
||||
"prop-types": "15.7.2",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<html lang="en-us" dir="ltr">
|
||||
<head>
|
||||
<title>ORA Enhanced Staff Grader | <%= process.env.SITE_NAME %></title>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -17,10 +17,14 @@ import StatusBadge from './StatusBadge';
|
||||
import './ReviewModal.scss';
|
||||
|
||||
export const ReviewActions = ({ submission: { status, username } }) => (
|
||||
<ActionRow>
|
||||
{username}
|
||||
<StatusBadge status={status} />
|
||||
</ActionRow>
|
||||
<div className="review-actions">
|
||||
<ActionRow>
|
||||
<span className="review-actions-username">{username}</span>
|
||||
<StatusBadge className="review-actions-status" status={status} />
|
||||
<ActionRow.Spacer />
|
||||
<Button>Show Rubric</Button>
|
||||
</ActionRow>
|
||||
</div>
|
||||
);
|
||||
ReviewActions.propTypes = {
|
||||
submission: PropTypes.shape({
|
||||
|
||||
@@ -7,7 +7,11 @@ import {
|
||||
Container,
|
||||
} from '@edx/paragon';
|
||||
|
||||
import createDOMPurify from 'dompurify';
|
||||
import parse from 'html-react-parser';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import actions from 'data/actions';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
|
||||
import ReviewActions from './ReviewActions';
|
||||
@@ -22,9 +26,15 @@ export class ReviewModal extends React.Component {
|
||||
super(props);
|
||||
console.log('review modal');
|
||||
console.log({ props });
|
||||
this.purify = createDOMPurify(window);
|
||||
this.onClose = this.onClose.bind(this);
|
||||
}
|
||||
|
||||
onClose = () => {
|
||||
get textContent() {
|
||||
return parse(this.purify.sanitize(this.props.response.text));
|
||||
}
|
||||
|
||||
onClose() {
|
||||
this.props.setShowReview(false);
|
||||
}
|
||||
|
||||
@@ -37,7 +47,7 @@ export class ReviewModal extends React.Component {
|
||||
onClose={this.onClose}
|
||||
>
|
||||
<Container size="md">
|
||||
{this.props.response.text}
|
||||
{this.textContent}
|
||||
</Container>
|
||||
</FullscreenModal>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.pgn__modal-close-container {
|
||||
// TODO: need to be able to load this from paragon
|
||||
right: 1rem;
|
||||
@import "@edx/paragon/scss/core/core";
|
||||
.review-actions {
|
||||
padding: map_get($spacers, 3);
|
||||
}
|
||||
#ora-esg-list-view {
|
||||
padding: 20px;
|
||||
|
||||
@@ -8,19 +8,23 @@ import { gradingStatuses as statuses } from 'data/services/lms/constants';
|
||||
/**
|
||||
* <StatusBadge />
|
||||
*/
|
||||
export const StatusBadge = ({ status }) => {
|
||||
export const StatusBadge = ({ className, status }) => {
|
||||
if (status === statuses.ungraded) {
|
||||
return (<Badge variant="primary">Ungraded</Badge>);
|
||||
return (<Badge className={className} variant="primary">Ungraded</Badge>);
|
||||
}
|
||||
if (status === statuses.locked) {
|
||||
return (<Badge variant="light">Grading in progress</Badge>);
|
||||
return (<Badge className={className} variant="light">Grading in progress</Badge>);
|
||||
}
|
||||
if (status === statuses.graded) {
|
||||
return (<Badge variant="success">Grading Complete</Badge>);
|
||||
return (<Badge className={className} variant="success">Grading Complete</Badge>);
|
||||
}
|
||||
return (<Badge>{status}</Badge>);
|
||||
};
|
||||
StatusBadge.defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
StatusBadge.propTypes = {
|
||||
className: PropTypes.string,
|
||||
status: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ export class ListView extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.props.initializeApp();
|
||||
this.handleViewAllResponsesClick = this.handleViewAllResponsesClick.bind(this);
|
||||
}
|
||||
|
||||
formatDate = ({ value }) => {
|
||||
@@ -44,7 +45,7 @@ export class ListView extends React.Component {
|
||||
|
||||
formatStatus = ({ value }) => (<StatusBadge status={value} />);
|
||||
|
||||
handleViewAllResponsesClick = (data) => {
|
||||
handleViewAllResponsesClick(data) {
|
||||
console.log("View all responses button clicked");
|
||||
console.log(data);
|
||||
if (data.selectedRows.length) {
|
||||
@@ -56,16 +57,17 @@ export class ListView extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log({ props: this.props, length: this.props.listData.length });
|
||||
return (
|
||||
<div id="ora-esg-list-view">
|
||||
<DataTable
|
||||
isFilterable
|
||||
defaultColumnValues={{ Filter: TextFilter }}
|
||||
isSelectable
|
||||
manalSelectColumn={selectColumn}
|
||||
isSortable
|
||||
isPaginated
|
||||
itemCount={this.props.listData.length}
|
||||
initialState={{ pageSize: 10, pageIndex: 0 }}
|
||||
data={this.props.listData}
|
||||
tableActions={[
|
||||
{
|
||||
@@ -113,7 +115,9 @@ export class ListView extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
ListView.defaultProps = {};
|
||||
ListView.defaultProps = {
|
||||
listData: [],
|
||||
};
|
||||
ListView.propTypes = {
|
||||
initializeApp: PropTypes.func.isRequired,
|
||||
listData: PropTypes.arrayOf(PropTypes.shape({
|
||||
@@ -121,7 +125,7 @@ ListView.propTypes = {
|
||||
dateSubmitted: PropTypes.number,
|
||||
status: PropTypes.string,
|
||||
grade: PropTypes.number,
|
||||
})).isRequired,
|
||||
})),
|
||||
loadSelectionForReview: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -6,17 +6,17 @@ const createAction = createActionFactory(dataKey);
|
||||
|
||||
/*
|
||||
* @param {obj} submission
|
||||
* { learnerId, response, grade, status, rubric }
|
||||
* { submissionId, response, grade, status, rubric }
|
||||
*/
|
||||
const loadSubmission = createAction('loadSubmission');
|
||||
/*
|
||||
* @param {obj} submission
|
||||
* { learnerId, response, grade, status, rubric }
|
||||
* { submissionId, response, grade, status, rubric }
|
||||
*/
|
||||
const preloadNext = createAction('preloadNext');
|
||||
/*
|
||||
* @param {obj} submission
|
||||
* { learnerId, response, grade, status, rubric }
|
||||
* { submissionId, response, grade, status, rubric }
|
||||
*/
|
||||
const preloadPrev = createAction('preloadPrev');
|
||||
/*
|
||||
|
||||
@@ -3,9 +3,9 @@ import actions from 'data/actions';
|
||||
const initialState = {
|
||||
list: {},
|
||||
selected: [],
|
||||
activeIndex: null, // learnerID
|
||||
activeIndex: null, // submissionId
|
||||
current: {
|
||||
learnerId: null,
|
||||
submissionId: null,
|
||||
response: {
|
||||
text: '',
|
||||
files: [],
|
||||
@@ -33,11 +33,9 @@ const grades = (state = initialState, { type, payload }) => {
|
||||
case actions.submissions.loadSubmission.toString():
|
||||
return {
|
||||
...state,
|
||||
selectedItem: payload.learnerId,
|
||||
current: payload,
|
||||
activeIndex: 0,
|
||||
};
|
||||
|
||||
case actions.submissions.preloadNext.toString():
|
||||
return { ...state, next: payload };
|
||||
case actions.submissions.preloadPrev.toString():
|
||||
|
||||
@@ -12,19 +12,19 @@ const simpleSelectors = {
|
||||
|
||||
export const selectionIndex = createSelector(
|
||||
[simpleSelectors.list],
|
||||
(list, { learnerId }) => list.selected.indexOf(learnerId),
|
||||
(list, { submissionId }) => list.selected.indexOf(submissionId),
|
||||
);
|
||||
|
||||
export const listData = createSelector(
|
||||
[simpleSelectors.list],
|
||||
(list) => _.sortBy(
|
||||
Object.values(list),
|
||||
['learnerId'],
|
||||
['submissionId'],
|
||||
),
|
||||
);
|
||||
|
||||
export const selectionLearnerId = (state, { index }) => (
|
||||
simpleSelectors.selected(state)[index].learnerId
|
||||
export const selectionSubmissionId = (state, { index }) => (
|
||||
simpleSelectors.selected(state)[index].submissionId
|
||||
);
|
||||
|
||||
export const currentSelection = createSelector(
|
||||
@@ -32,25 +32,25 @@ export const currentSelection = createSelector(
|
||||
(list, activeIndex) => list[activeIndex],
|
||||
);
|
||||
|
||||
export const selectedLearnerId = createSelector(
|
||||
export const selectedSubmissionId = createSelector(
|
||||
[currentSelection],
|
||||
(selection) => selection.learnerId,
|
||||
(selection) => selection.submissionId,
|
||||
);
|
||||
|
||||
export const prevLearnerId = createSelector(
|
||||
export const prevSubmissionId = createSelector(
|
||||
[simpleSelectors.selected, simpleSelectors.activeIndex],
|
||||
(list, activeIndex) => {
|
||||
if (activeIndex > 0) {
|
||||
return list[activeIndex - 1].learnerId;
|
||||
return list[activeIndex - 1].submissionId;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
export const nextLearnerId = createSelector(
|
||||
export const nextSubmissionId = createSelector(
|
||||
[simpleSelectors.selected, simpleSelectors.activeIndex],
|
||||
(list, activeIndex) => {
|
||||
if (activeIndex < list.length - 1) {
|
||||
return list[activeIndex + 1].learnerId;
|
||||
return list[activeIndex + 1].submissionId;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -61,7 +61,7 @@ export default StrictDict({
|
||||
currentSelection,
|
||||
selectionIndex,
|
||||
listData,
|
||||
selectedLearnerId,
|
||||
nextLearnerId,
|
||||
prevLearnerId,
|
||||
selectedSubmissionId,
|
||||
nextSubmissionId,
|
||||
prevSubmissionId,
|
||||
});
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import submissionList from './submissionList';
|
||||
|
||||
const responseText = `
|
||||
const responseText = `<div><h1>Title</h1>
|
||||
Phasellus tempor eros aliquam ipsum molestie, vitae varius lectus tempus. Morbi iaculis, libero euismod vehicula rutrum, nisi leo volutpat diam, quis commodo ex nunc ut odio. Pellentesque condimentum feugiat erat ac vulputate. Pellentesque porta rutrum sagittis. Curabitur vulputate tempus accumsan. Fusce bibendum gravida metus a scelerisque. Mauris fringilla orci non lobortis commodo. Quisque iaculis, quam a tincidunt vehicula, erat nisi accumsan quam, eu cursus ligula magna id odio. Nulla porttitor, lorem gravida vehicula tristique, sapien metus tristique ex, id tincidunt sapien justo nec sapien. Maecenas luctus, nisl vestibulum scelerisque pharetra, ligula orci vulputate turpis, in ultrices mauris dolor eu enim. Suspendisse quis nibh nec augue semper maximus. Morbi maximus eleifend magna.
|
||||
|
||||
Phasellus porttitor vel magna et auctor. Nulla porttitor convallis aliquam. Donec cursus, ipsum ut egestas bibendum, purus metus dignissim est, ac condimentum leo felis eget diam. In magna mi, tincidunt id sapien id, fermentum vestibulum quam. Quisque et dui sed urna convallis rutrum pellentesque quis sapien. Cras non lectus velit. Praesent semper eros id risus mollis, quis interdum quam imperdiet. Sed nec vulputate tortor, at tristique tortor.`;
|
||||
Phasellus porttitor vel magna et auctor. Nulla porttitor convallis aliquam. Donec cursus, ipsum ut egestas bibendum, purus metus dignissim est, ac condimentum leo felis eget diam. In magna mi, tincidunt id sapien id, fermentum vestibulum quam. Quisque et dui sed urna convallis rutrum pellentesque quis sapien. Cras non lectus velit. Praesent semper eros id risus mollis, quis interdum quam imperdiet. Sed nec vulputate tortor, at tristique tortor.
|
||||
</div>`;
|
||||
|
||||
const rubric = {
|
||||
name: 'Rubric name',
|
||||
|
||||
@@ -24,7 +24,7 @@ const createSubmission = (grade, status) => {
|
||||
const submissionId = ids.submissionId(index);
|
||||
const learnerId = ids.learnerId(index);
|
||||
submissions[submissionId] = {
|
||||
id: submissionId,
|
||||
submissionId,
|
||||
username: ids.username(index),
|
||||
learnerId,
|
||||
dateSubmitted: date0 + (day * index),
|
||||
|
||||
@@ -15,13 +15,13 @@ export const initialize = () => (dispatch) => (
|
||||
);
|
||||
|
||||
export const prefetchPrev = () => (dispatch, getState) => (
|
||||
api.fetchSubmission(selectors.submissions.prevLearnerId(getState())).then((response) => {
|
||||
api.fetchSubmission(selectors.submissions.prevSubmissionId(getState())).then((response) => {
|
||||
dispatch(actions.submissions.preloadPrev(response.submission));
|
||||
})
|
||||
);
|
||||
|
||||
export const prefetchNext = () => (dispatch, getState) => (
|
||||
api.fetchSubmission(selectors.submissions.nextLearnerId(getState())).then((response) => {
|
||||
api.fetchSubmission(selectors.submissions.nextSubmissionId(getState())).then((response) => {
|
||||
dispatch(actions.submissions.preloadNext(response.submission));
|
||||
if (selectors.submissions.activeIndex(getState()) > 0) {
|
||||
return dispatch(prefetchPrev());
|
||||
@@ -30,22 +30,27 @@ export const prefetchNext = () => (dispatch, getState) => (
|
||||
})
|
||||
);
|
||||
|
||||
export const fetchSubmissionFromSelection = () => (dispatch, getState) => (
|
||||
api.fetchSubmission(
|
||||
selectors.submissions.selectedLearnerId(getState()),
|
||||
).then((response) => {
|
||||
dispatch(actions.submissions.loadSubmission(response.submission));
|
||||
const activeIndex = selectors.submissions.activeIndex(getState());
|
||||
const selected = selectors.submissions.selected(getState());
|
||||
if (activeIndex < selected.length - 1) {
|
||||
return dispatch(prefetchNext());
|
||||
}
|
||||
if (activeIndex > 0) {
|
||||
return dispatch(prefetchPrev());
|
||||
}
|
||||
return true;
|
||||
})
|
||||
);
|
||||
export const fetchSubmissionFromSelection = () => (dispatch, getState) => {
|
||||
console.log({
|
||||
fetchSubmission: selectors.submissions.selectedSubmissionId(getState()),
|
||||
});
|
||||
return (
|
||||
api.fetchSubmission(
|
||||
selectors.submissions.selectedSubmissionId(getState()),
|
||||
).then((response) => {
|
||||
dispatch(actions.submissions.loadSubmission(response.submission));
|
||||
const activeIndex = selectors.submissions.activeIndex(getState());
|
||||
const selected = selectors.submissions.selected(getState());
|
||||
if (activeIndex < selected.length - 1) {
|
||||
return dispatch(prefetchNext());
|
||||
}
|
||||
if (activeIndex > 0) {
|
||||
return dispatch(prefetchPrev());
|
||||
}
|
||||
return true;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const loadSelectionForReview = (selection) => (dispatch) => {
|
||||
const submissions = selection.map(row => row.original);
|
||||
|
||||
@@ -15,33 +15,19 @@ import { messages as footerMessages } from '@edx/frontend-component-footer';
|
||||
import appMessages from './i18n';
|
||||
import App from './App';
|
||||
|
||||
/*
|
||||
subscribe(APP_READY, () => {
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
});
|
||||
|
||||
initialize({
|
||||
messages: [
|
||||
appMessages,
|
||||
footerMessages,
|
||||
],
|
||||
requireAuthenticatedUser: true,
|
||||
});
|
||||
*/
|
||||
|
||||
// ReactDOM.render(
|
||||
// <IntlProvider locale="en">
|
||||
// <App />
|
||||
// </IntlProvider>,
|
||||
// document.getElementById('root'),
|
||||
// );
|
||||
|
||||
subscribe(APP_READY, () => {
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
ReactDOM.render(
|
||||
<IntlProvider locale="en">
|
||||
<App />
|
||||
</IntlProvider>,
|
||||
document.getElementById('root'));
|
||||
});
|
||||
|
||||
subscribe(APP_INIT_ERROR, (error) => {
|
||||
ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));
|
||||
ReactDOM.render(
|
||||
<ErrorPage message={error.message} />,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
});
|
||||
|
||||
initialize({
|
||||
@@ -50,4 +36,4 @@ initialize({
|
||||
footerMessages,
|
||||
],
|
||||
requireAuthenticatedUser: true,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user