mirror of
https://github.com/UniversityOfHelsinkiCS/ohtuilmo.git
synced 2026-10-12 19:03:41 +03:00
refactor: migrate to dndkit for drag list
This commit is contained in:
Generated
+1087
-577
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,8 @@
|
|||||||
"format:check": "oxfmt --check"
|
"format:check": "oxfmt --check"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dnd-kit/helpers": "^0.2.4",
|
||||||
|
"@dnd-kit/react": "^0.2.4",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mui/icons-material": "^9.2.0",
|
"@mui/icons-material": "^9.2.0",
|
||||||
@@ -31,7 +33,6 @@
|
|||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^19.2.8",
|
"react": "^19.2.8",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
"react-drag-list": "^1.1.0",
|
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
"react-redux": "^9.3.0",
|
"react-redux": "^9.3.0",
|
||||||
"react-router-dom": "^7.18.2",
|
"react-router-dom": "^7.18.2",
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { withRouter } from '../utils/withRouter'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import ReactDragList from 'react-drag-list'
|
|
||||||
|
|
||||||
import registrationActions from '../reducers/actions/registrationActions'
|
import registrationActions from '../reducers/actions/registrationActions'
|
||||||
import { setError } from '../reducers/actions/notificationActions'
|
import { setError } from '../reducers/actions/notificationActions'
|
||||||
@@ -11,8 +10,8 @@ import peerReviewService from '../services/peerReview'
|
|||||||
|
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography'
|
||||||
import { Input, Card, CardContent, Select, MenuItem } from '@mui/material'
|
import { Input, Card, CardContent, Select, MenuItem } from '@mui/material'
|
||||||
import TopicDialog from './TopicDialog'
|
|
||||||
import CourseMaterial from './common/CourseMaterial'
|
import CourseMaterial from './common/CourseMaterial'
|
||||||
|
import SortableTopicList from './SortableTopicList'
|
||||||
|
|
||||||
import { formatDate, extractCallingName } from '../utils/functions'
|
import { formatDate, extractCallingName } from '../utils/functions'
|
||||||
|
|
||||||
@@ -125,26 +124,8 @@ const PreferredTopics = ({ topics }) => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>Preferred Topics</h2>
|
<h2>Preferred Topics</h2>
|
||||||
<div className="dragndrop-container">
|
<div className="dragndrop-container" style={{ flexDirection: 'column' }}>
|
||||||
<div className="dragndrop-indexes-container">
|
<SortableTopicList topics={topics} isReadOnly={true} />
|
||||||
{topics.map((topic, index) => {
|
|
||||||
return (
|
|
||||||
<Card key={index} className="dragndrop-index">
|
|
||||||
{index + 1}
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<ReactDragList
|
|
||||||
className="dragndrop-list"
|
|
||||||
handles={false}
|
|
||||||
dataSource={topics}
|
|
||||||
rowKey="id"
|
|
||||||
row={(topic) => {
|
|
||||||
return <TopicDialog topic={topic} key={topic.content.title} />
|
|
||||||
}}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -27,10 +27,6 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dragndrop-list {
|
|
||||||
flex: 99;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dragndrop-indexes-container {
|
.dragndrop-indexes-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { withRouter } from '../utils/withRouter'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import ReactDragList from 'react-drag-list'
|
|
||||||
// MUI
|
// MUI
|
||||||
import Card from '@mui/material/Card'
|
import Card from '@mui/material/Card'
|
||||||
import CardContent from '@mui/material/CardContent'
|
import CardContent from '@mui/material/CardContent'
|
||||||
@@ -19,7 +18,6 @@ import configurationService from '../services/configuration'
|
|||||||
// components
|
// components
|
||||||
import LoadingSpinner from './common/LoadingSpinner'
|
import LoadingSpinner from './common/LoadingSpinner'
|
||||||
import CourseMaterial from './common/CourseMaterial'
|
import CourseMaterial from './common/CourseMaterial'
|
||||||
import TopicDialog from './TopicDialog'
|
|
||||||
import UserDetails from './UserDetails'
|
import UserDetails from './UserDetails'
|
||||||
import './RegistrationPage.css'
|
import './RegistrationPage.css'
|
||||||
// Actions
|
// Actions
|
||||||
@@ -27,6 +25,7 @@ import registrationPageActions from '../reducers/actions/registrationPageActions
|
|||||||
import * as notificationActions from '../reducers/actions/notificationActions'
|
import * as notificationActions from '../reducers/actions/notificationActions'
|
||||||
import registrationActions from '../reducers/actions/registrationActions'
|
import registrationActions from '../reducers/actions/registrationActions'
|
||||||
import registrationmanagementActions from '../reducers/actions/registrationManagementActions'
|
import registrationmanagementActions from '../reducers/actions/registrationManagementActions'
|
||||||
|
import SortableTopicList from './SortableTopicList'
|
||||||
|
|
||||||
const Prerequisites = ({ checkbox1, checkbox2, checkbox3, onToggle1, onToggle2, onToggle3 }) => {
|
const Prerequisites = ({ checkbox1, checkbox2, checkbox3, onToggle1, onToggle2, onToggle3 }) => {
|
||||||
return (
|
return (
|
||||||
@@ -306,12 +305,6 @@ class RegistrationPage extends React.Component {
|
|||||||
</Card>
|
</Card>
|
||||||
))
|
))
|
||||||
|
|
||||||
const indexes = this.props.topics.map((item, idx) => (
|
|
||||||
<Card key={idx} className="dragndrop-index">
|
|
||||||
{idx + 1}
|
|
||||||
</Card>
|
|
||||||
))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -455,15 +448,7 @@ class RegistrationPage extends React.Component {
|
|||||||
dragging and dropping, click to expand details
|
dragging and dropping, click to expand details
|
||||||
</div>
|
</div>
|
||||||
<div className="dragndrop-container">
|
<div className="dragndrop-container">
|
||||||
<div className="dragndrop-indexes-container">{indexes}</div>
|
<SortableTopicList topics={this.props.topics} onUpdate={this.handleUpdate} />
|
||||||
<ReactDragList
|
|
||||||
className="dragndrop-list"
|
|
||||||
handles={false}
|
|
||||||
dataSource={this.props.topics}
|
|
||||||
onUpdate={this.handleUpdate}
|
|
||||||
rowKey="id"
|
|
||||||
row={(topic) => <TopicDialog topic={topic} key={topic.content.title} />}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { DragDropProvider } from '@dnd-kit/react'
|
||||||
|
import { useSortable } from '@dnd-kit/react/sortable'
|
||||||
|
import { move } from '@dnd-kit/helpers'
|
||||||
|
import Card from '@mui/material/Card'
|
||||||
|
import TopicDialog from './TopicDialog'
|
||||||
|
|
||||||
|
const SortableTopicItem = ({ topic, index, isReadOnly }) => {
|
||||||
|
const { ref, isDragging } = useSortable({
|
||||||
|
id: topic.id,
|
||||||
|
index,
|
||||||
|
disabled: isReadOnly,
|
||||||
|
})
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
opacity: isDragging ? 0.4 : 1,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'stretch',
|
||||||
|
marginBottom: '8px',
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={isReadOnly ? null : ref}
|
||||||
|
style={{ ...style, cursor: isReadOnly ? 'default' : 'grab' }}
|
||||||
|
>
|
||||||
|
<Card
|
||||||
|
className="dragndrop-index"
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
minWidth: '40px',
|
||||||
|
maxHeight: 'none',
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{index + 1}
|
||||||
|
</Card>
|
||||||
|
<div style={{ flex: 1, minWidth: 0 }}>
|
||||||
|
<TopicDialog topic={topic} showDragIcon={!isReadOnly} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const SortableTopicList = ({ topics, onUpdate, isReadOnly }) => {
|
||||||
|
const handleDragEnd = (event) => {
|
||||||
|
if (!event.canceled && onUpdate) {
|
||||||
|
const newTopics = move(topics, event)
|
||||||
|
onUpdate(null, newTopics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DragDropProvider onDragEnd={handleDragEnd}>
|
||||||
|
<div className="dragndrop-list">
|
||||||
|
{topics.map((topic, index) => (
|
||||||
|
<SortableTopicItem key={topic.id} topic={topic} index={index} isReadOnly={isReadOnly} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DragDropProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SortableTopicList
|
||||||
@@ -7,6 +7,7 @@ import Card from '@mui/material/Card'
|
|||||||
import CardContent from '@mui/material/CardContent'
|
import CardContent from '@mui/material/CardContent'
|
||||||
import Topic from './Topic'
|
import Topic from './Topic'
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography'
|
||||||
|
import DragIndicatorIcon from '@mui/icons-material/DragIndicator'
|
||||||
|
|
||||||
class TopicDialog extends React.Component {
|
class TopicDialog extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -37,8 +38,29 @@ class TopicDialog extends React.Component {
|
|||||||
: 'Software is published under an open source license'
|
: 'Software is published under an open source license'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card style={{ margin: '2px', height: '78px' }}>
|
<Card style={{ margin: '2px', minHeight: '78px' }}>
|
||||||
<CardContent style={{ padding, display: 'flex', flexDirection: 'row' }}>
|
<CardContent
|
||||||
|
style={{
|
||||||
|
padding,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{this.props.showDragIcon && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginRight: '12px',
|
||||||
|
color: '#888',
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DragIndicatorIcon />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div style={{ flex: 4 }}>
|
<div style={{ flex: 4 }}>
|
||||||
<Typography style={{ flex: 1, fontWeight: 'bold' }}>
|
<Typography style={{ flex: 1, fontWeight: 'bold' }}>
|
||||||
{this.props.topic.content.title}
|
{this.props.topic.content.title}
|
||||||
|
|||||||
Generated
-2
@@ -6,8 +6,6 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ohtuilmo",
|
"name": "ohtuilmo",
|
||||||
"version": "1.0.0",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^17.3.0"
|
"lint-staged": "^17.3.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user