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

Removing createReactClass usage in 3 files. #1893

Merged
merged 27 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4199980
Beginning of removing createReactClass.
catandthemachines Sep 16, 2024
0d3c466
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Sep 23, 2024
021340c
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Sep 23, 2024
0987c84
Migrated measure to class structure.
catandthemachines Sep 23, 2024
28517ff
Removing createReactClass
catandthemachines Sep 24, 2024
2576372
graph settings updating.
catandthemachines Sep 24, 2024
c0947ec
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Sep 25, 2024
268988b
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Sep 27, 2024
c740d0b
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Oct 2, 2024
bc4e6bd
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Nov 20, 2024
f494bc2
undoing measurer changes.
catandthemachines Nov 20, 2024
1d3a1de
reverting json-editor.tsx
catandthemachines Nov 20, 2024
5acba42
reverting graph-settings.tsx
catandthemachines Nov 20, 2024
1772774
Add changeset.
catandthemachines Nov 20, 2024
a23968f
Adding some more typing.
catandthemachines Nov 20, 2024
71000e0
Merge branch 'main' into catjohnson/remove-createreactclass
catandthemachines Nov 25, 2024
0ab55ed
Fixing some structure to drag-target.tsx
catandthemachines Nov 25, 2024
4c613b7
removing prop types import.
catandthemachines Nov 25, 2024
cd38ae9
Adding more typing and binding to drag-target.tsx.
catandthemachines Nov 25, 2024
72566c4
Fixing some sortable constructor.
catandthemachines Nov 25, 2024
984f9e0
Cleaning up sortable.tsx file!
catandthemachines Nov 26, 2024
61c0cb5
removing stateful-editor-page.
catandthemachines Nov 26, 2024
d2a2678
Adding comment on broken file and link to issue.
catandthemachines Nov 26, 2024
6807952
Fixing a few types and using state vs. props.
catandthemachines Nov 26, 2024
658efd0
removing unnecessary comment.
catandthemachines Nov 26, 2024
a92c58d
Removing unnecessary constructor.
catandthemachines Nov 27, 2024
9db2826
using default exports.
catandthemachines Nov 27, 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
5 changes: 5 additions & 0 deletions .changeset/khaki-keys-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus-editor": patch
---

Removing usage of createReactClass from several component files.
96 changes: 59 additions & 37 deletions packages/perseus-editor/src/components/drag-target.tsx
catandthemachines marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -22,53 +22,75 @@
// * custom styles for global drag and dragOver
// * only respond to certain types of drags (only images for instance)!

import createReactClass from "create-react-class";
import PropTypes from "prop-types";
import * as React from "react";

