From 77089a1178b451ef733900f6652a231ced7e3c2b Mon Sep 17 00:00:00 2001 From: Matus Benko Date: Wed, 6 Sep 2017 20:02:47 +0200 Subject: [PATCH] extracted folder list and item to separate components --- .../modals/PreferencesModal/FolderItem.js | 276 ++++++++++++++++++ .../modals/PreferencesModal/FolderItem.styl | 94 ++++++ .../modals/PreferencesModal/FolderList.js | 52 ++++ .../modals/PreferencesModal/FolderList.styl | 0 .../modals/PreferencesModal/StorageItem.js | 276 +----------------- .../modals/PreferencesModal/StorageItem.styl | 94 ------ 6 files changed, 427 insertions(+), 365 deletions(-) create mode 100644 browser/main/modals/PreferencesModal/FolderItem.js create mode 100644 browser/main/modals/PreferencesModal/FolderItem.styl create mode 100644 browser/main/modals/PreferencesModal/FolderList.js create mode 100644 browser/main/modals/PreferencesModal/FolderList.styl diff --git a/browser/main/modals/PreferencesModal/FolderItem.js b/browser/main/modals/PreferencesModal/FolderItem.js new file mode 100644 index 00000000..35407406 --- /dev/null +++ b/browser/main/modals/PreferencesModal/FolderItem.js @@ -0,0 +1,276 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import ReactDOM from 'react-dom' +import styles from './FolderItem.styl' +import dataApi from 'browser/main/lib/dataApi' +import store from 'browser/main/store' +import { SketchPicker } from 'react-color' + +class FolderItem extends React.Component { + constructor (props) { + super(props) + + this.state = { + status: 'IDLE', + folder: { + showColumnPicker: false, + colorPickerPos: { left: 0, top: 0 }, + color: props.color, + name: props.name + } + } + } + + handleEditChange (e) { + let { folder } = this.state + + folder.name = this.refs.nameInput.value + this.setState({ + folder + }) + } + + handleConfirmButtonClick (e) { + this.confirm() + } + + confirm () { + let { storage, folder } = this.props + dataApi + .updateFolder(storage.key, folder.key, { + color: this.state.folder.color, + name: this.state.folder.name + }) + .then((data) => { + store.dispatch({ + type: 'UPDATE_FOLDER', + storage: data.storage + }) + this.setState({ + status: 'IDLE' + }) + }) + } + + handleColorButtonClick (e) { + const folder = Object.assign({}, this.state.folder, { showColumnPicker: true, colorPickerPos: { left: 0, top: 0 } }) + this.setState({ folder }, function () { + // After the color picker has been painted, re-calculate its position + // by comparing its dimensions to the host dimensions. + const { hostBoundingBox } = this.props + const colorPickerNode = ReactDOM.findDOMNode(this.refs.colorPicker) + const colorPickerBox = colorPickerNode.getBoundingClientRect() + const offsetTop = hostBoundingBox.bottom - colorPickerBox.bottom + const folder = Object.assign({}, this.state.folder, { + colorPickerPos: { + left: 25, + top: offsetTop < 0 ? offsetTop - 5 : 0 // subtract 5px for aestetics + } + }) + this.setState({ folder }) + }) + } + + handleColorChange (color) { + const folder = Object.assign({}, this.state.folder, { color: color.hex }) + this.setState({ folder }) + } + + handleColorPickerClose (event) { + const folder = Object.assign({}, this.state.folder, { showColumnPicker: false }) + this.setState({ folder }) + } + + handleCancelButtonClick (e) { + this.setState({ + status: 'IDLE' + }) + } + + handleFolderItemBlur (e) { + let el = e.relatedTarget + while (el != null) { + if (el === this.refs.root) { + return false + } + el = el.parentNode + } + this.confirm() + } + + renderEdit (e) { + const popover = { position: 'absolute', zIndex: 2 } + const cover = { + position: 'fixed', + top: 0, + right: 0, + bottom: 0, + left: 0 + } + const pickerStyle = Object.assign({}, { + position: 'absolute' + }, this.state.folder.colorPickerPos) + return ( +
this.handleFolderItemBlur(e)} + tabIndex='-1' + ref='root' + > +
+ + this.handleEditChange(e)} + /> +
+
+ + +
+
+ ) + } + + handleDeleteConfirmButtonClick (e) { + let { storage, folder } = this.props + dataApi + .deleteFolder(storage.key, folder.key) + .then((data) => { + store.dispatch({ + type: 'DELETE_FOLDER', + storage: data.storage, + folderKey: data.folderKey + }) + }) + } + + renderDelete () { + return ( +
+
+ Are you sure to delete this folder? +
+
+ + +
+
+ ) + } + + handleEditButtonClick (e) { + let { folder: propsFolder } = this.props + let { folder: stateFolder } = this.state + const folder = Object.assign({}, stateFolder, propsFolder) + this.setState({ + status: 'EDIT', + folder + }, () => { + this.refs.nameInput.select() + }) + } + + handleDeleteButtonClick (e) { + this.setState({ + status: 'DELETE' + }) + } + + renderIdle () { + let { folder } = this.props + return ( +
this.handleEditButtonClick(e)} + > +
+ {folder.name} + ({folder.key}) +
+
+ + +
+
+ ) + } + + render () { + switch (this.state.status) { + case 'DELETE': + return this.renderDelete() + case 'EDIT': + return this.renderEdit() + case 'IDLE': + default: + return this.renderIdle() + } + } +} + +FolderItem.propTypes = { + hostBoundingBox: PropTypes.shape({ + bottom: PropTypes.number, + height: PropTypes.number, + left: PropTypes.number, + right: PropTypes.number, + top: PropTypes.number, + width: PropTypes.number + }), + storage: PropTypes.shape({ + key: PropTypes.string + }), + folder: PropTypes.shape({ + key: PropTypes.string, + color: PropTypes.string, + name: PropTypes.string + }) +} + +export default CSSModules(FolderItem, styles) diff --git a/browser/main/modals/PreferencesModal/FolderItem.styl b/browser/main/modals/PreferencesModal/FolderItem.styl new file mode 100644 index 00000000..010e5ebb --- /dev/null +++ b/browser/main/modals/PreferencesModal/FolderItem.styl @@ -0,0 +1,94 @@ +.folderItem + height 35px + box-sizing border-box + padding 2.5px 15px + &:hover + background-color darken(white, 3%) +.folderItem-left + height 30px + border-left solid 2px transparent + padding 0 10px + line-height 30px + float left +.folderItem-left-danger + color $danger-color + font-weight bold + +.folderItem-left-key + color $ui-inactive-text-color + font-size 10px + margin 0 5px + border none + +.folderItem-left-colorButton + colorDefaultButton() + height 25px + width 25px + line-height 23px + padding 0 + box-sizing border-box + vertical-align middle + border $ui-border + border-radius 2px + margin-right 5px + margin-left -15px + +.folderItem-left-nameInput + height 25px + box-sizing border-box + vertical-align middle + border $ui-border + border-radius 2px + padding 0 5px + outline none + +.folderItem-right + float right + +.folderItem-right-button + vertical-align middle + height 25px + margin-top 2.5px + colorDefaultButton() + border-radius 2px + border $ui-border + margin-right 5px + padding 0 5px + &:last-child + margin-right 0 + +.folderItem-right-confirmButton + @extend .folderItem-right-button + border none + colorPrimaryButton() + +.folderItem-right-dangerButton + @extend .folderItem-right-button + border none + colorDangerButton() + +body[data-theme="dark"] + .folderItem + &:hover + background-color lighten($ui-dark-button--hover-backgroundColor, 5%) + + .folderItem-left-danger + color $danger-color + font-weight bold + + .folderItem-left-key + color $ui-dark-inactive-text-color + + .folderItem-left-colorButton + colorDarkDefaultButton() + border-color $ui-dark-borderColor + + .folderItem-right-button + colorDarkDefaultButton() + border-color $ui-dark-borderColor + + .folderItem-right-confirmButton + colorDarkPrimaryButton() + + .folderItem-right-dangerButton + colorDarkDangerButton() diff --git a/browser/main/modals/PreferencesModal/FolderList.js b/browser/main/modals/PreferencesModal/FolderList.js new file mode 100644 index 00000000..5d6010b9 --- /dev/null +++ b/browser/main/modals/PreferencesModal/FolderList.js @@ -0,0 +1,52 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './FolderList.styl' +import FolderItem from './FolderItem' + +class FolderList extends React.Component { + constructor (props) { + super(props) + } + + render () { + let { storage, hostBoundingBox } = this.props + + let folderList = storage.folders.map((folder) => { + return + }) + + return ( +
+ {folderList.length > 0 + ? folderList + :
No Folders
+ } +
+ ) + } +} + +FolderList.propTypes = { + hostBoundingBox: PropTypes.shape({ + bottom: PropTypes.number, + height: PropTypes.number, + left: PropTypes.number, + right: PropTypes.number, + top: PropTypes.number, + width: PropTypes.number + }), + storage: PropTypes.shape({ + key: PropTypes.string + }), + folder: PropTypes.shape({ + key: PropTypes.string, + color: PropTypes.string, + name: PropTypes.string + }) +} + +export default CSSModules(FolderList, styles) diff --git a/browser/main/modals/PreferencesModal/FolderList.styl b/browser/main/modals/PreferencesModal/FolderList.styl new file mode 100644 index 00000000..e69de29b diff --git a/browser/main/modals/PreferencesModal/StorageItem.js b/browser/main/modals/PreferencesModal/StorageItem.js index d3586f35..478e4c44 100644 --- a/browser/main/modals/PreferencesModal/StorageItem.js +++ b/browser/main/modals/PreferencesModal/StorageItem.js @@ -1,265 +1,13 @@ import React, { PropTypes } from 'react' -import ReactDOM from 'react-dom' import CSSModules from 'browser/lib/CSSModules' import styles from './StorageItem.styl' import consts from 'browser/lib/consts' import dataApi from 'browser/main/lib/dataApi' import store from 'browser/main/store' +import FolderList from './FolderList' const { shell, remote } = require('electron') const { dialog } = remote -import { SketchPicker } from 'react-color' - -class UnstyledFolderItem extends React.Component { - constructor (props) { - super(props) - - this.state = { - status: 'IDLE', - folder: { - showColumnPicker: false, - colorPickerPos: { left: 0, top: 0 }, - color: props.color, - name: props.name - } - } - } - - handleEditChange (e) { - let { folder } = this.state - - folder.name = this.refs.nameInput.value - this.setState({ - folder - }) - } - - handleConfirmButtonClick (e) { - this.confirm() - } - - confirm () { - let { storage, folder } = this.props - dataApi - .updateFolder(storage.key, folder.key, { - color: this.state.folder.color, - name: this.state.folder.name - }) - .then((data) => { - store.dispatch({ - type: 'UPDATE_FOLDER', - storage: data.storage - }) - this.setState({ - status: 'IDLE' - }) - }) - } - - handleColorButtonClick (e) { - const folder = Object.assign({}, this.state.folder, { showColumnPicker: true, colorPickerPos: { left: 0, top: 0 } }) - this.setState({ folder }, function () { - // After the color picker has been painted, re-calculate its position - // by comparing its dimensions to the host dimensions. - const { hostBoundingBox } = this.props - const colorPickerNode = ReactDOM.findDOMNode(this.refs.colorPicker) - const colorPickerBox = colorPickerNode.getBoundingClientRect() - const offsetTop = hostBoundingBox.bottom - colorPickerBox.bottom - const folder = Object.assign({}, this.state.folder, { - colorPickerPos: { - left: 25, - top: offsetTop < 0 ? offsetTop - 5 : 0 // subtract 5px for aestetics - } - }) - this.setState({ folder }) - }) - } - - handleColorChange (color) { - const folder = Object.assign({}, this.state.folder, { color: color.hex }) - this.setState({ folder }) - } - - handleColorPickerClose (event) { - const folder = Object.assign({}, this.state.folder, { showColumnPicker: false }) - this.setState({ folder }) - } - - handleCancelButtonClick (e) { - this.setState({ - status: 'IDLE' - }) - } - - handleFolderItemBlur (e) { - let el = e.relatedTarget - while (el != null) { - if (el === this.refs.root) { - return false - } - el = el.parentNode - } - this.confirm() - } - - renderEdit (e) { - const popover = { position: 'absolute', zIndex: 2 } - const cover = { - position: 'fixed', - top: 0, - right: 0, - bottom: 0, - left: 0 - } - const pickerStyle = Object.assign({}, { - position: 'absolute' - }, this.state.folder.colorPickerPos) - return ( -
this.handleFolderItemBlur(e)} - tabIndex='-1' - ref='root' - > -
- - this.handleEditChange(e)} - /> -
-
- - -
-
- ) - } - - handleDeleteConfirmButtonClick (e) { - let { storage, folder } = this.props - dataApi - .deleteFolder(storage.key, folder.key) - .then((data) => { - store.dispatch({ - type: 'DELETE_FOLDER', - storage: data.storage, - folderKey: data.folderKey - }) - }) - } - - renderDelete () { - return ( -
-
- Are you sure to delete this folder? -
-
- - -
-
- ) - } - - handleEditButtonClick (e) { - let { folder: propsFolder } = this.props - let { folder: stateFolder } = this.state - const folder = Object.assign({}, stateFolder, propsFolder) - this.setState({ - status: 'EDIT', - folder - }, () => { - this.refs.nameInput.select() - }) - } - - handleDeleteButtonClick (e) { - this.setState({ - status: 'DELETE' - }) - } - - renderIdle () { - let { folder } = this.props - return ( -
this.handleEditButtonClick(e)} - > -
- {folder.name} - ({folder.key}) -
-
- - -
-
- - ) - } - - render () { - switch (this.state.status) { - case 'DELETE': - return this.renderDelete() - case 'EDIT': - return this.renderEdit() - case 'IDLE': - default: - return this.renderIdle() - } - } -} - -const FolderItem = CSSModules(UnstyledFolderItem, styles) class StorageItem extends React.Component { constructor (props) { @@ -349,13 +97,7 @@ class StorageItem extends React.Component { render () { let { storage, hostBoundingBox } = this.props - let folderList = storage.folders.map((folder) => { - return - }) + return (
@@ -404,12 +146,9 @@ class StorageItem extends React.Component {
-
- {folderList.length > 0 - ? folderList - :
No Folders
- } -
+ ) } @@ -426,11 +165,6 @@ StorageItem.propTypes = { }), storage: PropTypes.shape({ key: PropTypes.string - }), - folder: PropTypes.shape({ - key: PropTypes.string, - color: PropTypes.string, - name: PropTypes.string }) } diff --git a/browser/main/modals/PreferencesModal/StorageItem.styl b/browser/main/modals/PreferencesModal/StorageItem.styl index 538edfb8..13759007 100644 --- a/browser/main/modals/PreferencesModal/StorageItem.styl +++ b/browser/main/modals/PreferencesModal/StorageItem.styl @@ -63,75 +63,6 @@ z-index 10 white-space nowrap -.folderList-item - height 35px - box-sizing border-box - padding 2.5px 15px - &:hover - background-color darken(white, 3%) -.folderList-item-left - height 30px - border-left solid 2px transparent - padding 0 10px - line-height 30px - float left -.folderList-item-left-danger - color $danger-color - font-weight bold - -.folderList-item-left-key - color $ui-inactive-text-color - font-size 10px - margin 0 5px - border none - -.folderList-item-left-colorButton - colorDefaultButton() - height 25px - width 25px - line-height 23px - padding 0 - box-sizing border-box - vertical-align middle - border $ui-border - border-radius 2px - margin-right 5px - margin-left -15px - -.folderList-item-left-nameInput - height 25px - box-sizing border-box - vertical-align middle - border $ui-border - border-radius 2px - padding 0 5px - outline none - -.folderList-item-right - float right - -.folderList-item-right-button - vertical-align middle - height 25px - margin-top 2.5px - colorDefaultButton() - border-radius 2px - border $ui-border - margin-right 5px - padding 0 5px - &:last-child - margin-right 0 - -.folderList-item-right-confirmButton - @extend .folderList-item-right-button - border none - colorPrimaryButton() - -.folderList-item-right-dangerButton - @extend .folderList-item-right-button - border none - colorDangerButton() - body[data-theme="dark"] .header border-color $ui-dark-borderColor @@ -153,28 +84,3 @@ body[data-theme="dark"] top 25px z-index 10 white-space nowrap - - .folderList-item - &:hover - background-color lighten($ui-dark-button--hover-backgroundColor, 5%) - - .folderList-item-left-danger - color $danger-color - font-weight bold - - .folderList-item-left-key - color $ui-dark-inactive-text-color - - .folderList-item-left-colorButton - colorDarkDefaultButton() - border-color $ui-dark-borderColor - - .folderList-item-right-button - colorDarkDefaultButton() - border-color $ui-dark-borderColor - - .folderList-item-right-confirmButton - colorDarkPrimaryButton() - - .folderList-item-right-dangerButton - colorDarkDangerButton()