Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4428963
allow a tag to be renamed and update all notes that use that tag
khaliqgant May 3, 2019
242e8b6
call handleConfirmButtonClick directly instead of sending through a c…
khaliqgant May 5, 2019
0f6e218
better name for method to confirm the rename
khaliqgant May 5, 2019
5873e50
Merge branch 'master' of https://github.com/BoostIO/Boostnote into 17…
khaliqgant May 11, 2019
e985f12
use close prop instead of a new method
khaliqgant May 11, 2019
b1d62c8
use callback ref instead of legacy string refs
khaliqgant May 11, 2019
ce5d4ac
bind the handleChange in the constructor to allow for direct function…
khaliqgant May 11, 2019
7c5077b
update the tag in the URL upon change
khaliqgant May 11, 2019
d2c329a
use the eventEmitter to update the tags in the SnippetNoteDetail head…
khaliqgant May 11, 2019
e2f0692
Merge branch 'master' of https://github.com/BoostIO/Boostnote into 17…
khaliqgant May 24, 2019
e493a83
Merge branch 'master' of https://github.com/BoostIO/Boostnote into 17…
khaliqgant Sep 15, 2019
9a2dcbc
respect themes when modal is opened
khaliqgant Sep 15, 2019
4efbe08
show error message when trying to rename to an existing tag
khaliqgant Sep 15, 2019
c0d22db
lint fix, const over let
khaliqgant Sep 15, 2019
a4532f1
add missing letter
AWolf81 Feb 14, 2020
686376a
fix routing and add merge warning dialog
AWolf81 Feb 14, 2020
2b56a11
Merge branch 'master' into 1706-tag-rename
AWolf81 Feb 14, 2020
d4ca69a
fix space-before-parens lint error
AWolf81 Feb 15, 2020
d2b48f4
change theming
AWolf81 Mar 27, 2020
de3cd71
add check if tag changed
AWolf81 Mar 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions browser/main/Detail/TagSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class TagSelect extends React.Component {
}

this.handleAddTag = this.handleAddTag.bind(this)
this.handleRenameTag = this.handleRenameTag.bind(this)
this.onInputBlur = this.onInputBlur.bind(this)
this.onInputChange = this.onInputChange.bind(this)
this.onInputKeyDown = this.onInputKeyDown.bind(this)
Expand Down Expand Up @@ -88,6 +89,7 @@ class TagSelect extends React.Component {
this.buildSuggestions()

ee.on('editor:add-tag', this.handleAddTag)
ee.on('sidebar:rename-tag', this.handleRenameTag)
}

componentDidUpdate() {
Expand All @@ -96,12 +98,23 @@ class TagSelect extends React.Component {

componentWillUnmount() {
ee.off('editor:add-tag', this.handleAddTag)
ee.off('sidebar:rename-tag', this.handleRenameTag)
}

handleAddTag() {
this.refs.newTag.input.focus()
}

handleRenameTag(event, tagChange) {
const { value } = this.props
const { tag, updatedTag } = tagChange
const newTags = value.slice()

newTags[value.indexOf(tag)] = updatedTag
this.value = newTags
this.props.onChange()
}

handleTagLabelClick(tag) {
const { dispatch } = this.props

Expand Down
16 changes: 16 additions & 0 deletions browser/main/SideNav/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,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'
Expand Down Expand Up @@ -170,6 +171,11 @@ class SideNav extends React.Component {
)
})

menu.push({
label: i18n.__('Rename Tag'),
click: this.handleRenameTagClick.bind(this, tag)
})

context.popup(menu)
}

Expand All @@ -193,6 +199,16 @@ class SideNav extends React.Component {
})
}

handleRenameTagClick(tagName) {
const { data, dispatch } = this.props

openModal(RenameTagModal, {
tagName,
data,
dispatch
})
}

