Allow editing polls (#7806)
This commit is contained in:
parent
fa9af44523
commit
7387f3c80a
8 changed files with 310 additions and 38 deletions
|
@ -16,7 +16,8 @@ limitations under the License.
|
|||
|
||||
import React, { ChangeEvent, createRef } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { M_POLL_KIND_DISCLOSED, PollStartEvent } from "matrix-events-sdk";
|
||||
import { IPartialEvent, M_POLL_KIND_DISCLOSED, M_POLL_START, PollStartEvent } from "matrix-events-sdk";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
|
||||
import ScrollableBaseModal, { IScrollableBaseState } from "../dialogs/ScrollableBaseModal";
|
||||
import { IDialogProps } from "../dialogs/IDialogProps";
|
||||
|
@ -31,6 +32,7 @@ import Spinner from "./Spinner";
|
|||
interface IProps extends IDialogProps {
|
||||
room: Room;
|
||||
threadId?: string;
|
||||
editingMxEvent?: MatrixEvent; // Truthy if we are editing an existing poll
|
||||
}
|
||||
|
||||
interface IState extends IScrollableBaseState {
|
||||
|
@ -45,21 +47,42 @@ const DEFAULT_NUM_OPTIONS = 2;
|
|||
const MAX_QUESTION_LENGTH = 340;
|
||||
const MAX_OPTION_LENGTH = 340;
|
||||
|
||||
function creatingInitialState(): IState {
|
||||
return {
|
||||
title: _t("Create poll"),
|
||||
actionLabel: _t("Create Poll"),
|
||||
canSubmit: false, // need to add a question and at least one option first
|
||||
question: "",
|
||||
options: arraySeed("", DEFAULT_NUM_OPTIONS),
|
||||
busy: false,
|
||||
};
|
||||
}
|
||||
|
||||
function editingInitialState(editingMxEvent: MatrixEvent): IState {
|
||||
const poll = editingMxEvent.unstableExtensibleEvent as PollStartEvent;
|
||||
if (!poll?.isEquivalentTo(M_POLL_START)) return creatingInitialState();
|
||||
|
||||
return {
|
||||
title: _t("Edit poll"),
|
||||
actionLabel: _t("Done"),
|
||||
canSubmit: true,
|
||||
question: poll.question.text,
|
||||
options: poll.answers.map(ans => ans.text),
|
||||
busy: false,
|
||||
};
|
||||
}
|
||||
|
||||
export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState> {
|
||||
private addOptionRef = createRef<HTMLDivElement>();
|
||||
|
||||
public constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
title: _t("Create poll"),
|
||||
actionLabel: _t("Create Poll"),
|
||||
canSubmit: false, // need to add a question and at least one option first
|
||||
|
||||
question: "",
|
||||
options: arraySeed("", DEFAULT_NUM_OPTIONS),
|
||||
busy: false,
|
||||
};
|
||||
this.state = (
|
||||
props.editingMxEvent
|
||||
? editingInitialState(props.editingMxEvent)
|
||||
: creatingInitialState()
|
||||
);
|
||||
}
|
||||
|
||||
private checkCanSubmit() {
|
||||
|
@ -97,13 +120,32 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
|
|||
});
|
||||
};
|
||||
|
||||
protected submit(): void {
|
||||
this.setState({ busy: true, canSubmit: false });
|
||||
const pollEvent = PollStartEvent.from(
|
||||
private createEvent(): IPartialEvent<object> {
|
||||
const pollStart = PollStartEvent.from(
|
||||
this.state.question.trim(),
|
||||
this.state.options.map(a => a.trim()).filter(a => !!a),
|
||||
M_POLL_KIND_DISCLOSED,
|
||||
).serialize();
|
||||
|
||||
if (!this.props.editingMxEvent) {
|
||||
return pollStart;
|
||||
} else {
|
||||
return {
|
||||
"content": {
|
||||
"m.new_content": pollStart.content,
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.replace",
|
||||
"event_id": this.props.editingMxEvent.getId(),
|
||||
},
|
||||
},
|
||||
"type": pollStart.type,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected submit(): void {
|
||||
this.setState({ busy: true, canSubmit: false });
|
||||
const pollEvent = this.createEvent();
|
||||
this.matrixClient.sendEvent(
|
||||
this.props.room.roomId,
|
||||
this.props.threadId,
|
||||
|
@ -159,7 +201,10 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
|
|||
maxLength={MAX_OPTION_LENGTH}
|
||||
label={_t("Option %(number)s", { number: i + 1 })}
|
||||
placeholder={_t("Write an option")}
|
||||
onChange={e => this.onOptionChange(i, e)}
|
||||
onChange={
|
||||
(e: ChangeEvent<HTMLInputElement>) =>
|
||||
this.onOptionChange(i, e)
|
||||
}
|
||||
usePlaceholderAsHint={true}
|
||||
disabled={this.state.busy}
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue