Add drag and drop
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import * as React from "react";
|
||||
import { Fragment } from "react";
|
||||
import * as shortid from "shortid";
|
||||
import { Draggable } from "react-beautiful-dnd";
|
||||
import { Question, InputProps, optionTypes, SignupQuestionError } from "./index";
|
||||
import OptionsWidget from "./OptionsWidget";
|
||||
import TypeWidget from "./TypeWidget";
|
||||
|
||||
export interface QuestionListProps {
|
||||
questions: Question[];
|
||||
innerRef: any;
|
||||
placeholder: any;
|
||||
onChange: (value: Question[]) => void;
|
||||
}
|
||||
export interface QuestionListState { }
|
||||
|
||||
class QuestionList extends React.Component<QuestionListProps, QuestionListState> {
|
||||
renderTextWidget = ({ questions, value, index }: InputProps) => (
|
||||
<input type="text" value={value} onChange={this.handleNameInputChange(questions, index)} />
|
||||
)
|
||||
|
||||
handleNameInputChange = (questions: Question[], index: number) => (event) => {
|
||||
const { onChange } = this.props;
|
||||
const val = event.target.value;
|
||||
questions[index].name = val;
|
||||
onChange(questions);
|
||||
}
|
||||
|
||||
renderQuestions() {
|
||||
const { questions, onChange, placeholder } = this.props;
|
||||
return questions.map((q, index) => {
|
||||
const nameWidgetProps = { value: q.name, type: "text", questions, index };
|
||||
const nameWidget = this.renderTextWidget(nameWidgetProps);
|
||||
|
||||
const dataProps = { value: q.options, type: q.type, questions, index };
|
||||
const optionsWidget = <OptionsWidget inputProps={dataProps} onChange={onChange} />;
|
||||
const typeSelectWidget = <TypeWidget inputProps={dataProps} onChange={onChange} />;
|
||||
return (
|
||||
<Draggable draggableId={q.id} key={q.id} index={index}>
|
||||
{(provided) => (
|
||||
<div
|
||||
className="signup-questions-widget-row"
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
{nameWidget}
|
||||
{typeSelectWidget}
|
||||
{optionsWidget}
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { placeholder, innerRef } = this.props;
|
||||
|
||||
return (
|
||||
<div ref={innerRef}>
|
||||
{ this.renderQuestions() }
|
||||
{ placeholder }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default QuestionList;
|
||||
@@ -11,5 +11,7 @@
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 0.5rem;
|
||||
background-color: $green;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import * as React from "react";
|
||||
import * as shortid from "shortid";
|
||||
import OptionsWidget from "./OptionsWidget";
|
||||
import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
||||
import { Question, InputProps, optionTypes } from ".";
|
||||
// @ts-ignore
|
||||
import * as AddIcon from "../../assets/img/add-icon.png";
|
||||
import "./SignupQuestionsWidget.scss";
|
||||
import TypeWidget from "./TypeWidget";
|
||||
import QuestionList from "./QuestionList";
|
||||
|
||||
export interface SignupQuestionsWidgetProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
onFocus: () => void;
|
||||
required: boolean;
|
||||
disabled: boolean;
|
||||
}
|
||||
@@ -34,42 +37,39 @@ class SignupQuestionsWidget extends React.Component<SignupQuestionsWidgetProps,
|
||||
this.onValueChange(newQuestions);
|
||||
}
|
||||
|
||||
handleNameInputChange = (questions: Question[], index: number) => (event) => {
|
||||
const val = event.target.value;
|
||||
questions[index].name = val;
|
||||
handleDragEnd = (questions: Question[]) => (result) => {
|
||||
const srcIndex = result.source.index;
|
||||
const dstIndex = result.destination.index;
|
||||
const srcCopy = { ...questions[srcIndex] };
|
||||
const dstCopy = { ...questions[dstIndex] };
|
||||
questions[dstIndex] = srcCopy;
|
||||
questions[srcIndex] = dstCopy;
|
||||
|
||||
this.onValueChange(questions);
|
||||
}
|
||||
|
||||
renderTextWidget = ({ questions, value, index }: InputProps) => (
|
||||
<input type="text" value={value} onChange={this.handleNameInputChange(questions, index)} />
|
||||
)
|
||||
|
||||
renderQuestions = (questions: Question[]) => {
|
||||
return questions.map((q, index) => {
|
||||
const nameWidgetProps = { value: q.name, type: "text", questions, index };
|
||||
const nameWidget = this.renderTextWidget(nameWidgetProps);
|
||||
|
||||
const dataProps = { value: q.options, type: q.type, questions, index };
|
||||
const optionsWidget = <OptionsWidget inputProps={dataProps} onChange={this.onValueChange} />;
|
||||
const typeSelectWidget = <TypeWidget inputProps={dataProps} onChange={this.onValueChange} />;
|
||||
return (
|
||||
<div key={q.id} className="signup-questions-widget-row">
|
||||
{ nameWidget }
|
||||
{ typeSelectWidget }
|
||||
{ optionsWidget }
|
||||
</div>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value } = this.props;
|
||||
const { value, onFocus } = this.props;
|
||||
|
||||
const questions = JSON.parse(value) as Question[];
|
||||
|
||||
return (
|
||||
<div className="signup-questions-widget">
|
||||
{this.renderQuestions(questions)}
|
||||
<DragDropContext
|
||||
onDragEnd={this.handleDragEnd(questions)}
|
||||
onDragStart={onFocus}
|
||||
>
|
||||
<Droppable droppableId="questions">
|
||||
{(provided) => (
|
||||
<QuestionList
|
||||
{...provided.droppableProps}
|
||||
innerRef={provided.innerRef}
|
||||
questions={questions}
|
||||
onChange={this.onValueChange}
|
||||
placeholder={provided.placeholder} />
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
<button type="button" className="add-link" onClick={this.handleNewRowClick(questions)}>
|
||||
<img src={AddIcon} /> New Question
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user