From fd2582dc51f7950d1915002bdb996e8e79ad28da Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 4 Mar 2019 12:52:12 +0100 Subject: [PATCH 1/6] install copy-to-clipboard --- package.json | 1 + yarn.lock | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index dd497c11..7892ff0f 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "color-hash": "^1.0.3", "commander": "^2.19.0", "connected-react-router": "6.0.0", + "copy-to-clipboard": "^3.0.8", "copy-webpack-plugin": "^4.6.0", "cross-env": "^5.2.0", "date-fns": "^1.30.1", diff --git a/yarn.lock b/yarn.lock index 6a7b9236..ff9c1bd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -725,7 +725,7 @@ pirates "^4.0.0" source-map-support "^0.5.9" -"@babel/runtime@^7.0.0": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.3.1": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== @@ -745,13 +745,6 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.3.1": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" - integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== - dependencies: - regenerator-runtime "^0.12.0" - "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" @@ -3059,6 +3052,13 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" +copy-to-clipboard@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9" + integrity sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw== + dependencies: + toggle-selection "^1.0.3" + copy-webpack-plugin@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz#e7f40dd8a68477d405dd1b7a854aae324b158bae" @@ -10640,6 +10640,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toggle-selection@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= + toposort@^1.0.0: version "1.0.7" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" From 0add59669bf4a7ce20ff70f8a1605b46bc8dcfde Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 4 Mar 2019 12:52:26 +0100 Subject: [PATCH 2/6] add copy log to clipboard button --- src/actions/LogActions.js | 17 ++++++++++++++ src/actions/constants/log.js | 3 ++- src/components/Log/index.js | 34 +++++++++++++++++++++++++++- src/components/Log/index.messages.js | 8 +++++++ src/components/Tooltip/index.js | 3 +++ src/reducers/LogReducer.js | 9 ++++++++ 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/actions/LogActions.js b/src/actions/LogActions.js index 5e1bf6a7..a6fd8427 100644 --- a/src/actions/LogActions.js +++ b/src/actions/LogActions.js @@ -1,6 +1,7 @@ /* @flow */ import * as LOG from 'actions/constants/log'; +import copy from 'copy-to-clipboard'; import type { Action, ThunkAction, GetState, Dispatch, @@ -11,6 +12,8 @@ export type LogAction = { type: typeof LOG.OPEN, } | { type: typeof LOG.CLOSE, +} | { + type: typeof LOG.COPY_SUCCESS, } | { type: typeof LOG.ADD, payload: LogEntry @@ -38,3 +41,17 @@ export const add = (type: string, message: any): Action => ({ message, }, }); + +export const copyToClipboard = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { + const { entries } = getState().log; + try { + const res = copy(JSON.stringify(entries)); + if (res) { + dispatch({ + type: LOG.COPY_SUCCESS, + }); + } + } catch (err) { + console.error(err); + } +}; diff --git a/src/actions/constants/log.js b/src/actions/constants/log.js index a08a84cf..c666cbba 100644 --- a/src/actions/constants/log.js +++ b/src/actions/constants/log.js @@ -3,4 +3,5 @@ export const OPEN: 'log__open' = 'log__open'; export const CLOSE: 'log__close' = 'log__close'; -export const ADD: 'log__add' = 'log__add'; \ No newline at end of file +export const ADD: 'log__add' = 'log__add'; +export const COPY_SUCCESS: 'log__copy_success' = 'log__copy_success'; \ No newline at end of file diff --git a/src/components/Log/index.js b/src/components/Log/index.js index 1b3c4125..8829f6c7 100644 --- a/src/components/Log/index.js +++ b/src/components/Log/index.js @@ -5,6 +5,8 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import colors from 'config/colors'; import { H2 } from 'components/Heading'; +import Button from 'components/Button'; +import Tooltip from 'components/Tooltip'; import ReactJson from 'react-json-view'; import Icon from 'components/Icon'; import P from 'components/Paragraph'; @@ -18,7 +20,8 @@ import l10nMessages from './index.messages'; type Props = { log: $ElementType, - toggle: typeof LogActions.toggle + toggle: typeof LogActions.toggle, + copyToClipboard: typeof LogActions.copyToClipboard } const Wrapper = styled.div` @@ -60,8 +63,22 @@ const LogWrapper = styled.div` overflow: scroll; `; +const CopyWrapper = styled.div` +`; + +const ButtonCopy = styled(Button)` + margin-top: 10px; + max-width: 200px; +`; + const Log = (props: Props): ?React$Element => { if (!props.log.opened) return null; + + const copyBtn = ( + props.copyToClipboard()}> + + + ); return ( @@ -76,6 +93,20 @@ const Log = (props: Props): ?React$Element => { + {props.log.copied ? ( + } + > + + {copyBtn} + + ) : ( + {copyBtn} + ) + } ); }; @@ -86,5 +117,6 @@ export default connect( }), (dispatch: Dispatch) => ({ toggle: bindActionCreators(LogActions.toggle, dispatch), + copyToClipboard: bindActionCreators(LogActions.copyToClipboard, dispatch), }), )(Log); \ No newline at end of file diff --git a/src/components/Log/index.messages.js b/src/components/Log/index.messages.js index f0dd2940..6a4d6920 100644 --- a/src/components/Log/index.messages.js +++ b/src/components/Log/index.messages.js @@ -12,6 +12,14 @@ const definedMessages: Messages = defineMessages({ defaultMessage: 'Log', description: 'application event and error', }, + TR_COPY_TO_CLIPBOARD: { + id: 'TR_COPY_TO_CLIPBOARD', + defaultMessage: 'Copy to clipboard', + }, + TR_COPIED: { + id: 'TR_COPIED', + defaultMessage: 'Copied!', + }, }); export default definedMessages; \ No newline at end of file diff --git a/src/components/Tooltip/index.js b/src/components/Tooltip/index.js index 3186f2a7..a0658e29 100644 --- a/src/components/Tooltip/index.js +++ b/src/components/Tooltip/index.js @@ -34,12 +34,14 @@ const Tooltip = ({ readMoreLink, children, enterDelayMs, + defaultVisible = false, }) => ( } placement={placement} mouseEnterDelay={enterDelayMs || 0} + defaultVisible={defaultVisible} overlay={() => ( {content} @@ -71,6 +73,7 @@ Tooltip.propTypes = { ]), readMoreLink: PropTypes.string, enterDelayMs: PropTypes.number, + defaultVisible: PropTypes.bool, }; export default Tooltip; diff --git a/src/reducers/LogReducer.js b/src/reducers/LogReducer.js index ac5998e7..2cf643be 100644 --- a/src/reducers/LogReducer.js +++ b/src/reducers/LogReducer.js @@ -12,11 +12,13 @@ export type LogEntry = { export type State = { opened: boolean; entries: Array; + copied: boolean } export const initialState: State = { opened: false, entries: [], + copied: false, }; @@ -32,6 +34,7 @@ export default (state: State = initialState, action: Action): State => { return { ...state, opened: false, + copied: false, }; case LOG.ADD: @@ -40,6 +43,12 @@ export default (state: State = initialState, action: Action): State => { entries: state.entries.concat([action.payload]), }; + case LOG.COPY_SUCCESS: + return { + ...state, + copied: true, + }; + default: return state; } From f47fddf1f864eb41c1c2c65f94c40f2b182d0903 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 4 Mar 2019 12:55:21 +0100 Subject: [PATCH 3/6] remove button max width --- src/components/Log/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Log/index.js b/src/components/Log/index.js index 8829f6c7..54bcdb02 100644 --- a/src/components/Log/index.js +++ b/src/components/Log/index.js @@ -68,7 +68,6 @@ const CopyWrapper = styled.div` const ButtonCopy = styled(Button)` margin-top: 10px; - max-width: 200px; `; const Log = (props: Props): ?React$Element => { From 05e6ff4975bb9a085fafd2e2d8a9a5f63ffb441c Mon Sep 17 00:00:00 2001 From: Vladimir Volek Date: Mon, 4 Mar 2019 14:03:53 +0100 Subject: [PATCH 4/6] merge missing file --- src/reducers/LogReducer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/reducers/LogReducer.js b/src/reducers/LogReducer.js index 84b75be9..1473f320 100644 --- a/src/reducers/LogReducer.js +++ b/src/reducers/LogReducer.js @@ -10,10 +10,10 @@ export type LogEntry = { }; export type State = { - opened: boolean; - entries: Array; - copied: boolean -} + opened: boolean, + entries: Array, + copied: boolean, +}; export const initialState: State = { opened: false, From 6e7200dcf4c65713d7661e1954408a67355f9c19 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 4 Mar 2019 15:36:04 +0100 Subject: [PATCH 5/6] hide "copied!" message --- src/actions/LogActions.js | 6 ++++++ src/actions/constants/log.js | 3 ++- src/components/Log/index.js | 5 ++++- src/components/Tooltip/index.js | 2 ++ src/reducers/LogReducer.js | 6 ++++++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/actions/LogActions.js b/src/actions/LogActions.js index a6fd8427..b81d181c 100644 --- a/src/actions/LogActions.js +++ b/src/actions/LogActions.js @@ -12,6 +12,8 @@ export type LogAction = { type: typeof LOG.OPEN, } | { type: typeof LOG.CLOSE, +} | { + type: typeof LOG.COPY_RESET, } | { type: typeof LOG.COPY_SUCCESS, } | { @@ -55,3 +57,7 @@ export const copyToClipboard = (): ThunkAction => (dispatch: Dispatch, getState: console.error(err); } }; + +export const resetCopyState = (): Action => ({ + type: LOG.COPY_RESET, +}); diff --git a/src/actions/constants/log.js b/src/actions/constants/log.js index c666cbba..c9f163f3 100644 --- a/src/actions/constants/log.js +++ b/src/actions/constants/log.js @@ -4,4 +4,5 @@ export const OPEN: 'log__open' = 'log__open'; export const CLOSE: 'log__close' = 'log__close'; export const ADD: 'log__add' = 'log__add'; -export const COPY_SUCCESS: 'log__copy_success' = 'log__copy_success'; \ No newline at end of file +export const COPY_SUCCESS: 'log__copy_success' = 'log__copy_success'; +export const COPY_RESET: 'log__copy_reset' = 'log__copy_reset'; \ No newline at end of file diff --git a/src/components/Log/index.js b/src/components/Log/index.js index 54bcdb02..37d2179c 100644 --- a/src/components/Log/index.js +++ b/src/components/Log/index.js @@ -21,7 +21,8 @@ import l10nMessages from './index.messages'; type Props = { log: $ElementType, toggle: typeof LogActions.toggle, - copyToClipboard: typeof LogActions.copyToClipboard + copyToClipboard: typeof LogActions.copyToClipboard, + resetCopyState: typeof LogActions.resetCopyState, } const Wrapper = styled.div` @@ -98,6 +99,7 @@ const Log = (props: Props): ?React$Element => { maxWidth={285} placement="top" content={} + afterVisibleChange={props.resetCopyState} > {copyBtn} @@ -117,5 +119,6 @@ export default connect( (dispatch: Dispatch) => ({ toggle: bindActionCreators(LogActions.toggle, dispatch), copyToClipboard: bindActionCreators(LogActions.copyToClipboard, dispatch), + resetCopyState: bindActionCreators(LogActions.resetCopyState, dispatch), }), )(Log); \ No newline at end of file diff --git a/src/components/Tooltip/index.js b/src/components/Tooltip/index.js index a0658e29..b2be7b85 100644 --- a/src/components/Tooltip/index.js +++ b/src/components/Tooltip/index.js @@ -35,6 +35,7 @@ const Tooltip = ({ children, enterDelayMs, defaultVisible = false, + ...rest }) => ( )} + {...rest} > {children} diff --git a/src/reducers/LogReducer.js b/src/reducers/LogReducer.js index 2cf643be..4d71067d 100644 --- a/src/reducers/LogReducer.js +++ b/src/reducers/LogReducer.js @@ -49,6 +49,12 @@ export default (state: State = initialState, action: Action): State => { copied: true, }; + case LOG.COPY_RESET: + return { + ...state, + copied: false, + }; + default: return state; } From 8f2f2d0bc781fbec535790d5132b7252a55e3ca9 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 4 Mar 2019 15:48:35 +0100 Subject: [PATCH 6/6] fix prettier --- src/actions/LogActions.js | 2 +- src/actions/constants/log.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/actions/LogActions.js b/src/actions/LogActions.js index b2ea6ea2..eaac6597 100644 --- a/src/actions/LogActions.js +++ b/src/actions/LogActions.js @@ -14,7 +14,7 @@ export type LogAction = type: typeof LOG.CLOSE, } | { - type: typeof LOG.COPY_RESET, + type: typeof LOG.COPY_RESET, } | { type: typeof LOG.COPY_SUCCESS, diff --git a/src/actions/constants/log.js b/src/actions/constants/log.js index 3dad4e52..33b89731 100644 --- a/src/actions/constants/log.js +++ b/src/actions/constants/log.js @@ -5,4 +5,3 @@ export const CLOSE: 'log__close' = 'log__close'; export const ADD: 'log__add' = 'log__add'; export const COPY_SUCCESS: 'log__copy_success' = 'log__copy_success'; export const COPY_RESET: 'log__copy_reset' = 'log__copy_reset'; -