handleColorPickerConfirm(color) {
const {
dispatch,
Expand Down
2 changes: 1 addition & 1 deletion browser/main/modals/RenameFolderModal.js
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,18 @@
font-size 14px
colorPrimaryButton()

.error
text-align center
color #F44336
height 20px

apply-theme(theme)
body[data-theme={theme}]
.root
background-color transparent

.header
background-color get-theme-var(theme, 'button--hover-backgroundColor')
background-color transparent
border-color get-theme-var(theme, 'borderColor')
color get-theme-var(theme, 'text-color')

Expand Down
196 changes: 196 additions & 0 deletions browser/main/modals/RenameTagModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
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'
import { replace } from 'connected-react-router'
import ee from 'browser/main/lib/eventEmitter'
import { isEmpty } from 'lodash'
import electron from 'electron'

const { remote } = electron
const { dialog } = remote

class RenameTagModal extends React.Component {
constructor(props) {
super(props)

this.nameInput = null

this.handleChange = this.handleChange.bind(this)

this.setTextInputRef = el => {
this.nameInput = el
}

this.state = {
name: props.tagName,
oldName: props.tagName
}
}

componentDidMount() {
this.nameInput.focus()
this.nameInput.select()
}

handleChange(e) {
this.setState({
name: this.nameInput.value,
showerror: false,
errormessage: ''
})
}

handleKeyDown(e) {
if (e.keyCode === 27) {
this.props.close()
}
}

handleInputKeyDown(e) {
switch (e.keyCode) {
case 13:
this.handleConfirm()
}
}

handleConfirm() {
if (this.state.name.trim().length > 0) {
const { name, oldName } = this.state
this.renameTag(oldName, name)
}
}

showError(message) {
this.setState({
showerror: true,
errormessage: message
})
}

renameTag(tag, updatedTag) {
const { data, dispatch } = this.props

if (tag === updatedTag) {
// confirm with-out any change - just dismiss the modal
this.props.close()
return
}

if (
data.noteMap
.map(note => note)
.some(note => note.tags.indexOf(updatedTag) !== -1)
) {
const alertConfig = {
type: 'warning',
message: i18n.__('Confirm tag merge'),
detail: i18n.__(
`Tag ${tag} will be merged with existing tag ${updatedTag}`
),
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
}

const dialogButtonIndex = dialog.showMessageBox(
remote.getCurrentWindow(),
alertConfig
)

if (dialogButtonIndex === 1) {
return // bail early on cancel click
}
}

const notes = data.noteMap
.map(note => note)
.filter(
note => note.tags.indexOf(tag) !== -1 && note.tags.indexOf(updatedTag)
)
.map(note => {
note = Object.assign({}, note)
note.tags = note.tags.slice()

note.tags[note.tags.indexOf(tag)] = updatedTag

return note
})

if (isEmpty(notes)) {
this.showError(i18n.__('Tag exists'))

return
}

Promise.all(
notes.map(note => dataApi.updateNote(note.storage, note.key, note))
)
.then(updatedNotes => {
updatedNotes.forEach(note => {
dispatch({
type: 'UPDATE_NOTE',
note
})
})
})
.then(() => {
if (window.location.hash.includes(tag)) {
dispatch(replace(`/tags/${updatedTag}`))
}
ee.emit('sidebar:rename-tag', { tag, updatedTag })
this.props.close()
})
}

render() {
const { close } = this.props
const { errormessage } = this.state

return (
<div
styleName='root'
tabIndex='-1'
onKeyDown={e => this.handleKeyDown(e)}
>
<div styleName='header'>
<div styleName='title'>{i18n.__('Rename Tag')}</div>
</div>
<ModalEscButton handleEscButtonClick={close} />

<div styleName='control'>
<input
styleName='control-input'
placeholder={i18n.__('Tag Name')}
ref={this.setTextInputRef}
value={this.state.name}
onChange={this.handleChange}
onKeyDown={e => this.handleInputKeyDown(e)}
/>
<button
styleName='control-confirmButton'
onClick={() => this.handleConfirm()}
>
{i18n.__('Confirm')}
</button>
</div>
<div className='error' styleName='error'>
{errormessage}
</div>
</div>
)
}
}

RenameTagModal.propTypes = {
storage: PropTypes.shape({
key: PropTypes.string
}),
folder: PropTypes.shape({
key: PropTypes.string,
name: PropTypes.string
})
}

export default CSSModules(RenameTagModal, styles)