From 4428963314c290353ba36c46670743097ed48dac Mon Sep 17 00:00:00 2001 From: Khaliq Gant Date: Fri, 3 May 2019 17:29:52 +0200 Subject: [PATCH 01/11] allow a tag to be renamed and update all notes that use that tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • repurpose RenameFolderModal.styl to RenameModal so it is more generic --- browser/main/SideNav/index.js | 16 +++ browser/main/modals/RenameFolderModal.js | 2 +- ...enameFolderModal.styl => RenameModal.styl} | 0 browser/main/modals/RenameTagModal.js | 128 ++++++++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) rename browser/main/modals/{RenameFolderModal.styl => RenameModal.styl} (100%) create mode 100644 browser/main/modals/RenameTagModal.js diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 640bedbf5..ada3c764d 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -5,6 +5,7 @@ import dataApi from 'browser/main/lib/dataApi' import styles from './SideNav.styl' import { openModal } from 'browser/main/lib/modal' import PreferencesModal from '../modals/PreferencesModal' +import RenameTagModal from 'browser/main/modals/RenameTagModal' import ConfigManager from 'browser/main/lib/ConfigManager' import StorageItem from './StorageItem' import TagListItem from 'browser/components/TagListItem' @@ -126,6 +127,11 @@ class SideNav extends React.Component { click: this.displayColorPicker.bind(this, tag, e.target.getBoundingClientRect()) }) + menu.push({ + label: i18n.__('Rename Tag'), + click: this.handleRenameTagClick.bind(this, tag) + }) + context.popup(menu) } @@ -149,6 +155,16 @@ class SideNav extends React.Component { }) } + handleRenameTagClick (tagName) { + const { data, dispatch } = this.props + + openModal(RenameTagModal, { + tagName, + data, + dispatch + }) + } + handleColorPickerConfirm (color) { const { dispatch, config: {coloredTags} } = this.props const { colorPicker: { tagName } } = this.state diff --git a/browser/main/modals/RenameFolderModal.js b/browser/main/modals/RenameFolderModal.js index edbcee670..c58807f98 100644 --- a/browser/main/modals/RenameFolderModal.js +++ b/browser/main/modals/RenameFolderModal.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' -import styles from './RenameFolderModal.styl' +import styles from './RenameModal.styl' import dataApi from 'browser/main/lib/dataApi' import store from 'browser/main/store' import ModalEscButton from 'browser/components/ModalEscButton' diff --git a/browser/main/modals/RenameFolderModal.styl b/browser/main/modals/RenameModal.styl similarity index 100% rename from browser/main/modals/RenameFolderModal.styl rename to browser/main/modals/RenameModal.styl diff --git a/browser/main/modals/RenameTagModal.js b/browser/main/modals/RenameTagModal.js new file mode 100644 index 000000000..985bee533 --- /dev/null +++ b/browser/main/modals/RenameTagModal.js @@ -0,0 +1,128 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './RenameModal.styl' +import dataApi from 'browser/main/lib/dataApi' +import ModalEscButton from 'browser/components/ModalEscButton' +import i18n from 'browser/lib/i18n' + +class RenameTagModal extends React.Component { + constructor (props) { + super(props) + + this.state = { + name: props.tagName, + oldName: props.tagName + } + } + + componentDidMount () { + this.refs.name.focus() + this.refs.name.select() + } + + handleCloseButtonClick (e) { + this.props.close() + } + + handleChange (e) { + this.setState({ + name: this.refs.name.value + }) + } + + handleKeyDown (e) { + if (e.keyCode === 27) { + this.props.close() + } + } + + handleInputKeyDown (e) { + switch (e.keyCode) { + case 13: + this.confirm() + } + } + + handleConfirmButtonClick (e) { + this.confirm() + } + + confirm () { + if (this.state.name.trim().length > 0) { + const { name, oldName } = this.state + this.renameTag(oldName, name) + } + } + + renameTag (tag, updatedTag) { + const { data, dispatch } = this.props + + const notes = data.noteMap + .map(note => note) + .filter(note => note.tags.indexOf(tag) !== -1) + .map(note => { + note = Object.assign({}, note) + note.tags = note.tags.slice() + + note.tags[note.tags.indexOf(tag)] = updatedTag + + return note + }) + + Promise + .all(notes.map(note => dataApi.updateNote(note.storage, note.key, note))) + .then(updatedNotes => { + updatedNotes.forEach(note => { + dispatch({ + type: 'UPDATE_NOTE', + note + }) + }) + }) + .then(() => { + this.props.close() + }) + } + + render () { + return ( +
this.handleKeyDown(e)} + > +
+
{i18n.__('Rename Tag')}
+
+ this.handleCloseButtonClick(e)} /> + +
+ this.handleChange(e)} + onKeyDown={(e) => this.handleInputKeyDown(e)} + /> + +
+
+ ) + } +} + +RenameTagModal.propTypes = { + storage: PropTypes.shape({ + key: PropTypes.string + }), + folder: PropTypes.shape({ + key: PropTypes.string, + name: PropTypes.string + }) +} + +export default CSSModules(RenameTagModal, styles) From 242e8b6e33a50037c9aef89851814d7c02b1a7f8 Mon Sep 17 00:00:00 2001 From: Khaliq Gant Date: Sun, 5 May 2019 11:15:53 +0200 Subject: [PATCH 02/11] call handleConfirmButtonClick directly instead of sending through a confirm method --- browser/main/modals/RenameTagModal.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/browser/main/modals/RenameTagModal.js b/browser/main/modals/RenameTagModal.js index 985bee533..c63141482 100644 --- a/browser/main/modals/RenameTagModal.js +++ b/browser/main/modals/RenameTagModal.js @@ -40,15 +40,11 @@ class RenameTagModal extends React.Component { handleInputKeyDown (e) { switch (e.keyCode) { case 13: - this.confirm() + this.handleConfirmButtonClick() } } handleConfirmButtonClick (e) { - this.confirm() - } - - confirm () { if (this.state.name.trim().length > 0) { const { name, oldName } = this.state this.renameTag(oldName, name) From 0f6e2181911554d386d51ccd3facaec2d4c0a51e Mon Sep 17 00:00:00 2001 From: Khaliq Gant Date: Sun, 5 May 2019 11:25:53 +0200 Subject: [PATCH 03/11] better name for method to confirm the rename --- browser/main/modals/RenameTagModal.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/main/modals/RenameTagModal.js b/browser/main/modals/RenameTagModal.js index c63141482..978bb2ee9 100644 --- a/browser/main/modals/RenameTagModal.js +++ b/browser/main/modals/RenameTagModal.js @@ -40,11 +40,11 @@ class RenameTagModal extends React.Component { handleInputKeyDown (e) { switch (e.keyCode) { case 13: - this.handleConfirmButtonClick() + this.handleConfirm() } } - handleConfirmButtonClick (e) { + handleConfirm () { if (this.state.name.trim().length > 0) { const { name, oldName } = this.state this.renameTag(oldName, name) @@ -101,7 +101,7 @@ class RenameTagModal extends React.Component { onKeyDown={(e) => this.handleInputKeyDown(e)} /> From e985f1226a342b7a77190ec9c5a6832eae38ab25 Mon Sep 17 00:00:00 2001 From: Khaliq Gant Date: Sat, 11 May 2019 15:51:19 +0200 Subject: [PATCH 04/11] use close prop instead of a new method --- browser/main/modals/RenameTagModal.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/main/modals/RenameTagModal.js b/browser/main/modals/RenameTagModal.js index 978bb2ee9..f16dc68cb 100644 --- a/browser/main/modals/RenameTagModal.js +++ b/browser/main/modals/RenameTagModal.js @@ -21,8 +21,6 @@ class RenameTagModal extends React.Component { this.refs.name.select() } - handleCloseButtonClick (e) { - this.props.close() } handleChange (e) { @@ -82,6 +80,8 @@ class RenameTagModal extends React.Component { } render () { + const { close } = this.props + return (
{i18n.__('Rename Tag')}
- this.handleCloseButtonClick(e)} /> +
Date: Sat, 11 May 2019 15:52:13 +0200 Subject: [PATCH 05/11] use callback ref instead of legacy string refs --- browser/main/modals/RenameTagModal.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/browser/main/modals/RenameTagModal.js b/browser/main/modals/RenameTagModal.js index f16dc68cb..c1ab2e343 100644 --- a/browser/main/modals/RenameTagModal.js +++ b/browser/main/modals/RenameTagModal.js @@ -10,6 +10,11 @@ class RenameTagModal extends React.Component { constructor (props) { super(props) + this.nameInput = null + this.setTextInputRef = el => { + this.nameInput = el + } + this.state = { name: props.tagName, oldName: props.tagName @@ -17,15 +22,13 @@ class RenameTagModal extends React.Component { } componentDidMount () { - this.refs.name.focus() - this.refs.name.select() - } - + this.nameInput.focus() + this.nameInput.select() } handleChange (e) { this.setState({ - name: this.refs.name.value + name: this.nameInput.value }) } @@ -95,7 +98,7 @@ class RenameTagModal extends React.Component {
this.handleChange(e)} onKeyDown={(e) => this.handleInputKeyDown(e)} From ce5d4acc11f3c436a5e915510bfb5720ae67ac54 Mon Sep 17 00:00:00 2001 From: Khaliq Gant Date: Sat, 11 May 2019 15:53:08 +0200 Subject: [PATCH 06/11] bind the handleChange in the constructor to allow for direct function assignment --- browser/main/modals/RenameTagModal.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/browser/main/modals/RenameTagModal.js b/browser/main/modals/RenameTagModal.js index c1ab2e343..e6a4795c3 100644 --- a/browser/main/modals/RenameTagModal.js +++ b/browser/main/modals/RenameTagModal.js @@ -11,6 +11,9 @@ class RenameTagModal extends React.Component { super(props) this.nameInput = null + + this.handleChange = this.handleChange.bind(this) + this.setTextInputRef = el => { this.nameInput = el } @@ -100,7 +103,7 @@ class RenameTagModal extends React.Component { placeholder={i18n.__('Tag Name')} ref={this.setTextInputRef} value={this.state.name} - onChange={(e) => this.handleChange(e)} + onChange={this.handleChange} onKeyDown={(e) => this.handleInputKeyDown(e)} />
) } From c0d22dbfb89405e076a8c816515b0f3f9dcbd16a Mon Sep 17 00:00:00 2001 From: Khaliq Gant Date: Sun, 15 Sep 2019 10:13:31 +0200 Subject: [PATCH 11/11] lint fix, const over let --- browser/main/Detail/TagSelect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/Detail/TagSelect.js b/browser/main/Detail/TagSelect.js index df6612d20..6b6a122a2 100644 --- a/browser/main/Detail/TagSelect.js +++ b/browser/main/Detail/TagSelect.js @@ -100,7 +100,7 @@ class TagSelect extends React.Component { } handleRenameTag (event, tagChange) { - let { value } = this.props + const { value } = this.props const { tag, updatedTag } = tagChange const newTags = value.slice()