mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-12 02:29:59 +00:00
Move EditableListItem component to EditableList file + cleanup
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import EditableListItem from "./EditableListItem";
|
|
||||||
|
|
||||||
const _ = browser.i18n.getMessage;
|
const _ = browser.i18n.getMessage;
|
||||||
|
|
||||||
@@ -50,9 +49,7 @@ export default class EditableList extends Component<
|
|||||||
{ this.state.rawView
|
{ this.state.rawView
|
||||||
? (
|
? (
|
||||||
<textarea className="editable-list__raw-view"
|
<textarea className="editable-list__raw-view"
|
||||||
rows={ this.props.data.length > 10
|
rows={ Math.min(this.props.data.length, 10) }
|
||||||
? this.props.data.length
|
|
||||||
: 10 }
|
|
||||||
value={ this.state.rawViewValue }
|
value={ this.state.rawViewValue }
|
||||||
onChange={ this.handleRawViewTextAreaChange }
|
onChange={ this.handleRawViewTextAreaChange }
|
||||||
ref={ el => { this.rawViewTextArea = el; }}>
|
ref={ el => { this.rawViewTextArea = el; }}>
|
||||||
@@ -66,6 +63,7 @@ export default class EditableList extends Component<
|
|||||||
onRemove={ this.handleItemRemove }
|
onRemove={ this.handleItemRemove }
|
||||||
onEdit={ this.handleItemEdit }
|
onEdit={ this.handleItemEdit }
|
||||||
key={ i } /> )}
|
key={ i } /> )}
|
||||||
|
|
||||||
{ this.state.addingNewItem &&
|
{ this.state.addingNewItem &&
|
||||||
<EditableListItem text=""
|
<EditableListItem text=""
|
||||||
itemPattern={ this.props.itemPattern }
|
itemPattern={ this.props.itemPattern }
|
||||||
@@ -73,7 +71,6 @@ export default class EditableList extends Component<
|
|||||||
onRemove={ this.handleNewItemRemove }
|
onRemove={ this.handleNewItemRemove }
|
||||||
onEdit={ this.handleNewItemEdit }
|
onEdit={ this.handleNewItemEdit }
|
||||||
editing={ true } /> }
|
editing={ true } /> }
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
<hr />
|
<hr />
|
||||||
@@ -85,12 +82,14 @@ export default class EditableList extends Component<
|
|||||||
type="button">
|
type="button">
|
||||||
<img src="assets/photon_new.svg" alt="icon, add" />
|
<img src="assets/photon_new.svg" alt="icon, add" />
|
||||||
</button> }
|
</button> }
|
||||||
|
|
||||||
{ this.state.rawView &&
|
{ this.state.rawView &&
|
||||||
<button className="editable-list__save-raw-button"
|
<button className="editable-list__save-raw-button"
|
||||||
onClick={ this.handleSaveRaw }
|
onClick={ this.handleSaveRaw }
|
||||||
type="button">
|
type="button">
|
||||||
{ _("optionsUserAgentWhitelistSaveRaw") }
|
{ _("optionsUserAgentWhitelistSaveRaw") }
|
||||||
</button> }
|
</button> }
|
||||||
|
|
||||||
<button className="editable-list__view-button"
|
<button className="editable-list__view-button"
|
||||||
onClick={ this.handleSwitchView }
|
onClick={ this.handleSwitchView }
|
||||||
type="button">
|
type="button">
|
||||||
@@ -113,8 +112,8 @@ export default class EditableList extends Component<
|
|||||||
private handleItemEdit (item: string, newValue: string) {
|
private handleItemEdit (item: string, newValue: string) {
|
||||||
this.props.onChange(this.props.data.map(
|
this.props.onChange(this.props.data.map(
|
||||||
currentItem => currentItem === item
|
currentItem => currentItem === item
|
||||||
? newValue
|
? newValue
|
||||||
: currentItem));
|
: currentItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleSwitchView () {
|
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 {
|
.editable-list__raw-view {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user