mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 08:39:59 +00:00
Move EditableListItem component to EditableList file + cleanup
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
"use strict";
|
||||
|
||||
import React, { Component } from "react";
|
||||
import EditableListItem from "./EditableListItem";
|
||||
|
||||
const _ = browser.i18n.getMessage;
|
||||
|
||||
@@ -50,9 +49,7 @@ export default class EditableList extends Component<
|
||||
{ this.state.rawView
|
||||
? (
|
||||
<textarea className="editable-list__raw-view"
|
||||
rows={ this.props.data.length > 10
|
||||
? this.props.data.length
|
||||
: 10 }
|
||||
rows={ Math.min(this.props.data.length, 10) }
|
||||
value={ this.state.rawViewValue }
|
||||
onChange={ this.handleRawViewTextAreaChange }
|
||||
ref={ el => { this.rawViewTextArea = el; }}>
|
||||
@@ -66,6 +63,7 @@ export default class EditableList extends Component<
|
||||
onRemove={ this.handleItemRemove }
|
||||
onEdit={ this.handleItemEdit }
|
||||
key={ i } /> )}
|
||||
|
||||
{ this.state.addingNewItem &&
|
||||
<EditableListItem text=""
|
||||
itemPattern={ this.props.itemPattern }
|
||||
@@ -73,7 +71,6 @@ export default class EditableList extends Component<
|
||||
onRemove={ this.handleNewItemRemove }
|
||||
onEdit={ this.handleNewItemEdit }
|
||||
editing={ true } /> }
|
||||
|
||||
</ul>
|
||||
)}
|
||||
<hr />
|
||||
@@ -85,12 +82,14 @@ export default class EditableList extends Component<
|
||||
type="button">
|
||||
<img src="assets/photon_new.svg" alt="icon, add" />
|
||||
</button> }
|
||||
|
||||
{ this.state.rawView &&
|
||||
<button className="editable-list__save-raw-button"
|
||||
onClick={ this.handleSaveRaw }
|
||||
type="button">
|
||||
{ _("optionsUserAgentWhitelistSaveRaw") }
|
||||
</button> }
|
||||
|
||||
<button className="editable-list__view-button"
|
||||
onClick={ this.handleSwitchView }
|
||||
type="button">
|
||||
@@ -113,8 +112,8 @@ export default class EditableList extends Component<
|
||||
private handleItemEdit (item: string, newValue: string) {
|
||||
this.props.onChange(this.props.data.map(
|
||||
currentItem => currentItem === item
|
||||
? newValue
|
||||
: currentItem));
|
||||
? newValue
|
||||
: currentItem));
|
||||
}
|
||||
|
||||
private handleSwitchView () {
|
||||
@@ -188,3 +187,128 @@ export default class EditableList extends Component<
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface EditableListItemProps {
|
||||
text: string;
|
||||
itemPattern: RegExp;
|
||||
editing?: boolean;
|
||||
itemPatternError (err?: string): string;
|
||||
onRemove (item: string): void;
|
||||
onEdit (item: string, newValue: string): void;
|
||||
}
|
||||
|
||||
interface EditableListItemState {
|
||||
editing: boolean;
|
||||
editValue: string;
|
||||
}
|
||||
|
||||
class EditableListItem extends Component<
|
||||
EditableListItemProps, EditableListItemState> {
|
||||
|
||||
private input: (HTMLInputElement | null) = null;
|
||||
|
||||
constructor (props: EditableListItemProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
editing: this.props.editing || false
|
||||
, editValue: ""
|
||||
};
|
||||
|
||||
this.handleRemove = this.handleRemove.bind(this);
|
||||
this.handleEditBegin = this.handleEditBegin.bind(this);
|
||||
this.handleEditEnd = this.handleEditEnd.bind(this);
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
this.handleInputKeyPress = this.handleInputKeyPress.bind(this);
|
||||
}
|
||||
|
||||
public render () {
|
||||
const selected = this.state.editing
|
||||
? "editable-list__item--selected" : "";
|
||||
|
||||
return (
|
||||
<li className={`editable-list__item ${selected}`}>
|
||||
<div className="editable-list__title"
|
||||
onDoubleClick={ this.handleEditBegin }>
|
||||
|
||||
{ this.state.editing
|
||||
? <input className="editable-list__edit-field"
|
||||
type="text"
|
||||
ref={ input => this.input = input }
|
||||
value={ this.state.editValue }
|
||||
onBlur={ this.handleEditEnd }
|
||||
onChange={ this.handleInputChange }
|
||||
onKeyPress={ this.handleInputKeyPress }/>
|
||||
: this.props.text }
|
||||
</div>
|
||||
|
||||
<button className="editable-list__edit-button ghost"
|
||||
title={ _("optionsUserAgentWhitelistEditItem") }
|
||||
onClick={ this.handleEditBegin }
|
||||
type="button">
|
||||
<img src="assets/photon_edit.svg" alt="icon, edit" />
|
||||
</button>
|
||||
|
||||
<button className="editable-list__remove-button ghost"
|
||||
title={ _("optionsUserAgentWhitelistRemoveItem") }
|
||||
onClick={ this.handleRemove }
|
||||
type="button">
|
||||
<img src="assets/photon_delete.svg" alt="icon, remove" />
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
private stopEditing (input: HTMLInputElement) {
|
||||
if (this.props.editing
|
||||
&& !this.props.itemPattern.test(this.state.editValue)) {
|
||||
input.setCustomValidity(this.props.itemPatternError());
|
||||
}
|
||||
|
||||
if (!input.validity.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onEdit(this.props.text, this.state.editValue);
|
||||
this.setState({
|
||||
editing: false
|
||||
, editValue: ""
|
||||
});
|
||||
}
|
||||
|
||||
private handleRemove () {
|
||||
this.props.onRemove(this.props.text);
|
||||
}
|
||||
|
||||
private handleEditBegin () {
|
||||
this.setState({
|
||||
editing: true
|
||||
, editValue: this.props.text
|
||||
}, () => {
|
||||
this.input?.focus();
|
||||
this.input?.select();
|
||||
});
|
||||
}
|
||||
|
||||
private handleEditEnd (ev: React.FocusEvent<HTMLInputElement>) {
|
||||
this.stopEditing(ev.target);
|
||||
}
|
||||
|
||||
private handleInputChange (ev: React.ChangeEvent<HTMLInputElement>) {
|
||||
this.setState({
|
||||
editValue: ev.target.value
|
||||
});
|
||||
|
||||
// If invalid, set custom error from parent
|
||||
ev.target.setCustomValidity(!this.props.itemPattern.test(ev.target.value)
|
||||
? this.props.itemPatternError()
|
||||
: "");
|
||||
}
|
||||
|
||||
private handleInputKeyPress (ev: React.KeyboardEvent<HTMLInputElement>) {
|
||||
if (ev.key === "Enter") {
|
||||
this.stopEditing(ev.target as HTMLInputElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/* tslint:disable:max-line-length */
|
||||
"use strict";
|
||||
|
||||
import React, { Component } from "react";
|
||||
|
||||
const _ = browser.i18n.getMessage;
|
||||
|
||||
|
||||
interface EditableListItemProps {
|
||||
text: string;
|
||||
itemPattern: RegExp;
|
||||
editing?: boolean;
|
||||
itemPatternError (err?: string): string;
|
||||
onRemove (item: string): void;
|
||||
onEdit (item: string, newValue: string): void;
|
||||
}
|
||||
|
||||
interface EditableListItemState {
|
||||
editing: boolean;
|
||||
editValue: string;
|
||||
}
|
||||
|
||||
export default class EditableListItem extends Component<
|
||||
EditableListItemProps, EditableListItemState> {
|
||||
|
||||
private input: (HTMLInputElement | null) = null;
|
||||
|
||||
constructor (props: EditableListItemProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
editing: this.props.editing || false
|
||||
, editValue: ""
|
||||
};
|
||||
|
||||
this.handleRemove = this.handleRemove.bind(this);
|
||||
this.handleEditBegin = this.handleEditBegin.bind(this);
|
||||
this.handleEditEnd = this.handleEditEnd.bind(this);
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
this.handleInputKeyPress = this.handleInputKeyPress.bind(this);
|
||||
}
|
||||
|
||||
public render () {
|
||||
const selected = this.state.editing
|
||||
? "editable-list__item--selected" : "";
|
||||
|
||||
return (
|
||||
<li className={`editable-list__item ${selected}`}>
|
||||
<div className="editable-list__title"
|
||||
onDoubleClick={ this.handleEditBegin }>
|
||||
{ this.state.editing
|
||||
? <input className="editable-list__edit-field"
|
||||
type="text"
|
||||
ref={ input => this.input = input }
|
||||
value={ this.state.editValue }
|
||||
onBlur={ this.handleEditEnd }
|
||||
onChange={ this.handleInputChange }
|
||||
onKeyPress={ this.handleInputKeyPress }/>
|
||||
: this.props.text }
|
||||
</div>
|
||||
<button className="editable-list__edit-button ghost"
|
||||
title={ _("optionsUserAgentWhitelistEditItem") }
|
||||
onClick={ this.handleEditBegin }
|
||||
type="button">
|
||||
<img src="assets/photon_edit.svg" alt="icon, edit" />
|
||||
</button>
|
||||
<button className="editable-list__remove-button ghost"
|
||||
title={ _("optionsUserAgentWhitelistRemoveItem") }
|
||||
onClick={ this.handleRemove }
|
||||
type="button">
|
||||
<img src="assets/photon_delete.svg" alt="icon, remove" />
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
private stopEditing (input: HTMLInputElement) {
|
||||
if (this.props.editing
|
||||
&& !this.props.itemPattern.test(this.state.editValue)) {
|
||||
input.setCustomValidity(this.props.itemPatternError());
|
||||
}
|
||||
|
||||
if (!input.validity.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onEdit(this.props.text, this.state.editValue);
|
||||
this.setState({
|
||||
editing: false
|
||||
, editValue: ""
|
||||
});
|
||||
}
|
||||
|
||||
private handleRemove () {
|
||||
this.props.onRemove(this.props.text);
|
||||
}
|
||||
|
||||
private handleEditBegin () {
|
||||
this.setState({
|
||||
editing: true
|
||||
, editValue: this.props.text
|
||||
}, () => {
|
||||
this.input?.focus();
|
||||
this.input?.select();
|
||||
});
|
||||
}
|
||||
|
||||
private handleEditEnd (ev: React.FocusEvent<HTMLInputElement>) {
|
||||
this.stopEditing(ev.target);
|
||||
}
|
||||
|
||||
private handleInputChange (ev: React.ChangeEvent<HTMLInputElement>) {
|
||||
this.setState({
|
||||
editValue: ev.target.value
|
||||
});
|
||||
|
||||
if (!this.props.itemPattern.test(ev.target.value)) {
|
||||
ev.target.setCustomValidity(this.props.itemPatternError());
|
||||
} else {
|
||||
ev.target.setCustomValidity("");
|
||||
}
|
||||
}
|
||||
|
||||
private handleInputKeyPress (ev: React.KeyboardEvent<HTMLInputElement>) {
|
||||
if (ev.key === "Enter") {
|
||||
this.stopEditing(ev.target as HTMLInputElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -409,6 +409,7 @@ button.ghost:not(:hover) {
|
||||
|
||||
.editable-list__raw-view {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
resize: vertical;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user