const DragTarget = createReactClass({
propTypes: {
// All props not listed here are forwarded to the root element without
// modification.
onDrop: PropTypes.func.isRequired,
component: PropTypes.any, // component type
shouldDragHighlight: PropTypes.func,
style: PropTypes.any,
},
getDefaultProps: function () {
return {
component: "div",
shouldDragHighlight: () => true,
type Props = {
onDrop: (e: DragEvent) => void;
component?: any;
shouldDragHighlight: (any) => boolean;
style?: any;
children?: any;
className?: string;
};

type DefaultProps = {
component: Props["component"];
shouldDragHighlight: Props["shouldDragHighlight"];
};

type State = {
dragHover: boolean;
};
class DragTarget extends React.Component<Props, State> {
static defaultProps: DefaultProps = {
component: "div",
shouldDragHighlight: () => true,
};

constructor(props) {
super(props);
this.state = {
dragHover: false,
};
},
getInitialState: function () {
return {dragHover: false};
},
handleDrop: function (e) {

this.handleDrop = this.handleDrop.bind(this);
this.handleDragEnd = this.handleDragEnd.bind(this);
this.handleDragOver = this.handleDragOver.bind(this);
this.handleDragLeave = this.handleDragLeave.bind(this);
this.handleDragEnter = this.handleDragEnter.bind(this);
}

handleDrop(e: DragEvent) {
e.stopPropagation();
e.preventDefault();
this.setState({dragHover: false});
this.props.onDrop(e);
},
handleDragEnd: function () {
}

handleDragEnd() {
this.setState({dragHover: false});
},
handleDragOver: function (e) {
}

handleDragOver(e) {
e.preventDefault();
},
handleDragLeave: function () {
}

handleDragLeave() {
this.setState({dragHover: false});
},
handleDragEnter: function (e) {
}

handleDragEnter(e) {
this.setState({dragHover: this.props.shouldDragHighlight(e)});
},
render: function () {
const opacity = this.state.dragHover ? {opacity: 0.3} : {};
const Component = this.props.component;
}

const forwardProps = Object.assign({}, this.props);
delete forwardProps.component;
delete forwardProps.shouldDragHighlight;
render() {
const opacity = this.state.dragHover ? {opacity: 0.3} : {};
const {
component: Component,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
shouldDragHighlight,
...forwardProps
} = this.props;

return (
<Component
Expand All @@ -81,7 +103,7 @@ const DragTarget = createReactClass({
onDragLeave={this.handleDragLeave}
/>
);
},
});
}
}

export default DragTarget;
156 changes: 93 additions & 63 deletions packages/perseus-editor/src/components/sortable.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,84 @@
import {css, StyleSheet} from "aphrodite";
import createReactClass from "create-react-class";
import PropTypes from "prop-types";
import * as React from "react";
import ReactDOM from "react-dom";

const PT = PropTypes;
type Props = {
className?: string;
components: React.ReactElement[];
onReorder: (i: any[]) => void;
style?: any;
verify: (i: any) => boolean;
};

type DefaultProps = {
verify: Props["verify"];
};

type State = {
dragging: number;
components: React.ReactElement[];
};

/**
* TODO(LEMS-2667): 11/26/24, at the time of writing this comment
* it has been identified that this file has been broken long before
* the refactoring of createReactClass. Future implementation need
* to determine how to fix this functionality or deprecate it.
* *
Comment on lines +23 to +27
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for leaving this comment here.

* Takes an array of components to sort.
* As of 08/05/24, there are two sortable components
* (one in perseus and one in perseus-editor).
* As far as I can tell, this one is only used in ExpressionEditor.
*/
// eslint-disable-next-line react/no-unsafe
const SortableArea = createReactClass({
propTypes: {
className: PT.string,
components: PT.arrayOf(PT.node).isRequired,
onReorder: PT.func.isRequired,
style: PT.any,
verify: PT.func,
},
getDefaultProps: function () {
return {verify: () => true};
},
getInitialState: function () {
return {
class SortableArea extends React.Component<Props, State> {
_dragItems: any;

static defaultProps: DefaultProps = {
verify: () => true,
};

constructor(props) {
super(props);
this.state = {
// index of the component being dragged
dragging: null,
dragging: -1,
components: this.props.components,
};
},

this.onDrop = this.onDrop.bind(this);
this.onDragStart = this.onDragStart.bind(this);
this.onDragEnter = this.onDragEnter.bind(this);
}

// Firefox refuses to drag an element unless you set data on it. Hackily
// add data each time an item is dragged.
componentDidMount: function () {
componentDidMount() {
this._setDragEvents();
},
}

// eslint-disable-next-line react/no-unsafe
UNSAFE_componentWillReceiveProps: function (nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({components: nextProps.components});
},
componentDidUpdate: function () {
}

componentDidUpdate() {
this._setDragEvents();
},
}

// Alternatively send each handler to each component individually,
// partially applied
onDragStart: function (startIndex) {
onDragStart(startIndex) {
this.setState({dragging: startIndex});
},
onDrop: function () {
}

onDrop() {
// tell the parent component
this.setState({dragging: null});
this.setState({dragging: -1});
this.props.onReorder(this.state.components);
},
onDragEnter: function (enterIndex) {
}

onDragEnter(enterIndex) {
// When a label is first dragged it triggers a dragEnter with itself,
// which we don't care about.
if (this.state.dragging === enterIndex) {
Expand All @@ -75,15 +100,18 @@ const SortableArea = createReactClass({
});
}
return verified;
},
_listenEvent: function (e) {
}

_listenEvent(e) {
e.dataTransfer.setData("hackhackhack", "because browsers!");
},
_cancelEvent: function (e) {
}

_cancelEvent(e) {
// prevent the browser from redirecting to 'because browsers!'
e.preventDefault();
},
_setDragEvents: function () {
}

_setDragEvents() {
this._dragItems = this._dragItems || [];
const items =
// @ts-expect-error - TS2531 - Object is possibly 'null'
Expand Down Expand Up @@ -117,8 +145,9 @@ const SortableArea = createReactClass({
dragItem.removeEventListener("dragstart", this._listenEvent);
dragItem.removeEventListener("drop", this._cancelEvent);
}
},
render: function () {
}

render() {
const sortables = this.state.components.map((component, index) => (
<SortableItem
index={index}
Expand All @@ -134,40 +163,41 @@ const SortableArea = createReactClass({
{sortables}
</ol>
);
},
});
}
}

type ItemProps = {
area: any;
component: React.ReactNode;
dragging: boolean;
draggable: boolean;
index: number;
};

// An individual sortable item
const SortableItem = createReactClass({
propTypes: {
area: PT.shape({
onDragEnter: PT.func.isRequired,
onDragStart: PT.func.isRequired,
onDrop: PT.func.isRequired,
}),
component: PT.node.isRequired,
dragging: PT.bool.isRequired,
draggable: PT.bool.isRequired,
index: PT.number.isRequired,
},
handleDragStart: function (e) {
class SortableItem extends React.Component<ItemProps> {
handleDragStart(e) {
e.nativeEvent.dataTransfer.effectAllowed = "move";
this.props.area.onDragStart(this.props.index);
},
handleDrop: function () {
}

handleDrop() {
this.props.area.onDrop(this.props.index);
},
handleDragEnter: function (e) {
}

handleDragEnter(e) {
const verified = this.props.area.onDragEnter(this.props.index);
// Ideally this would change the cursor based on whether this is a
// valid place to drop.
e.nativeEvent.dataTransfer.effectAllowed = verified ? "move" : "none";
},
handleDragOver: function (e) {
}

handleDragOver(e) {
// allow a drop by preventing default handling
e.preventDefault();
},
render: function () {
}

render() {
// I think these might be getting styles from Webapp
let dragState = "sortable-disabled";
if (this.props.dragging) {
Expand All @@ -188,8 +218,8 @@ const SortableItem = createReactClass({
{this.props.component}
</li>
);
},
});
}
}

const styles = StyleSheet.create({
sortableListItem: {
Expand Down
1 change: 0 additions & 1 deletion packages/perseus-editor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export {default as Editor} from "./editor";
export {default as i18n} from "./i18n";
export {default as IframeContentRenderer} from "./iframe-content-renderer";
export {default as MultiRendererEditor} from "./multirenderer-editor";
export {default as StatefulEditorPage} from "./stateful-editor-page";

import "./styles/perseus-editor.less";

Expand Down
Loading